~singpolyma/sgx-jmp

f571b5e726750cf8c4523c22d77e110194c3e16a — Stephen Paul Weber 7 months ago da30c37
Postgres#query_one

Helper for queries that only return a single row.
M lib/call_attempt_repo.rb => lib/call_attempt_repo.rb +4 -5
@@ 49,25 49,24 @@ protected
	end

	def find_usage(customer_id)
		promise = db.query_defer(<<~SQL, [customer_id])
		db.query_one(<<~SQL, customer_id, default: { a: 0 }).then { |r| r[:a] }
			SELECT COALESCE(SUM(charge), 0) AS a FROM cdr_with_charge
			WHERE
				customer_id=$1 AND
				start > DATE_TRUNC('month', LOCALTIMESTAMP)
		SQL
		promise.then { |rows| rows.first&.dig("a") || 0 }
	end

	def find_rate(plan_name, other_tel, direction)
		promise = db.query_defer(<<~SQL, [plan_name, other_tel, direction])
		promise = db.query_one(<<~SQL, plan_name, other_tel, direction)
			SELECT rate FROM call_rates
			WHERE
				plan_name=$1 AND
				$2 LIKE prefix || '%' AND
				direction=$3
			ORDER BY prefix DESC
			LIMIT 1;
			LIMIT 1
		SQL
		promise.then { |rows| rows.first&.dig("rate") }
		promise.then { |row| row&.dig(:rate) }
	end
end

M lib/customer_plan.rb => lib/customer_plan.rb +1 -5
@@ 83,15 83,11 @@ class CustomerPlan
	end

	def activation_date
		dates = DB.query_defer(<<~SQL, [@customer_id])
		DB.query_one(<<~SQL, @customer_id).then { |r| r[:start_date] }
			SELECT
				MIN(LOWER(date_range)) AS start_date
			FROM plan_log WHERE customer_id = $1;
		SQL

		dates.then do |r|
			r.first["start_date"]
		end
	end

protected

M lib/customer_repo.rb => lib/customer_repo.rb +1 -7
@@ 150,16 150,10 @@ protected
		WHERE customer_id=$1 LIMIT 1
	SQL

	def fetch_sql(customer_id)
		@db.query_defer(SQL, [customer_id]).then do |rows|
			rows.first&.transform_keys(&:to_sym) || {}
		end
	end

	def fetch_all(customer_id)
		EMPromise.all([
			@sgx_repo.get(customer_id),
			fetch_sql(customer_id),
			@db.query_one(SQL, customer_id, default: {}),
			fetch_redis(customer_id)
		]).then { |sgx, sql, redis| [sgx, sql.merge(redis)] }
	end

A lib/postgres.rb => lib/postgres.rb +18 -0
@@ 0,0 1,18 @@
# frozen_string_literal: true

require "delegate"

class Postgres < SimpleDelegator
	def self.connect(**kwargs)
		new(PG::EM::ConnectionPool.new(**kwargs) { |conn|
			conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn)
			conn.type_map_for_queries = PG::BasicTypeMapForQueries.new(conn)
		})
	end

	def query_one(sql, *args, field_names_as: :symbol, default: nil)
		query_defer(sql, args).then do |rows|
			rows.field_names_as(field_names_as)&.first || default
		end
	end
end

M lib/trust_level_repo.rb => lib/trust_level_repo.rb +3 -3
@@ 14,11 14,11 @@ class TrustLevelRepo
		EMPromise.all([
			redis.get("jmp_customer_trust_level-#{customer.customer_id}"),
			fetch_settled_amount(customer.customer_id)
		]).then do |(manual, rows)|
		]).then do |(manual, row)|
			TrustLevel.for(
				manual: manual,
				plan_name: customer.plan_name,
				**(rows.first&.transform_keys(&:to_sym) || {})
				**row
			)
		end
	end


@@ 26,7 26,7 @@ class TrustLevelRepo
protected

	def fetch_settled_amount(customer_id)
		db.query_defer(<<~SQL, [customer_id])
		db.query_one(<<~SQL, customer_id, default: {})
			SELECT SUM(amount) AS settled_amount FROM transactions
			WHERE customer_id=$1 AND settled_after < LOCALTIMESTAMP AND amount > 0
		SQL

M sgx_jmp.rb => sgx_jmp.rb +2 -4
@@ 92,6 92,7 @@ require_relative "lib/low_balance"
require_relative "lib/port_in_order"
require_relative "lib/payment_methods"
require_relative "lib/paypal_done"
require_relative "lib/postgres"
require_relative "lib/registration"
require_relative "lib/transaction"
require_relative "lib/tel_selections"


@@ 220,10 221,7 @@ when_ready do
	REDIS = EM::Hiredis.connect
	TEL_SELECTIONS = TelSelections.new
	BTC_SELL_PRICES = BTCSellPrices.new(REDIS, CONFIG[:oxr_app_id])
	DB = PG::EM::ConnectionPool.new(dbname: "jmp") { |conn|
		conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn)
		conn.type_map_for_queries = PG::BasicTypeMapForQueries.new(conn)
	}
	DB = Postgres.connect(dbname: "jmp")

	DB.hold do |conn|
		conn.query("LISTEN low_balance")

M test/test_customer_info.rb => test/test_customer_info.rb +6 -6
@@ 20,9 20,9 @@ class CustomerInfoTest < Minitest::Test
		sgx.expect(:registered?, false)

		CustomerPlan::DB.expect(
			:query_defer,
			EMPromise.resolve([{ "start_date" => Time.now }]),
			[String, ["test"]]
			:query_one,
			EMPromise.resolve({ start_date: Time.now }),
			[String, "test"]
		)

		cust = customer(sgx: sgx, plan_name: "test_usd")


@@ 39,9 39,9 @@ class CustomerInfoTest < Minitest::Test
		sgx.expect(:fwd, fwd)

		CustomerPlan::DB.expect(
			:query_defer,
			EMPromise.resolve([{ "start_date" => Time.now }]),
			[String, ["test"]]
			:query_one,
			EMPromise.resolve({ start_date: Time.now }),
			[String, "test"]
		)

		cust = customer(sgx: sgx, plan_name: "test_usd")

M test/test_helper.rb => test/test_helper.rb +6 -0
@@ 228,6 228,12 @@ class FakeDB
	def query_defer(_, args)
		EMPromise.resolve(@items.fetch(args, []).to_a)
	end

	def query_one(_, *args, field_names_as: :symbol, default: nil)
		row = @items.fetch(args, []).to_a.first
		row = row.transform_keys(&:to_sym) if row && field_names_as == :symbol
		EMPromise.resolve(row || default)
	end
end

class FakeLog