Class: Trifle::Stats::Driver::Sqlite

Inherits:
Object
  • Object
show all
Includes:
Mixins::Packer
Defined in:
lib/trifle/stats/driver/sqlite.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Mixins::Packer

included

Constructor Details

#initialize(client = SQLite3::Database.new('stats.db'), table_name: 'trifle_stats') ⇒ Sqlite

Returns a new instance of Sqlite.



12
13
14
15
16
# File 'lib/trifle/stats/driver/sqlite.rb', line 12

def initialize(client = SQLite3::Database.new('stats.db'), table_name: 'trifle_stats')
  @client = client
  @table_name = table_name
  @separator = '::'
end

Instance Attribute Details

#clientObject

Returns the value of attribute client.



10
11
12
# File 'lib/trifle/stats/driver/sqlite.rb', line 10

def client
  @client
end

#separatorObject

Returns the value of attribute separator.



10
11
12
# File 'lib/trifle/stats/driver/sqlite.rb', line 10

def separator
  @separator
end

#table_nameObject

Returns the value of attribute table_name.



10
11
12
# File 'lib/trifle/stats/driver/sqlite.rb', line 10

def table_name
  @table_name
end

Class Method Details

.setup!(client = SQLite3::Database.new('stats.db'), table_name: 'trifle_stats') ⇒ Object



18
19
20
21
# File 'lib/trifle/stats/driver/sqlite.rb', line 18

def self.setup!(client = SQLite3::Database.new('stats.db'), table_name: 'trifle_stats')
  client.execute("CREATE TABLE #{table_name} (key varchar(255), data json);")
  client.execute("CREATE UNIQUE INDEX idx_#{table_name}_key ON #{table_name} (key);")
end

Instance Method Details

#get(keys:) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/trifle/stats/driver/sqlite.rb', line 59

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| map.fetch(pkey, {}) }
end

#get_all(keys:) ⇒ Object



67
68
69
70
71
72
73
74
75
# File 'lib/trifle/stats/driver/sqlite.rb', line 67

def get_all(keys:)
  results = client.execute(get_query(keys: keys)).to_a

  results.map do |key, data|
    { key: key, data: JSON.parse(data) }
  rescue JSON::ParserError
    { key: key, data: {} }
  end
end

#get_query(keys:) ⇒ Object



77
78
79
80
81
# File 'lib/trifle/stats/driver/sqlite.rb', line 77

def get_query(keys:)
  <<-SQL
    SELECT key, data FROM #{table_name} WHERE key IN ('#{keys.join("', '")}');
  SQL
end

#inc(keys:, **values) ⇒ Object



23
24
25
26
27
28
29
30
31
# File 'lib/trifle/stats/driver/sqlite.rb', line 23

def inc(keys:, **values)
  data = self.class.pack(hash: values)
  client.transaction do |c|
    keys.each do |key|
      pkey = key.join(separator)
      c.execute(inc_query(key: pkey, data: data))
    end
  end
end

#inc_query(key:, data:) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/trifle/stats/driver/sqlite.rb', line 33

def inc_query(key:, data:)
  <<-SQL
    INSERT INTO #{table_name} (key, data) values('#{key}', json('#{data.to_json}'))
    ON CONFLICT (key) DO UPDATE SET data =
    #{data.inject('data') { |o, (k, v)| "json_set(#{o}, '$.#{k}', IFNULL(json_extract(data, '$.#{k}'), 0) + #{v})" }};
  SQL
end

#set(keys:, **values) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/trifle/stats/driver/sqlite.rb', line 41

def set(keys:, **values)
  data = self.class.pack(hash: values)
  client.transaction do |c|
    keys.each do |key|
      pkey = key.join(separator)
      c.execute(set_query(key: pkey, data: data))
    end
  end
end

#set_query(key:, data:) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/trifle/stats/driver/sqlite.rb', line 51

def set_query(key:, data:)
  <<-SQL
    INSERT INTO #{table_name} (key, data) values('#{key}', json('#{data.to_json}'))
    ON CONFLICT (key) DO UPDATE SET data =
    #{data.inject('data') { |o, (k, v)| "json_set(#{o}, '$.#{k}', #{v})" }};
  SQL
end