~singpolyma/jmp-pay

092fa28a05ba09f9eaaab3f6ee2ae38bd10f36a9 — Stephen Paul Weber 16 days ago 42df6be + 265bb3e
Merge branch 'do-not-bill-unregistered'

* do-not-bill-unregistered:
  Query sgx-jmp for every expired user
  Show backtrace and bail out hard on panic
4 files changed, 74 insertions(+), 2 deletions(-)

M Gemfile
M bin/billing_monthly_cronjob
M lib/blather_notify.rb
A lib/to_form.rb
M Gemfile => Gemfile +1 -0
@@ 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"

M bin/billing_monthly_cronjob => bin/billing_monthly_cronjob +23 -1
@@ 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


M lib/blather_notify.rb => lib/blather_notify.rb +33 -1
@@ 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

A lib/to_form.rb => lib/to_form.rb +17 -0
@@ 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