trifle-stats 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +9 -3
- data/lib/trifle/stats.rb +3 -1
- data/lib/trifle/stats/configuration.rb +1 -3
- data/lib/trifle/stats/driver/README.md +1 -1
- data/lib/trifle/stats/driver/mongo.rb +63 -0
- data/lib/trifle/stats/driver/postgres.rb +69 -0
- data/lib/trifle/stats/driver/process.rb +12 -3
- data/lib/trifle/stats/driver/redis.rb +8 -7
- data/lib/trifle/stats/operations/timeseries/increment.rb +1 -1
- data/lib/trifle/stats/operations/timeseries/set.rb +1 -1
- data/lib/trifle/stats/operations/timeseries/values.rb +1 -1
- data/lib/trifle/stats/version.rb +1 -1
- data/trifle-stats.gemspec +3 -0
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a3916f479d04bbffdab357ec6562c37134f114bb74eb8274b8c8285256ace45
|
4
|
+
data.tar.gz: 30df5c2bf81b14fef07ad6fd5a31e130bec6183e589fbc6dd9b9e1a23e2f94bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1427bd400037791d86dd1890bd8dde7f91e5482dd65119f4223cc0f235cee7563af9675b4bbc8f15243fb4313dfea9a5d70d4e986f3c5ff91a58900430d60c4
|
7
|
+
data.tar.gz: 637dcd3e31689fa0b62ea583d8343fbc93943afbb285daaa8203f0e25eb87b43f3f4ed78217923be01316c2eeefeb6650988588ac14b6dd40d5caac47980250b
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
trifle-stats (0.
|
4
|
+
trifle-stats (0.4.0)
|
5
|
+
mongo (>= 2.14.0)
|
6
|
+
pg (>= 1.2)
|
5
7
|
redis (>= 4.2)
|
6
8
|
tzinfo (~> 2.0)
|
7
9
|
|
@@ -9,16 +11,20 @@ GEM
|
|
9
11
|
remote: https://rubygems.org/
|
10
12
|
specs:
|
11
13
|
ast (2.4.2)
|
14
|
+
bson (4.12.1)
|
12
15
|
byebug (11.1.3)
|
13
|
-
concurrent-ruby (1.1.
|
16
|
+
concurrent-ruby (1.1.9)
|
14
17
|
diff-lcs (1.4.4)
|
15
18
|
dotenv (2.7.6)
|
19
|
+
mongo (2.14.0)
|
20
|
+
bson (>= 4.8.2, < 5.0.0)
|
16
21
|
parallel (1.20.1)
|
17
22
|
parser (3.0.0.0)
|
18
23
|
ast (~> 2.4.1)
|
24
|
+
pg (1.2.3)
|
19
25
|
rainbow (3.0.0)
|
20
26
|
rake (12.3.3)
|
21
|
-
redis (4.
|
27
|
+
redis (4.3.1)
|
22
28
|
regexp_parser (2.0.3)
|
23
29
|
rexml (3.2.4)
|
24
30
|
rspec (3.10.0)
|
data/lib/trifle/stats.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'trifle/stats/driver/
|
3
|
+
require 'trifle/stats/driver/mongo'
|
4
|
+
require 'trifle/stats/driver/postgres'
|
4
5
|
require 'trifle/stats/driver/process'
|
6
|
+
require 'trifle/stats/driver/redis'
|
5
7
|
require 'trifle/stats/mixins/packer'
|
6
8
|
require 'trifle/stats/nocturnal'
|
7
9
|
require 'trifle/stats/configuration'
|
@@ -6,11 +6,9 @@ module Trifle
|
|
6
6
|
module Stats
|
7
7
|
class Configuration
|
8
8
|
attr_writer :driver
|
9
|
-
attr_accessor :track_ranges, :
|
10
|
-
:beginning_of_week
|
9
|
+
attr_accessor :track_ranges, :time_zone, :beginning_of_week
|
11
10
|
|
12
11
|
def initialize
|
13
|
-
@separator = '::'
|
14
12
|
@ranges = %i[minute hour day week month quarter year]
|
15
13
|
@beginning_of_week = :monday
|
16
14
|
@time_zone = 'GMT'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Driver is a wrapper class that persists and retrieves values from backend. It needs to implement:
|
4
4
|
|
5
|
-
- `inc(key:, **values)` method
|
5
|
+
- `inc(key:, **values)` method increment values
|
6
6
|
- `set(key:, **values)` method set values
|
7
7
|
- `get(key:)` method to retrieve values
|
8
8
|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mongo'
|
4
|
+
require_relative '../mixins/packer'
|
5
|
+
|
6
|
+
module Trifle
|
7
|
+
module Stats
|
8
|
+
module Driver
|
9
|
+
class Mongo
|
10
|
+
include Mixins::Packer
|
11
|
+
attr_accessor :client, :collection_name, :separator
|
12
|
+
|
13
|
+
def initialize(client, collection_name: 'trifle_stats')
|
14
|
+
@client = client
|
15
|
+
@collection_name = collection_name
|
16
|
+
@separator = '::'
|
17
|
+
end
|
18
|
+
|
19
|
+
def inc(key:, **values)
|
20
|
+
pkey = key.join(separator)
|
21
|
+
|
22
|
+
collection.bulk_write(
|
23
|
+
[upsert_operation('$inc', pkey: pkey, values: values)]
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def set(key:, **values)
|
28
|
+
pkey = key.join(separator)
|
29
|
+
|
30
|
+
collection.bulk_write(
|
31
|
+
[upsert_operation('$set', pkey: pkey, values: values)]
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def upsert_operation(operation, pkey:, values:)
|
36
|
+
data = self.class.pack(hash: { data: values })
|
37
|
+
{
|
38
|
+
update_many: {
|
39
|
+
filter: { key: pkey },
|
40
|
+
update: { operation => data },
|
41
|
+
upsert: true
|
42
|
+
}
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def get(key:)
|
47
|
+
pkey = key.join(separator)
|
48
|
+
|
49
|
+
data = collection.find(key: pkey).limit(1).first
|
50
|
+
return {} if data.nil? || data['data'].nil?
|
51
|
+
|
52
|
+
data['data']
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def collection
|
58
|
+
client[collection_name]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pg'
|
4
|
+
require_relative '../mixins/packer'
|
5
|
+
|
6
|
+
module Trifle
|
7
|
+
module Stats
|
8
|
+
module Driver
|
9
|
+
class Postgres
|
10
|
+
include Mixins::Packer
|
11
|
+
attr_accessor :client, :table_name, :separator
|
12
|
+
|
13
|
+
def initialize(client = PG::Connection.new, table_name: 'trifle_stats')
|
14
|
+
@client = client
|
15
|
+
@table_name = table_name
|
16
|
+
@separator = '::'
|
17
|
+
end
|
18
|
+
|
19
|
+
def inc(key:, **values)
|
20
|
+
pkey = key.join(separator)
|
21
|
+
|
22
|
+
self.class.pack(hash: values).each do |k, c|
|
23
|
+
_inc_one(key: pkey, name: k, value: c)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def _inc_one(key:, name:, value:)
|
28
|
+
data = { name => value }
|
29
|
+
query = "INSERT INTO trifle_stats(key, data) VALUES ('#{key}', '#{data.to_json}') ON CONFLICT (key) DO UPDATE SET data = jsonb_set(to_jsonb(trifle_stats.data), '{#{name}}', (COALESCE(trifle_stats.data->>'#{name}','0')::int + #{value})::text::jsonb)" # rubocop:disable Metric/LineLength
|
30
|
+
|
31
|
+
client.exec(query)
|
32
|
+
end
|
33
|
+
|
34
|
+
def set(key:, **values)
|
35
|
+
pkey = key.join(separator)
|
36
|
+
|
37
|
+
_set_all(key: pkey, **values)
|
38
|
+
end
|
39
|
+
|
40
|
+
def _set_all(key:, **values)
|
41
|
+
data = self.class.pack(hash: values)
|
42
|
+
query = "INSERT INTO trifle_stats(key, data) VALUES ('#{key}', '#{data.to_json}') ON CONFLICT (key) DO UPDATE SET data = '#{data.to_json}'" # rubocop:disable Metric/LineLength
|
43
|
+
|
44
|
+
client.exec(query)
|
45
|
+
end
|
46
|
+
|
47
|
+
def get(key:)
|
48
|
+
pkey = key.join(separator)
|
49
|
+
|
50
|
+
data = _get(key: pkey)
|
51
|
+
return {} if data.nil?
|
52
|
+
|
53
|
+
self.class.unpack(hash: data)
|
54
|
+
end
|
55
|
+
|
56
|
+
def _get(key:)
|
57
|
+
result = client.exec_params(
|
58
|
+
"SELECT * FROM #{table_name} WHERE key = $1 LIMIT 1;", [key]
|
59
|
+
).to_a.first
|
60
|
+
return nil if result.nil?
|
61
|
+
|
62
|
+
JSON.parse(result.try(:fetch, 'data'))
|
63
|
+
rescue JSON::ParserError
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -9,19 +9,28 @@ module Trifle
|
|
9
9
|
include Mixins::Packer
|
10
10
|
def initialize
|
11
11
|
@data = {}
|
12
|
+
@separator = '::'
|
12
13
|
end
|
13
14
|
|
14
15
|
def inc(key:, **values)
|
15
16
|
self.class.pack(hash: values).each do |k, c|
|
16
|
-
d = @data.fetch(key, {})
|
17
|
+
d = @data.fetch(key.join(@separator), {})
|
17
18
|
d[k] = d[k].to_i + c
|
18
|
-
@data[key] = d
|
19
|
+
@data[key.join(@separator)] = d
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def set(key:, **values)
|
24
|
+
self.class.pack(hash: values).each do |k, c|
|
25
|
+
d = @data.fetch(key.join(@separator), {})
|
26
|
+
d[k] = c
|
27
|
+
@data[key.join(@separator)] = d
|
19
28
|
end
|
20
29
|
end
|
21
30
|
|
22
31
|
def get(key:)
|
23
32
|
self.class.unpack(
|
24
|
-
hash: @data.fetch(key, {})
|
33
|
+
hash: @data.fetch(key.join(@separator), {})
|
25
34
|
)
|
26
35
|
end
|
27
36
|
end
|
@@ -8,32 +8,33 @@ module Trifle
|
|
8
8
|
module Driver
|
9
9
|
class Redis
|
10
10
|
include Mixins::Packer
|
11
|
-
attr_accessor :prefix
|
11
|
+
attr_accessor :client, :prefix, :separator
|
12
12
|
|
13
13
|
def initialize(client = ::Redis.current, prefix: 'trfl')
|
14
14
|
@client = client
|
15
15
|
@prefix = prefix
|
16
|
+
@separator = '::'
|
16
17
|
end
|
17
18
|
|
18
19
|
def inc(key:, **values)
|
19
|
-
pkey = [
|
20
|
+
pkey = ([prefix] + key).join(separator)
|
20
21
|
|
21
22
|
self.class.pack(hash: values).each do |k, c|
|
22
|
-
|
23
|
+
client.hincrby(pkey, k, c)
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
27
|
def set(key:, **values)
|
27
|
-
pkey = [
|
28
|
+
pkey = ([prefix] + key).join(separator)
|
28
29
|
|
29
|
-
|
30
|
+
client.hmset(pkey, *self.class.pack(hash: values))
|
30
31
|
end
|
31
32
|
|
32
33
|
def get(key:)
|
33
|
-
pkey = [
|
34
|
+
pkey = ([prefix] + key).join(separator)
|
34
35
|
|
35
36
|
self.class.unpack(
|
36
|
-
hash:
|
37
|
+
hash: client.hgetall(pkey)
|
37
38
|
)
|
38
39
|
end
|
39
40
|
end
|
data/lib/trifle/stats/version.rb
CHANGED
data/trifle-stats.gemspec
CHANGED
@@ -33,6 +33,9 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency('rake', '~> 13.0')
|
34
34
|
spec.add_development_dependency('rspec', '~> 3.2')
|
35
35
|
spec.add_development_dependency('rubocop', '1.0.0')
|
36
|
+
|
37
|
+
spec.add_runtime_dependency('mongo', '>= 2.14.0')
|
38
|
+
spec.add_runtime_dependency('pg', '>= 1.2')
|
36
39
|
spec.add_runtime_dependency('redis', '>= 4.2')
|
37
40
|
spec.add_runtime_dependency('tzinfo', '~> 2.0')
|
38
41
|
end
|
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: 0.
|
4
|
+
version: 0.4.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: 2021-
|
11
|
+
date: 2021-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,6 +94,34 @@ dependencies:
|
|
94
94
|
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 1.0.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mongo
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.14.0
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 2.14.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pg
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.2'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.2'
|
97
125
|
- !ruby/object:Gem::Dependency
|
98
126
|
name: redis
|
99
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +178,8 @@ files:
|
|
150
178
|
- lib/trifle/stats.rb
|
151
179
|
- lib/trifle/stats/configuration.rb
|
152
180
|
- lib/trifle/stats/driver/README.md
|
181
|
+
- lib/trifle/stats/driver/mongo.rb
|
182
|
+
- lib/trifle/stats/driver/postgres.rb
|
153
183
|
- lib/trifle/stats/driver/process.rb
|
154
184
|
- lib/trifle/stats/driver/redis.rb
|
155
185
|
- lib/trifle/stats/mixins/packer.rb
|