Merge branch 'do-not-bill-unregistered'

Stephen Paul Weber created

* do-not-bill-unregistered:
  Query sgx-jmp for every expired user
  Show backtrace and bail out hard on panic

Change summary

Gemfile                     |  1 +
bin/billing_monthly_cronjob | 24 +++++++++++++++++++++++-
lib/blather_notify.rb       | 34 +++++++++++++++++++++++++++++++++-
lib/to_form.rb              | 17 +++++++++++++++++
4 files changed, 74 insertions(+), 2 deletions(-)

Detailed changes

Gemfile 🔗

@@ -5,6 +5,7 @@ source "https://rubygems.org"
 gem "blather"
 gem "braintree"
 gem "dhall"
+gem "em_promise.rb"
 gem "money-open-exchange-rates"
 gem "pg"
 gem "redis"

bin/billing_monthly_cronjob 🔗

@@ -19,6 +19,9 @@ require "pg"
 require "redis"
 
 require_relative "../lib/blather_notify"
+require_relative "../lib/to_form"
+
+using ToForm
 
 CONFIG = Dhall.load(<<-DHALL).sync
 	let Quota = < unlimited | limited: { included: Natural, price: Natural } >
@@ -26,6 +29,7 @@ CONFIG = Dhall.load(<<-DHALL).sync
 	in
 	(#{ARGV[0]}) : {
 		healthchecks_url: Text,
+		sgx_jmp: Text,
 		notify_using: {
 			jid: Text,
 			password: Text,
@@ -71,6 +75,7 @@ end
 stats = Stats.new(
 	not_renewed: 0,
 	renewed: 0,
+	not_registered: 0,
 	revenue: BigDecimal(0)
 )
 
@@ -219,7 +224,24 @@ db.transaction do
 		WHERE expires_at <= NOW()
 		SQL
 	).each do |row|
-		ExpiredCustomer.for(row, db).try_renew(db, stats)
+		one = Queue.new
+		EM.next_tick do
+			BlatherNotify.execute(
+				"customer info",
+				{ q: row["customer_id"] }.to_form(:submit)
+			).then(
+				->(x) { one << x },
+				->(e) { one << RuntimeError.new(e.to_s) }
+			)
+		end
+		info = one.pop
+		raise info if info.is_a?(Exception)
+
+		if info.form.field("tel")&.value
+			ExpiredCustomer.for(row, db).try_renew(db, stats)
+		else
+			stats.add(:not_registered, 1)
+		end
 	end
 end
 

lib/blather_notify.rb 🔗

@@ -1,6 +1,7 @@
 # frozen_string_literal: true
 
 require "blather/client/dsl"
+require "em_promise"
 require "timeout"
 
 module BlatherNotify
@@ -28,7 +29,8 @@ module BlatherNotify
 
 	def self.panic(e)
 		warn e.message
-		exit 2
+		warn e.backtrace
+		exit! 2
 	end
 
 	def self.wait_then_exit
@@ -37,4 +39,34 @@ module BlatherNotify
 		shutdown
 		@thread.join
 	end
+
+	def self.write_with_promise(stanza)
+		promise = EMPromise.new
+		client.write_with_handler(stanza) do |s|
+			if s.error?
+				promise.reject(s)
+			else
+				promise.fulfill(s)
+			end
+		end
+		promise
+	end
+
+	def self.command(node, sessionid=nil, action: :execute, form: nil)
+		Blather::Stanza::Iq::Command.new.tap do |cmd|
+			cmd.to = CONFIG[:sgx_jmp]
+			cmd.node = node
+			cmd.command[:sessionid] = sessionid if sessionid
+			cmd.action = action
+			cmd.command << form if form
+		end
+	end
+
+	def self.execute(command_node, form=nil)
+		write_with_promise(command(command_node)).then do |iq|
+			next iq unless form
+
+			write_with_promise(command(command_node, iq.sessionid, form: form))
+		end
+	end
 end

lib/to_form.rb 🔗

@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require "blather"
+
+module ToForm
+	refine ::Hash do
+		def to_fields
+			map { |k, v| { var: k.to_s, value: v.to_s } }
+		end
+
+		def to_form(type)
+			Blather::Stanza::Iq::X.new(type).tap do |form|
+				form.fields = to_fields
+			end
+		end
+	end
+end