From f571b5e726750cf8c4523c22d77e110194c3e16a Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Mon, 18 Apr 2022 21:41:40 -0500 Subject: [PATCH] Postgres#query_one Helper for queries that only return a single row. --- lib/call_attempt_repo.rb | 9 ++++----- lib/customer_plan.rb | 6 +----- lib/customer_repo.rb | 8 +------- lib/postgres.rb | 18 ++++++++++++++++++ lib/trust_level_repo.rb | 6 +++--- sgx_jmp.rb | 6 ++---- test/test_customer_info.rb | 12 ++++++------ test/test_helper.rb | 6 ++++++ 8 files changed, 41 insertions(+), 30 deletions(-) create mode 100644 lib/postgres.rb diff --git a/lib/call_attempt_repo.rb b/lib/call_attempt_repo.rb index c0a28aaa7ccf16fe7d51106960403c2650cfe071..c3b2c4f1a7d46b093252a195b0297751cffa5cca 100644 --- a/lib/call_attempt_repo.rb +++ b/lib/call_attempt_repo.rb @@ -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 diff --git a/lib/customer_plan.rb b/lib/customer_plan.rb index 110a6ae081a0b89a616787d4b8a517977dbfe8d1..b0b78984de6da88ea89e603704ebe5990071cbdb 100644 --- a/lib/customer_plan.rb +++ b/lib/customer_plan.rb @@ -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 diff --git a/lib/customer_repo.rb b/lib/customer_repo.rb index 15d99798f4dc84b1be7efd6a5a7ccfec58a87c79..28a171dd49bfae34719fdb1b4c767387850fda08 100644 --- a/lib/customer_repo.rb +++ b/lib/customer_repo.rb @@ -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 diff --git a/lib/postgres.rb b/lib/postgres.rb new file mode 100644 index 0000000000000000000000000000000000000000..bbaeea15b56d16f7c898edb702afe8f5c3e8d399 --- /dev/null +++ b/lib/postgres.rb @@ -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 diff --git a/lib/trust_level_repo.rb b/lib/trust_level_repo.rb index 3e064d85b5b5b44ff39fc3bde5c7e264fdb9eb47..61e9925483a5e835e7a7494163362b2aee62a7b2 100644 --- a/lib/trust_level_repo.rb +++ b/lib/trust_level_repo.rb @@ -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 diff --git a/sgx_jmp.rb b/sgx_jmp.rb index cc2b0458ca7ab511003b779adec11616567bdf71..5fc7c4254dd3c849e21a6cc1df4711e6e4036d81 100644 --- a/sgx_jmp.rb +++ b/sgx_jmp.rb @@ -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") diff --git a/test/test_customer_info.rb b/test/test_customer_info.rb index 3e6aae1c13bfa54b14aca941f54ce535a20aa8f6..14e371980a10cc694ba0c76b1b474904742ab32a 100644 --- a/test/test_customer_info.rb +++ b/test/test_customer_info.rb @@ -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") diff --git a/test/test_helper.rb b/test/test_helper.rb index ce7746d9c67b5c6ca9827c1269c66741bf8a06b4..e71357cdbd4b3cbfcb576491d50c076d7e02094a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -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