From 3b7abebd4df7b8508edd310704b098095c3e17a7 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Tue, 29 Mar 2022 15:45:50 -0500 Subject: [PATCH] Allow the DB to notify us to bill a customer --- lib/db_notification.rb | 17 +++++++++++++++++ lib/dummy_command.rb | 17 +++++++++++++++++ sgx_jmp.rb | 28 +++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 lib/db_notification.rb create mode 100644 lib/dummy_command.rb diff --git a/lib/db_notification.rb b/lib/db_notification.rb new file mode 100644 index 0000000..d9b7f1f --- /dev/null +++ b/lib/db_notification.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require_relative "dummy_command" + +module DbNotification + def self.for(notify, customer) + case notify[:relname] + when "low_balance" + LowBalance.for(customer).then { |lb| lb.method(:notify!) } + when "possible_renewal" + Command.execution = DummyCommand.new(customer) + BillPlanCommand.for(customer) + else + raise "Unknown notification: #{notify[:relname]}" + end + end +end diff --git a/lib/dummy_command.rb b/lib/dummy_command.rb new file mode 100644 index 0000000..7df14ce --- /dev/null +++ b/lib/dummy_command.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class DummyCommand + attr_reader :customer + + def initialize(customer) + @customer = customer + end + + def reply(*); end + + def finish(*); end + + def log + ::LOG + end +end diff --git a/sgx_jmp.rb b/sgx_jmp.rb index 7891cd9..cc2b045 100644 --- a/sgx_jmp.rb +++ b/sgx_jmp.rb @@ -81,6 +81,8 @@ require_relative "lib/command_list" require_relative "lib/customer" require_relative "lib/customer_info_form" require_relative "lib/customer_repo" +require_relative "lib/dummy_command" +require_relative "lib/db_notification" require_relative "lib/electrum" require_relative "lib/empty_repo" require_relative "lib/expiring_lock" @@ -178,10 +180,27 @@ end EM.error_handler(&method(:panic)) +# Infer anything we might have been notified about while we were down +def catchup_notify(db) + db.query("SELECT customer_id FROM balances WHERE balance < 5").each do |c| + db.query("SELECT pg_notify('low_balance', $1)", c.values) + end + db.query(<<~SQL).each do |c| + SELECT customer_id + FROM customer_plans INNER JOIN balances USING (customer_id) + WHERE expires_at < LOCALTIMESTAMP AND balance >= 5 + SQL + db.query("SELECT pg_notify('possible_renewal', $1)", c.values) + end +end + def poll_for_notify(db) db.wait_for_notify_defer.then { |notify| - CustomerRepo.new(sgx_repo: Bwmsgsv2Repo.new).find(notify[:extra]) - }.then(&LowBalance.method(:for)).then(&:notify!).then { + CustomerRepo + .new(sgx_repo: Bwmsgsv2Repo.new) + .find(notify[:extra]) + .then { |customer| DbNotification.for(notify, customer) } + }.then(&:call).then { poll_for_notify(db) }.catch(&method(:panic)) end @@ -208,9 +227,8 @@ when_ready do DB.hold do |conn| conn.query("LISTEN low_balance") - conn.query("SELECT customer_id FROM balances WHERE balance < 5").each do |c| - conn.query("SELECT pg_notify('low_balance', $1)", c.values) - end + conn.query("LISTEN possible_renewal") + catchup_notify(conn) poll_for_notify(conn) end -- 2.45.2