Count MMS rate by 10-chunks

Phillip Davis created

Change summary

lib/blather_ext.rb          |  2 
lib/customer_usage.rb       |  3 
sgx_jmp.rb                  |  7 +-
test/test_customer_usage.rb | 95 +++++++++++++++++++++++++++++++++++++++
4 files changed, 103 insertions(+), 4 deletions(-)

Detailed changes

lib/blather_ext.rb 🔗

@@ -3,6 +3,8 @@
 require "securerandom"
 
 module Blather
+	ADDRESSES_NS = "http://jabber.org/protocol/address"
+
 	class JID
 		def with(node: self.node, domain: self.domain, resource: self.resource)
 			self.class.new(node, domain, resource)

lib/customer_usage.rb 🔗

@@ -28,7 +28,8 @@ class CustomerUsage
 		)
 	end
 
-	def incr_message_usage(amount=1, body=nil)
+	def incr_message_usage(recipients:, body: nil)
+		amount = recipients.each_slice(10).count
 		today = Time.now.utc.to_date
 		EMPromise.all([
 			expire_message_usage,

sgx_jmp.rb 🔗

@@ -291,7 +291,6 @@ before nil, to: /\Acustomer_/, from: /(\A|@)#{FROM_BACKEND}(\/|\Z)/ do |s|
 	halt
 end
 
-ADDRESSES_NS = "http://jabber.org/protocol/address"
 message(
 	to: /\A#{CONFIG[:component][:jid]}\Z/,
 	from: /(\A|@)#{FROM_BACKEND}(\/|\Z)/
@@ -427,10 +426,12 @@ message do |m|
 		next customer.stanza_from(m) unless billable_message(m)
 
 		expired_guard(customer)
-
 		EMPromise.all([
 			TrustLevelRepo.new.find(customer),
-			customer.incr_message_usage(1, m.body)
+			customer.incr_message_usage(
+				recipients: m.addresses.to_a,
+				body: m.body
+			)
 		]).then { |(tl, usage)|
 			usage_guard(m, m.to.node.to_s, customer, tl, usage)
 		}.then do

test/test_customer_usage.rb 🔗

@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+require "customer_usage"
+
+CustomerUsage::REDIS = Minitest::Mock.new
+
+class CustomerUsageTest < Minitest::Test
+	def setup
+		@customer_usage = CustomerUsage.new("customer")
+	end
+
+	def test_incr_message_usage_counts_ten_recipients_as_one_message
+		CustomerUsage::REDIS.expect(:zremrangebylex, []) do |*args|
+			cust_key, dash, * = args
+			assert_equal "jmp_customer_outbound_messages-customer", cust_key
+			assert_equal "-", dash
+		end
+		CustomerUsage::REDIS.expect(:zincrby, 1) do |*args|
+			cust_key, amount, * = args
+			assert_equal "jmp_customer_outbound_messages-customer", cust_key
+			assert_equal 1, amount
+		end
+
+		result = @customer_usage.incr_message_usage(
+			recipients: Array.new(10) { |i| "#{i}@example.com" }
+		).sync
+
+		assert_equal result, { today: 1, body: 0 }
+		CustomerUsage::REDIS.verify
+	end
+	em :test_incr_message_usage_counts_ten_recipients_as_one_message
+
+	def test_incr_message_usage_counts_nine_recipients_as_one_message
+		CustomerUsage::REDIS.expect(:zremrangebylex, []) do |*args|
+			cust_key, dash, * = args
+			assert_equal "jmp_customer_outbound_messages-customer", cust_key
+			assert_equal "-", dash
+		end
+		CustomerUsage::REDIS.expect(:zincrby, 1) do |*args|
+			cust_key, amount, * = args
+			assert_equal "jmp_customer_outbound_messages-customer", cust_key
+			assert_equal 1, amount
+		end
+
+		result = @customer_usage.incr_message_usage(
+			recipients: Array.new(9) { |i| "#{i}@example.com" }
+		).sync
+
+		assert_equal result, { today: 1, body: 0 }
+		CustomerUsage::REDIS.verify
+	end
+	em :test_incr_message_usage_counts_nine_recipients_as_one_message
+
+	def test_incr_message_usage
+		CustomerUsage::REDIS.expect(:zremrangebylex, []) do |*args|
+			cust_key, dash, * = args
+			assert_equal "jmp_customer_outbound_messages-customer", cust_key
+			assert_equal "-", dash
+		end
+		CustomerUsage::REDIS.expect(:zincrby, 2) do |*args|
+			cust_key, amount, * = args
+			assert_equal "jmp_customer_outbound_messages-customer", cust_key
+			assert_equal 2, amount
+		end
+
+		# Literally no way to make this fit
+		# rubocop:disable Metrics/LineLength
+		expected_key = "jmp_outbound_body-dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f"
+		# rubocop:enable Metrics/LineLength
+
+		CustomerUsage::REDIS.expect(:incrby, 2) do |*args|
+			body_key, amount = args
+			assert_equal body_key, expected_key
+			assert_equal amount, 2
+		end
+
+		CustomerUsage::REDIS.expect(:expire, 2) do |*args|
+			body_key, timeout = args
+
+			assert_equal body_key, expected_key
+			assert_equal timeout, 180
+		end
+
+		result = @customer_usage.incr_message_usage(
+			recipients: Array.new(11) { |i| "#{i}@example.com" },
+			body: "Hello, World!"
+		).sync
+
+		assert_equal result, { today: 2, body: 2 }
+		CustomerUsage::REDIS.verify
+	end
+	em :test_incr_message_usage
+end