Class: Trifle::Stats::Driver::Postgres
- Inherits:
-
Object
- Object
- Trifle::Stats::Driver::Postgres
- Includes:
- Mixins::Packer
- Defined in:
- lib/trifle/stats/driver/postgres.rb
Instance Attribute Summary collapse
-
#client ⇒ Object
Returns the value of attribute client.
-
#separator ⇒ Object
Returns the value of attribute separator.
-
#table_name ⇒ Object
Returns the value of attribute table_name.
Class Method Summary collapse
Instance Method Summary collapse
- #get(keys:) ⇒ Object
- #get_all(keys:) ⇒ Object
- #get_query(keys:) ⇒ Object
- #inc(keys:, **values) ⇒ Object
- #inc_query(key:, data:) ⇒ Object
-
#initialize(client = PG::Connection.new, table_name: 'trifle_stats') ⇒ Postgres
constructor
A new instance of Postgres.
- #set(keys:, **values) ⇒ Object
- #set_query(key:, data:) ⇒ Object
Methods included from Mixins::Packer
Constructor Details
#initialize(client = PG::Connection.new, table_name: 'trifle_stats') ⇒ Postgres
Returns a new instance of Postgres.
12 13 14 15 16 |
# File 'lib/trifle/stats/driver/postgres.rb', line 12 def initialize(client = PG::Connection.new, table_name: 'trifle_stats') @client = client @table_name = table_name @separator = '::' end |
Instance Attribute Details
#client ⇒ Object
Returns the value of attribute client.
10 11 12 |
# File 'lib/trifle/stats/driver/postgres.rb', line 10 def client @client end |
#separator ⇒ Object
Returns the value of attribute separator.
10 11 12 |
# File 'lib/trifle/stats/driver/postgres.rb', line 10 def separator @separator end |
#table_name ⇒ Object
Returns the value of attribute table_name.
10 11 12 |
# File 'lib/trifle/stats/driver/postgres.rb', line 10 def table_name @table_name end |
Class Method Details
.setup!(client = PG::Connection.new, table_name: 'trifle_stats') ⇒ Object
18 19 20 |
# File 'lib/trifle/stats/driver/postgres.rb', line 18 def self.setup!(client = PG::Connection.new, table_name: 'trifle_stats') client.exec("CREATE TABLE #{table_name} (key VARCHAR(255) PRIMARY KEY, data JSONB NOT NULL DEFAULT '{}'::jsonb)") # rubocop:disable Layout/LineLength end |
Instance Method Details
#get(keys:) ⇒ Object
58 59 60 61 62 63 64 |
# File 'lib/trifle/stats/driver/postgres.rb', line 58 def get(keys:) pkeys = keys.map { |key| key.join(separator) } data = get_all(keys: pkeys) map = data.inject({}) { |o, d| o.merge(d[:key] => d[:data]) } pkeys.map { |pkey| self.class.unpack(hash: map.fetch(pkey, {})) } end |
#get_all(keys:) ⇒ Object
66 67 68 69 70 71 72 73 74 |
# File 'lib/trifle/stats/driver/postgres.rb', line 66 def get_all(keys:) results = client.exec_params(get_query(keys: keys)).to_a results.map do |r| { key: r['key'], data: JSON.parse(r['data']) } rescue JSON::ParserError { key: r['key'], data: {} } end end |
#get_query(keys:) ⇒ Object
76 77 78 79 80 |
# File 'lib/trifle/stats/driver/postgres.rb', line 76 def get_query(keys:) <<-SQL SELECT * FROM #{table_name} WHERE key IN ('#{keys.join("', '")}'); SQL end |
#inc(keys:, **values) ⇒ Object
22 23 24 25 26 27 28 29 30 |
# File 'lib/trifle/stats/driver/postgres.rb', line 22 def inc(keys:, **values) data = self.class.pack(hash: values) client.transaction do |c| keys.map do |key| pkey = key.join(separator) c.exec(inc_query(key: pkey, data: data)) end end end |
#inc_query(key:, data:) ⇒ Object
32 33 34 35 36 37 38 |
# File 'lib/trifle/stats/driver/postgres.rb', line 32 def inc_query(key:, data:) <<-SQL INSERT INTO #{table_name} (key, data) VALUES ('#{key}', '#{data.to_json}') ON CONFLICT (key) DO UPDATE SET data = #{data.inject("to_jsonb(#{table_name}.data)") { |o, (k, v)| "jsonb_set(#{o}, '{#{k}}', (COALESCE(trifle_stats.data->>'#{k}', '0')::int + #{v})::text::jsonb)" }}; SQL end |
#set(keys:, **values) ⇒ Object
40 41 42 43 44 45 46 47 48 |
# File 'lib/trifle/stats/driver/postgres.rb', line 40 def set(keys:, **values) data = self.class.pack(hash: values) client.transaction do |c| keys.map do |key| pkey = key.join(separator) c.exec(set_query(key: pkey, data: data)) end end end |
#set_query(key:, data:) ⇒ Object
50 51 52 53 54 55 56 |
# File 'lib/trifle/stats/driver/postgres.rb', line 50 def set_query(key:, data:) <<-SQL INSERT INTO #{table_name} (key, data) VALUES ('#{key}', '#{data.to_json}') ON CONFLICT (key) DO UPDATE SET data = #{data.inject("to_jsonb(#{table_name}.data)") { |o, (k, v)| "jsonb_set(#{o}, '{#{k}}', (#{v})::text::jsonb)" }} SQL end |