trifle-stats 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a42d81aa9cf531df2abc462167d9b173af444c2089f15f1d53354153b1fb18df
4
- data.tar.gz: b5237b9c28ce0779ecdc3f129d26de062084490dd9b470b05ffb975a05ecc293
3
+ metadata.gz: 1a496a80a0581a3fb0ab818d86132fd9b1e7377ff271b25e654e91a543c35eb5
4
+ data.tar.gz: 85eba8c25e377e2d30b17b092a91bf5f5ef13f8eddbe39c5b5d910ef7f092050
5
5
  SHA512:
6
- metadata.gz: d835304df2db49efd76728e0de0bb1ae827680a5ec1a5d4a071a9ac60ca4a045441b8afa5628ca6e38e7f07c010c2cd550bdb15b91409e89f9211242bed17527
7
- data.tar.gz: '08e5fa3dceb15fd8927c2320efe73ab543801ac4bac99ff80a478ea344e03b0c6f1f78c7ec23a21c5ac18d22912f4a10774f5a6389e2ae5a428402776e057fc5'
6
+ metadata.gz: f8f68bd3587f76c996ea3707815d2779e74e68a25a4da0cf74fb27ae592ea66d702e654b39accf11eb3bb03e67d62f16033cc4aa949e396d9e19a3f5bc8c87f1
7
+ data.tar.gz: ae59825f8565c8ac8cd404f43088fccb42f645a9dcf1519e3fe370d46e181062bce7f31420ddd5cfc3539c852a609551bbbacbe4aa1203b1e69a9f826f0f26ba
@@ -1 +1 @@
1
- FROM trifle/environment:1.0.2
1
+ FROM trifle/environment:1.0.4
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
12
  /.byebug_history
13
+ stats.db
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- trifle-stats (1.2.0)
4
+ trifle-stats (1.3.0)
5
5
  tzinfo (~> 2.0)
6
6
 
7
7
  GEM
@@ -49,6 +49,7 @@ GEM
49
49
  rubocop-ast (1.4.1)
50
50
  parser (>= 2.7.1.5)
51
51
  ruby-progressbar (1.11.0)
52
+ sqlite3 (1.4.4)
52
53
  tzinfo (2.0.5)
53
54
  concurrent-ruby (~> 1.0)
54
55
  unicode-display_width (1.7.0)
@@ -67,6 +68,7 @@ DEPENDENCIES
67
68
  redis (>= 4.2)
68
69
  rspec (~> 3.0)
69
70
  rubocop (= 1.0.0)
71
+ sqlite3 (>= 1.4.4)
70
72
  trifle-stats!
71
73
 
72
74
  BUNDLED WITH
@@ -16,6 +16,11 @@ module Trifle
16
16
  @separator = '::'
17
17
  end
18
18
 
19
+ def self.setup!(client, collection_name: 'trifle_stats')
20
+ client[collection_name].create
21
+ client[collection_name].indexes.create_one({ key: 1 }, unique: true)
22
+ end
23
+
19
24
  def inc(keys:, **values)
20
25
  data = self.class.pack(hash: { data: values })
21
26
 
@@ -16,56 +16,69 @@ module Trifle
16
16
  @separator = '::'
17
17
  end
18
18
 
19
- def inc(keys:, **values)
20
- keys.map do |key|
21
- pkey = key.join(separator)
19
+ def self.setup!(client = PG::Connection.new, table_name: 'trifle_stats')
20
+ client.exec("CREATE TABLE #{table_name} (key VARCHAR(255) PRIMARY KEY, data JSONB NOT NULL DEFAULT '{}'::jsonb)") # rubocop:disable Layout/LineLength
21
+ end
22
22
 
23
- _inc_all(key: pkey, data: self.class.pack(hash: values))
23
+ def inc(keys:, **values)
24
+ data = self.class.pack(hash: values)
25
+ client.transaction do |c|
26
+ keys.map do |key|
27
+ pkey = key.join(separator)
28
+ c.exec(inc_query(key: pkey, data: data))
29
+ end
24
30
  end
25
31
  end
26
32
 
27
- def _inc_all(key:, data:)
28
- query = "INSERT INTO trifle_stats(key, data) VALUES ('#{key}', '#{data.to_json}') ON CONFLICT (key) DO UPDATE SET data = " + # rubocop:disable Layout/LineLength
29
- data.inject('to_jsonb(trifle_stats.data)') { |o, (k, v)| "jsonb_set(#{o}, '{#{k}}', (COALESCE(trifle_stats.data->>'#{k}', '0')::int + #{v})::text::jsonb)" } # rubocop:disable Layout/LineLength
30
-
31
- client.exec(query)
33
+ def inc_query(key:, data:)
34
+ <<-SQL
35
+ INSERT INTO #{table_name} (key, data) VALUES ('#{key}', '#{data.to_json}')
36
+ ON CONFLICT (key) DO UPDATE SET data =
37
+ #{data.inject("to_jsonb(#{table_name}.data)") { |o, (k, v)| "jsonb_set(#{o}, '{#{k}}', (COALESCE(trifle_stats.data->>'#{k}', '0')::int + #{v})::text::jsonb)" }};
38
+ SQL
32
39
  end
33
40
 
34
41
  def set(keys:, **values)
35
- keys.map do |key|
36
- pkey = key.join(separator)
37
-
38
- _set_all(key: pkey, data: self.class.pack(hash: values))
42
+ data = self.class.pack(hash: values)
43
+ client.transaction do |c|
44
+ keys.map do |key|
45
+ pkey = key.join(separator)
46
+ c.exec(set_query(key: pkey, data: data))
47
+ end
39
48
  end
40
49
  end
41
50
 
42
- def _set_all(key:, data:)
43
- query = "INSERT INTO trifle_stats(key, data) VALUES ('#{key}', '#{data.to_json}') ON CONFLICT (key) DO UPDATE SET data = " + # rubocop:disable Layout/LineLength
44
- data.inject('to_jsonb(trifle_stats.data)') { |o, (k, v)| "jsonb_set(#{o}, '{#{k}}', (#{v})::text::jsonb)" } # rubocop:disable Layout/LineLength
45
-
46
- client.exec(query)
51
+ def set_query(key:, data:)
52
+ <<-SQL
53
+ INSERT INTO #{table_name} (key, data) VALUES ('#{key}', '#{data.to_json}')
54
+ ON CONFLICT (key) DO UPDATE SET data =
55
+ #{data.inject("to_jsonb(#{table_name}.data)") { |o, (k, v)| "jsonb_set(#{o}, '{#{k}}', (#{v})::text::jsonb)" }}
56
+ SQL
47
57
  end
48
58
 
49
59
  def get(keys:)
50
60
  pkeys = keys.map { |key| key.join(separator) }
51
- data = _get_all(keys: pkeys)
52
- map = data.inject({}) { |o, d| o.merge(d['key'] => d['data']) }
61
+ data = get_all(keys: pkeys)
62
+ map = data.inject({}) { |o, d| o.merge(d[:key] => d[:data]) }
53
63
 
54
- pkeys.map { |pkey| self.class.unpack(hash: map[pkey]) || {} }
64
+ pkeys.map { |pkey| self.class.unpack(hash: map.fetch(pkey, {})) }
55
65
  end
56
66
 
57
- def _get_all(keys:)
58
- results = client.exec_params(
59
- "SELECT * FROM #{table_name} WHERE key IN ('#{keys.join("', '")}');"
60
- ).to_a
67
+ def get_all(keys:)
68
+ results = client.exec_params(get_query(keys: keys)).to_a
61
69
 
62
70
  results.map do |r|
63
- r['data'] = JSON.parse(r['data'])
64
- r
71
+ { key: r['key'], data: JSON.parse(r['data']) }
65
72
  rescue JSON::ParserError
66
- r
73
+ { key: r['key'], data: {} }
67
74
  end
68
75
  end
76
+
77
+ def get_query(keys:)
78
+ <<-SQL
79
+ SELECT * FROM #{table_name} WHERE key IN ('#{keys.join("', '")}');
80
+ SQL
81
+ end
69
82
  end
70
83
  end
71
84
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sqlite3'
4
+ require_relative '../mixins/packer'
5
+
6
+ module Trifle
7
+ module Stats
8
+ module Driver
9
+ class Sqlite
10
+ include Mixins::Packer
11
+ attr_accessor :client, :table_name, :separator
12
+
13
+ def initialize(client = SQLite3::Database.new('stats.db'), table_name: 'trifle_stats')
14
+ @client = client
15
+ @table_name = table_name
16
+ @separator = '::'
17
+ end
18
+
19
+ def self.setup!(client = SQLite3::Database.new('stats.db'), table_name: 'trifle_stats')
20
+ client.execute("CREATE TABLE #{table_name} (key varchar(255), data json);")
21
+ client.execute("CREATE UNIQUE INDEX idx_#{table_name}_key ON #{table_name} (key);")
22
+ end
23
+
24
+ def inc(keys:, **values)
25
+ data = self.class.pack(hash: values)
26
+ client.transaction do |c|
27
+ keys.each do |key|
28
+ pkey = key.join(separator)
29
+ c.execute(inc_query(key: pkey, data: data))
30
+ end
31
+ end
32
+ end
33
+
34
+ def inc_query(key:, data:)
35
+ <<-SQL
36
+ INSERT INTO #{table_name} (key, data) values('#{key}', json('#{data.to_json}'))
37
+ ON CONFLICT (key) DO UPDATE SET data =
38
+ #{data.inject('data') { |o, (k, v)| "json_set(#{o}, '$.#{k}', IFNULL(json_extract(data, '$.#{k}'), 0) + #{v})" }};
39
+ SQL
40
+ end
41
+
42
+ def set(keys:, **values)
43
+ data = self.class.pack(hash: values)
44
+ client.transaction do |c|
45
+ keys.each do |key|
46
+ pkey = key.join(separator)
47
+ c.execute(set_query(key: pkey, data: data))
48
+ end
49
+ end
50
+ end
51
+
52
+ def set_query(key:, data:)
53
+ <<-SQL
54
+ INSERT INTO #{table_name} (key, data) values('#{key}', json('#{data.to_json}'))
55
+ ON CONFLICT (key) DO UPDATE SET data =
56
+ #{data.inject('data') { |o, (k, v)| "json_set(#{o}, '$.#{k}', #{v})" }};
57
+ SQL
58
+ end
59
+
60
+ def get(keys:)
61
+ pkeys = keys.map { |key| key.join(separator) }
62
+ data = get_all(keys: pkeys)
63
+ map = data.inject({}) { |o, d| o.merge(d[:key] => d[:data]) }
64
+
65
+ pkeys.map { |pkey| map.fetch(pkey, {}) }
66
+ end
67
+
68
+ def get_all(keys:)
69
+ results = client.execute(get_query(keys: keys)).to_a
70
+
71
+ results.map do |key, data|
72
+ { key: key, data: JSON.parse(data) }
73
+ rescue JSON::ParserError
74
+ { key: key, data: {} }
75
+ end
76
+ end
77
+
78
+ def get_query(keys:)
79
+ <<-SQL
80
+ SELECT key, data FROM #{table_name} WHERE key IN ('#{keys.join("', '")}');
81
+ SQL
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Trifle
4
4
  module Stats
5
- VERSION = '1.2.0'
5
+ VERSION = '1.3.0'
6
6
  end
7
7
  end
data/lib/trifle/stats.rb CHANGED
@@ -7,6 +7,7 @@ require 'trifle/stats/driver/mongo'
7
7
  require 'trifle/stats/driver/postgres'
8
8
  require 'trifle/stats/driver/process'
9
9
  require 'trifle/stats/driver/redis'
10
+ require 'trifle/stats/driver/sqlite'
10
11
  require 'trifle/stats/mixins/packer'
11
12
  require 'trifle/stats/nocturnal'
12
13
  require 'trifle/stats/configuration'
data/trifle-stats.gemspec CHANGED
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency('byebug', '>= 0')
33
33
  spec.add_development_dependency('dotenv')
34
34
  spec.add_development_dependency('mongo', '>= 2.14.0')
35
+ spec.add_development_dependency('sqlite3', '>= 1.4.4')
35
36
  spec.add_development_dependency('pg', '>= 1.2')
36
37
  spec.add_development_dependency('rake', '~> 13.0')
37
38
  spec.add_development_dependency('redis', '>= 4.2')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trifle-stats
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jozef Vaclavik
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-07-31 00:00:00.000000000 Z
11
+ date: 2022-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: 2.14.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 1.4.4
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 1.4.4
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: pg
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -191,6 +205,7 @@ files:
191
205
  - lib/trifle/stats/driver/postgres.rb
192
206
  - lib/trifle/stats/driver/process.rb
193
207
  - lib/trifle/stats/driver/redis.rb
208
+ - lib/trifle/stats/driver/sqlite.rb
194
209
  - lib/trifle/stats/mixins/packer.rb
195
210
  - lib/trifle/stats/nocturnal.rb
196
211
  - lib/trifle/stats/operations/timeseries/classify.rb