@@ -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)
@@ -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,
@@ -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
@@ -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