~singpolyma/sgx-jmp

ref: f571b5e726750cf8c4523c22d77e110194c3e16a sgx-jmp/lib/customer_usage.rb -rw-r--r-- 1.6 KiB
f571b5e7Stephen Paul Weber Postgres#query_one 1 year, 7 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# frozen_string_literal: true

require_relative "./usage_report"

class CustomerUsage
	def initialize(customer_id)
		@customer_id = customer_id
	end

	def usage_report(range)
		EMPromise.all([
			messages_by_day(range),
			minutes_by_day(range)
		]).then do |args|
			UsageReport.new(range, *args)
		end
	end

	def expire_message_usage
		today = Time.now.utc.to_date
		REDIS.zremrangebylex(
			"jmp_customer_outbound_messages-#{@customer_id}",
			"-",
			# Store message counts per day for 1 year
			"[#{(today << 12).strftime('%Y%m%d')}"
		)
	end

	def incr_message_usage(amount=1)
		today = Time.now.utc.to_date
		EMPromise.all([
			expire_message_usage,
			REDIS.zincrby(
				"jmp_customer_outbound_messages-#{@customer_id}",
				amount,
				today.strftime("%Y%m%d")
			)
		])
	end

	def message_usage(range)
		messages_by_day(range).then do |by_day|
			by_day.values.sum
		end
	end

	def messages_by_day(range)
		EMPromise.all(range.first.downto(range.last).map { |day|
			REDIS.zscore(
				"jmp_customer_outbound_messages-#{@customer_id}",
				day.strftime("%Y%m%d")
			).then { |c| [day, c.to_i] if c }
		}).then { |r| r.compact.to_h.tap { |h| h.default = 0 } }
	end

	QUERY_FOR_MINUTES = <<~SQL
		SELECT
			date_trunc('day', start)::date as day,
			CEIL(SUM(billsec)/60.0)::integer as minutes
		FROM cdr
		WHERE customer_id=$1 and start >= $3 and date_trunc('day', start) <= $2
		GROUP BY date_trunc('day', start);
	SQL

	def minutes_by_day(range)
		DB.query_defer(
			QUERY_FOR_MINUTES,
			[@customer_id, range.first, range.last]
		).then do |result|
			result.each_with_object(Hash.new(0)) do |row, minutes|
				minutes[row["day"]] = row["minutes"]
			end
		end
	end
end