redis_counters-dumpers 1.2.0 → 1.2.4

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
  SHA1:
3
- metadata.gz: 9768a6973b5c7597061b0c9979577504ad5724e6
4
- data.tar.gz: 5e9940f0b1cd4d21f605f9d5ef75134228e1b393
3
+ metadata.gz: b9d2c6c4b07a8698c85d840ec777404a9206cc3b
4
+ data.tar.gz: 6a17082018c974180d3566e6687921807fe38051
5
5
  SHA512:
6
- metadata.gz: 7f49176f615448b7d0b796b9de61192d775d92e0a2e920a22e324666a2a99c1460335d3cf7fbe8fc2b61a082129e91dc256b9a53a2637a8e560a829ea90270db
7
- data.tar.gz: 842d8c7fefc9bba5b821572fd5ba995c82e57a3670aa29b114aa867ccfd90ed4c6781562ef0fb01d9b956cc8d90a7533fc7fd4f6fffffcb25352b41b1c68b897
6
+ metadata.gz: 8b1adb66801e63e2cbe7bb294cd6b02d16ab3c231df0df8afb0936b75ff8af43ac3378772933269f7e29002eb9170d4f4378ffff9b64d3a226208c8ecbd7fb62
7
+ data.tar.gz: d2134d05745204497462927cb8d92d8e3f52a8cd8aa2b0f87acdb3c1378999b086a84d3320045086eb55757db9dce02141c19347d1065f206fc1c25f7edc9428
data/.drone.yml CHANGED
@@ -1,21 +1,86 @@
1
- build:
2
- test:
3
- image: abakpress/dind-testing
4
- pull: true
5
- privileged: true
6
- volumes:
7
- - /home/data/drone/images:/images
8
- - /home/data/drone/gems:/bundle
1
+ name: build
2
+
3
+ kind: pipeline
4
+ type: docker
5
+
6
+ volumes:
7
+ - name: rubygems
8
+ host:
9
+ path: /home/data/drone/rubygems
10
+ - name: images
11
+ host:
12
+ path: /home/data/drone/images
13
+ - name: bundle
14
+ host:
15
+ path: /home/data/drone/gems
16
+ - name: keys
17
+ host:
18
+ path: /home/data/drone/key_cache
19
+
20
+ spec_step_common: &spec_step_common
21
+ image: abakpress/dind-testing:1.0.3
22
+ pull: if-not-exists
23
+ privileged: true
24
+ volumes:
25
+ - name: images
26
+ path: /images
27
+ - name: bundle
28
+ path: /bundle
29
+ - name: keys
30
+ path: /ssh_keys
31
+ commands:
32
+ - prepare-build
33
+
34
+ - fetch-images
35
+ --image whilp/ssh-agent
36
+ --image abakpress/ruby-app:$RUBY_IMAGE_TAG
37
+ --image abakpress/postgres-db:$POSTGRES_IMAGE_TAG
38
+ --image redis:$REDIS_IMAGE_TAG
39
+
40
+ - dip ssh add -T -v /ssh_keys -k /ssh_keys/id_rsa
41
+ - dip provision
42
+ - dip rspec
43
+
44
+ steps:
45
+ - name: Tests Ruby 2.2
9
46
  environment:
10
- - COMPOSE_FILE_EXT=drone
11
- - POSTGRES_IMAGE_TAG=9.6-latest
12
- - RUBY_IMAGE_TAG=2.2-latest
13
- commands:
14
- - wrapdocker docker -v
47
+ COMPOSE_FILE_EXT: drone
48
+ DOCKER_RUBY_VERSION: 2.2
49
+ RUBY_IMAGE_TAG: 2.2-latest
50
+ POSTGRES_IMAGE_TAG: 9.6-latest
51
+ REDIS_IMAGE_TAG: 4-alpine
52
+ RAILS_ENV: test
53
+ <<: *spec_step_common
54
+
55
+ - name: Tests Ruby 2.3
56
+ environment:
57
+ COMPOSE_FILE_EXT: drone
58
+ DOCKER_RUBY_VERSION: 2.3
59
+ RUBY_IMAGE_TAG: 2.3-latest
60
+ POSTGRES_IMAGE_TAG: 9.6-latest
61
+ REDIS_IMAGE_TAG: 4-alpine
62
+ RAILS_ENV: test
63
+ <<: *spec_step_common
15
64
 
16
- - fetch-images
17
- --image abakpress/ruby-app:$RUBY_IMAGE_TAG
18
- --image abakpress/postgres-db:$POSTGRES_IMAGE_TAG
65
+ - name: Tests Ruby 2.4
66
+ environment:
67
+ COMPOSE_FILE_EXT: drone
68
+ DOCKER_RUBY_VERSION: 2.4
69
+ RUBY_IMAGE_TAG: 2.4-latest
70
+ POSTGRES_IMAGE_TAG: 9.6-latest
71
+ REDIS_IMAGE_TAG: 4-alpine
72
+ RAILS_ENV: test
73
+ <<: *spec_step_common
19
74
 
20
- - dip provision
21
- - dip rspec
75
+ - name: release
76
+ image: abakpress/gem-publication:latest
77
+ pull: if-not-exists
78
+ when:
79
+ event: push
80
+ branch: master
81
+ status: success
82
+ volumes:
83
+ - name: rubygems
84
+ path: /root/.gem
85
+ commands:
86
+ - release-gem --public
data/.gitignore CHANGED
@@ -14,3 +14,4 @@
14
14
  *.o
15
15
  *.a
16
16
  mkmf.log
17
+ /.idea/
data/Appraisals CHANGED
@@ -1,14 +1,11 @@
1
- appraise 'rails3.2' do
2
- gem 'activesupport', '~> 3.2.14'
3
- gem 'activerecord', '~> 3.2.14'
1
+ if RUBY_VERSION < '2.4'
2
+ appraise 'rails4.0' do
3
+ gem 'activesupport', '~> 4.0.0'
4
+ gem 'activerecord', '~> 4.0.0'
5
+ end
4
6
  end
5
7
 
6
- appraise 'rails4.0' do
7
- gem 'activesupport', '~> 4.0.0'
8
- gem 'activerecord', '~> 4.0.0'
9
- end
10
-
11
- appraise 'rails4.1' do
12
- gem 'activesupport', '~> 4.1.0'
13
- gem 'activerecord', '~> 4.1.0'
8
+ appraise 'rails4.2' do
9
+ gem 'activesupport', '~> 4.2.0'
10
+ gem 'activerecord', '~> 4.2.0'
14
11
  end
data/CHANGELOG.md CHANGED
@@ -1,25 +1,59 @@
1
+ # v1.2.4
1
2
 
2
- #### [Current]
3
+ * 2021-08-06 [f1e9b41](../../commit/f1e9b41) - __(TamarinEA)__ Release 1.2.4
4
+ * 2021-08-06 [9b68886](../../commit/9b68886) - __(TamarinEA)__ chore: remove mock_redis
3
5
 
6
+ # v1.2.3
4
7
 
5
- #### v1.1.0
6
- * 2017-07-07 [ae5ffbf](../../commit/ae5ffbf) - __(Pavel Galkin)__ Release 1.1.0
7
- * 2017-06-21 [fc29058](../../commit/fc29058) - __(Pavel Galkin)__ feat: matching_expr option for destination
8
- * 2017-06-20 [d21a7d8](../../commit/d21a7d8) - __(Pavel Galkin)__ chore: update infrastructure
8
+ * 2021-08-06 [fb93322](../../commit/fb93322) - __(TamarinEA)__ chore: add rubygems volume
9
+ * 2021-08-05 [06cc372](../../commit/06cc372) - __(TamarinEA)__ chore: add ruby 2.4 support
9
10
 
10
- #### v1.0.0
11
- * 2016-10-14 [704ad6d](../../commit/704ad6d) - __(Semyon Pupkov)__ Bump version
12
- * 2016-09-05 [0bf4850](../../commit/0bf4850) - __(vadshalamov)__ feature: позволит не задавать increment_fields
13
- * 2016-08-31 [b5c9bd9](../../commit/b5c9bd9) - __(vadshalamov)__ feature: добавит hstore в список возможных полей
14
- * 2016-08-31 [3b0235c](../../commit/3b0235c) - __(vadshalamov)__ feature: позволит передавать набор аргументов для дампа
15
- * 2016-07-18 [caa913e](../../commit/caa913e) - __(Stanislav Gordanov)__ feat: добавит enum тип в список возможных полей
16
- * 2016-05-27 [bbb7119](../../commit/bbb7119) - __(Michail Merkushin)__ fix: Remove CTE favor temp table
11
+ # v1.2.2
17
12
 
18
- #### v0.1.0
19
- * 2015-09-15 [bf8cde3](../../commit/bf8cde3) - __(ZhidkovDenis)__ Release 0.1.0
20
- * 2015-09-10 [1f96c39](../../commit/1f96c39) - __(Zhidkov Denis)__ feat: add source_conditions method
21
- * 2015-02-19 [8885300](../../commit/8885300) - __(bibendi)__ add group_by method
13
+ * 2018-12-21 [6dd9509](../../commit/6dd9509) - __(Oleg Perminov)__ fix: add type text to updating expression
14
+ https://jira.railsc.ru/browse/CRM-4532
22
15
 
23
- #### v0.0.1
24
- * 2015-01-26 [86918bd](../../commit/86918bd) - __(bibendi)__ initial code base
25
- * 2015-01-26 [a238032](../../commit/a238032) - __(bibendi)__ initial
16
+ * 2018-12-13 [b197e2a](../../commit/b197e2a) - __(Oleg Perminov)__ feature: add flexibility to persistent types
17
+ https://jira.railsc.ru/browse/CRM-4532
18
+
19
+ # v1.2.1
20
+
21
+ * 2018-12-27 [dca67bc](../../commit/dca67bc) - __(Andrew N. Shalaev)__ feature: add autopublication to rubygems.org
22
+ * 2018-12-26 [21b57c8](../../commit/21b57c8) - __(Andrew N. Shalaev)__ fix: constraint pg gem
23
+ * 2018-12-21 [2f4ceab](../../commit/2f4ceab) - __(Andrew N. Shalaev)__ feature: add support for redis >= v4
24
+
25
+ # v1.2.0
26
+
27
+ * 2017-11-13 [bd94a94](../../commit/bd94a94) - __(Artem Napolskih)__ fix: specs for redis_counters 1.5
28
+ * 2017-11-13 [5641228](../../commit/5641228) - __(Artem Napolskih)__ chore: remove hstore dependency
29
+
30
+ # v1.1.0
31
+
32
+ Ограничение activesupport нужно, чтобы собрался бандл.
33
+
34
+ * 2017-06-21 [fc29058](../../commit/fc29058) - __(Pavel Galkin)__ feat: matching_expr option for destination
35
+ https://jira.railsc.ru/browse/CK-862 - пункт 4.
36
+
37
+ * 2017-06-20 [d21a7d8](../../commit/d21a7d8) - __(Pavel Galkin)__ chore: update infrastructure
38
+
39
+ # v1.0.0
40
+
41
+ * 2016-10-14 [704ad6d](../../commit/704ad6d) - __(Semyon Pupkov)__ Bump version
42
+ * 2016-09-05 [0bf4850](../../commit/0bf4850) - __(vadshalamov)__ feature: позволит не задавать increment_fields
43
+ * 2016-08-31 [b5c9bd9](../../commit/b5c9bd9) - __(vadshalamov)__ feature: добавит hstore в список возможных полей
44
+ * 2016-08-31 [3b0235c](../../commit/3b0235c) - __(vadshalamov)__ feature: позволит передавать набор аргументов для дампа
45
+ * 2016-07-18 [caa913e](../../commit/caa913e) - __(Stanislav Gordanov)__ feat: добавит enum тип в список возможных полей
46
+ * 2016-05-27 [bbb7119](../../commit/bbb7119) - __(Michail Merkushin)__ fix: Remove CTE favor temp table
47
+ https://jira.railsc.ru/browse/PC4-17052
48
+
49
+ # v0.1.0
50
+
51
+ * 2015-09-10 [1f96c39](../../commit/1f96c39) - __(Zhidkov Denis)__ feat: add source_conditions method
52
+ Adds ability to specify WHERE-clause for select query from source tmp-table
53
+
54
+ * 2015-02-19 [8885300](../../commit/8885300) - __(bibendi)__ add group_by method
55
+
56
+ # v0.0.1
57
+
58
+ * 2015-01-26 [86918bd](../../commit/86918bd) - __(bibendi)__ initial code base
59
+ * 2015-01-26 [a238032](../../commit/a238032) - __(bibendi)__ initial
data/Gemfile CHANGED
@@ -2,5 +2,6 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'activerecord-postgres-hstore', require: false
4
4
  gem 'simple_hstore_accessor', '~> 0.2', require: false
5
+ gem 'pg', '~> 0.11'
5
6
 
6
7
  gemspec
data/dip.yml CHANGED
@@ -1,9 +1,10 @@
1
1
  version: '1'
2
2
 
3
3
  environment:
4
- DOCKER_RUBY_VERSION: 2.2
5
- RUBY_IMAGE_TAG: 2.2-latest
4
+ DOCKER_RUBY_VERSION: 2.4
5
+ RUBY_IMAGE_TAG: 2.4-latest
6
6
  POSTGRES_IMAGE_TAG: 9.6-latest
7
+ REDIS_IMAGE_TAG: 4-alpine
7
8
  COMPOSE_FILE_EXT: development
8
9
 
9
10
  compose:
data/docker-compose.yml CHANGED
@@ -9,11 +9,17 @@ services:
9
9
  - TEST_DB_HOST=db
10
10
  - TEST_DB_NAME=docker
11
11
  - TEST_DB_USERNAME=postgres
12
+ - TEST_REDIS_HOST=redis
12
13
  command: bash
13
14
  depends_on:
14
15
  - db
16
+ - redis
15
17
 
16
18
  db:
17
19
  image: abakpress/postgres-db:$POSTGRES_IMAGE_TAG
18
20
  environment:
19
21
  - POSTGRES_DB=docker
22
+
23
+ redis:
24
+ image: redis:$REDIS_IMAGE_TAG
25
+ command: 'redis-server --bind 0.0.0.0'
@@ -18,6 +18,8 @@ module RedisCounters
18
18
  extend Forwardable
19
19
  include ::RedisCounters::Dumpers::Dsl::Destination
20
20
 
21
+ VALUE_DELIMITER = ','.freeze
22
+
21
23
  # Ссылка на родительский движек - дампер.
22
24
  attr_accessor :engine
23
25
 
@@ -76,6 +78,9 @@ module RedisCounters
76
78
  # Returns String
77
79
  attr_accessor :matching_expr
78
80
 
81
+ # Разделитель значений, String.
82
+ attr_accessor :value_delimiter
83
+
79
84
  def initialize(engine)
80
85
  @engine = engine
81
86
  @fields_map = HashWithIndifferentAccess.new
@@ -174,7 +179,16 @@ module RedisCounters
174
179
  end
175
180
 
176
181
  def updating_expression
177
- increment_fields.map { |field| "#{field} = COALESCE(target.#{field}, 0) + source.#{field}" }.join(', ')
182
+ increment_fields.map do |field|
183
+ case model.columns_hash[field.to_s].type
184
+ when :datetime, :date
185
+ "#{field} = source.#{field}"
186
+ when :text, :string
187
+ "#{field} = array_to_string(ARRAY[source.#{field}, target.#{field}], '#{delimiter}')"
188
+ else
189
+ "#{field} = COALESCE(target.#{field}, 0) + source.#{field}"
190
+ end
191
+ end.join(', ')
178
192
  end
179
193
 
180
194
  def matching_expression
@@ -197,6 +211,10 @@ module RedisCounters
197
211
 
198
212
  "WHERE #{source_conditions.map { |source_condition| "(#{source_condition})" }.join(' AND ')}"
199
213
  end
214
+
215
+ def delimiter
216
+ value_delimiter || VALUE_DELIMITER
217
+ end
200
218
  end
201
219
  end
202
220
  end
@@ -13,6 +13,7 @@ module RedisCounters
13
13
 
14
14
  setter :model
15
15
  setter :matching_expr
16
+ setter :value_delimiter
16
17
 
17
18
  varags_setter :fields
18
19
  varags_setter :key_fields
@@ -234,10 +234,16 @@ module RedisCounters
234
234
  end
235
235
 
236
236
  def redis_session
237
- @redis_session ||= begin
238
- redis = ::Redis.new(counter.redis.client.options)
239
- ::Redis::Namespace.new(counter.redis.namespace, :redis => redis)
240
- end
237
+ return @redis_session if defined?(@redis_session)
238
+
239
+ client = if Gem::Version.new(::Redis::VERSION) < Gem::Version.new('4')
240
+ counter.redis.client
241
+ else
242
+ counter.redis._client
243
+ end
244
+ redis = ::Redis.new(client.options)
245
+
246
+ @redis_session = ::Redis::Namespace.new(counter.redis.namespace, redis: redis)
241
247
  end
242
248
 
243
249
  def create_temp_table
@@ -1,5 +1,5 @@
1
1
  module RedisCounters
2
2
  module Dumpers
3
- VERSION = '1.2.0'.freeze
3
+ VERSION = '1.2.4'.freeze
4
4
  end
5
5
  end
@@ -18,7 +18,6 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.add_runtime_dependency 'activesupport', '>= 3.0', '< 5'
20
20
  spec.add_runtime_dependency 'activerecord', '>= 3.0'
21
- spec.add_runtime_dependency 'pg'
22
21
  spec.add_runtime_dependency 'redis', '>= 3.0'
23
22
  spec.add_runtime_dependency 'redis-namespace', '>= 1.3'
24
23
  spec.add_runtime_dependency 'callbacks_rb', '>= 0.0.1'
@@ -27,10 +26,8 @@ Gem::Specification.new do |spec|
27
26
  spec.add_development_dependency 'bundler', '>= 1.7'
28
27
  spec.add_development_dependency 'rake', '>= 10.0'
29
28
  spec.add_development_dependency 'rspec', '>= 3.2'
30
- spec.add_development_dependency 'rspec-rails', '>= 3.2'
29
+ spec.add_development_dependency 'rspec-rails', '~> 3.9.1'
31
30
  spec.add_development_dependency 'appraisal', '>= 1.0.2'
32
- spec.add_development_dependency 'mock_redis'
33
31
  spec.add_development_dependency 'combustion'
34
32
  spec.add_development_dependency 'pry-byebug'
35
- spec.add_development_dependency 'test-unit'
36
33
  end
@@ -0,0 +1,2 @@
1
+ class RealtimeStat < ActiveRecord::Base
2
+ end
@@ -52,4 +52,12 @@ ActiveRecord::Schema.define do
52
52
  t.integer :value, null: false, default: 0
53
53
  t.string :payload
54
54
  end
55
+
56
+ create_table :realtime_stats do |t|
57
+ t.integer :record_id, null: false
58
+ t.integer :column_id, null: false
59
+ t.integer :hits, null: false, default: 0
60
+ t.timestamp :date
61
+ t.string :params
62
+ end
55
63
  end
@@ -60,105 +60,241 @@ describe RedisCounters::Dumpers::Engine do
60
60
  end
61
61
 
62
62
  before do
63
- allow(dumper).to receive(:redis_session).and_return(MockRedis.new)
63
+ allow(dumper).to receive(:redis_session).and_return(Redis.new(host: ENV['TEST_REDIS_HOST']))
64
64
  end
65
65
 
66
66
  describe '#process!' do
67
67
  context 'when increment_fields specified' do
68
- before do
69
- counter.increment(date: prev_date_s, record_id: 1, column_id: 100, subject: '', params: '')
70
- counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '', params: '')
71
- counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '', params: '')
72
- counter.increment(date: prev_date_s, record_id: 2, column_id: 100, subject: nil, params: '')
68
+ context 'without source conditions' do
69
+ before do
70
+ counter.increment(date: prev_date_s, record_id: 1, column_id: 100, subject: '', params: '')
71
+ counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '', params: '')
72
+ counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '', params: '')
73
+ counter.increment(date: prev_date_s, record_id: 2, column_id: 100, subject: nil, params: '')
73
74
 
74
- params = {a: 1}.stringify_keys.to_s[1..-2]
75
- counter.increment(date: prev_date_s, record_id: 3, column_id: 300, subject: nil, params: params)
75
+ params = {a: 1}.stringify_keys.to_s[1..-2]
76
+ counter.increment(date: prev_date_s, record_id: 3, column_id: 300, subject: nil, params: params)
76
77
 
77
- dumper.process!(counter, date: prev_date)
78
+ dumper.process!(counter, date: prev_date)
78
79
 
79
- counter.increment(date: date_s, record_id: 1, column_id: 100, subject: '', params: '')
80
- counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '', params: '')
81
- counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '', params: '')
82
- counter.increment(date: date_s, record_id: 2, column_id: 100, subject: nil, params: '')
80
+ counter.increment(date: date_s, record_id: 1, column_id: 100, subject: '', params: '')
81
+ counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '', params: '')
82
+ counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '', params: '')
83
+ counter.increment(date: date_s, record_id: 2, column_id: 100, subject: nil, params: '')
83
84
 
84
- dumper.process!(counter, date: date)
85
- end
85
+ dumper.process!(counter, date: date)
86
+ end
86
87
 
87
- it { expect(StatsByDay.count).to eq 7 }
88
- it { expect(StatsByDay.where(record_id: 1, column_id: 100, date: prev_date).first.hits).to eq 1 }
89
- it { expect(StatsByDay.where(record_id: 1, column_id: 200, date: prev_date).first.hits).to eq 2 }
90
- it { expect(StatsByDay.where(record_id: 2, column_id: 100, date: prev_date).first.hits).to eq 1 }
91
- it { expect(StatsByDay.where(record_id: 3, column_id: 300, date: prev_date).first.params).to eq("a" => "1") }
92
- it { expect(StatsByDay.where(record_id: 1, column_id: 100, date: date).first.hits).to eq 1 }
93
- it { expect(StatsByDay.where(record_id: 1, column_id: 200, date: date).first.hits).to eq 2 }
94
- it { expect(StatsByDay.where(record_id: 2, column_id: 100, date: date).first.hits).to eq 1 }
88
+ it { expect(StatsByDay.count).to eq 7 }
89
+ it { expect(StatsByDay.where(record_id: 1, column_id: 100, date: prev_date).first.hits).to eq 1 }
90
+ it { expect(StatsByDay.where(record_id: 1, column_id: 200, date: prev_date).first.hits).to eq 2 }
91
+ it { expect(StatsByDay.where(record_id: 2, column_id: 100, date: prev_date).first.hits).to eq 1 }
92
+ it { expect(StatsByDay.where(record_id: 3, column_id: 300, date: prev_date).first.params).to eq("a" => "1") }
93
+ it { expect(StatsByDay.where(record_id: 1, column_id: 100, date: date).first.hits).to eq 1 }
94
+ it { expect(StatsByDay.where(record_id: 1, column_id: 200, date: date).first.hits).to eq 2 }
95
+ it { expect(StatsByDay.where(record_id: 2, column_id: 100, date: date).first.hits).to eq 1 }
95
96
 
96
- it { expect(StatsTotal.count).to eq 4 }
97
- it { expect(StatsTotal.where(record_id: 1, column_id: 100).first.hits).to eq 2 }
98
- it { expect(StatsTotal.where(record_id: 1, column_id: 200).first.hits).to eq 4 }
99
- it { expect(StatsTotal.where(record_id: 2, column_id: 100).first.hits).to eq 2 }
97
+ it { expect(StatsTotal.count).to eq 4 }
98
+ it { expect(StatsTotal.where(record_id: 1, column_id: 100).first.hits).to eq 2 }
99
+ it { expect(StatsTotal.where(record_id: 1, column_id: 200).first.hits).to eq 4 }
100
+ it { expect(StatsTotal.where(record_id: 2, column_id: 100).first.hits).to eq 2 }
100
101
 
101
- it { expect(StatsAggTotal.count).to eq 3 }
102
- it { expect(StatsAggTotal.where(record_id: 1).first.hits).to eq 6 }
103
- it { expect(StatsAggTotal.where(record_id: 2).first.hits).to eq 2 }
102
+ it { expect(StatsAggTotal.count).to eq 3 }
103
+ it { expect(StatsAggTotal.where(record_id: 1).first.hits).to eq 6 }
104
+ it { expect(StatsAggTotal.where(record_id: 2).first.hits).to eq 2 }
105
+ end
104
106
 
105
107
  context 'with source conditions' do
108
+ context 'when incremented field class is integer' do
109
+ let(:dumper) do
110
+ RedisCounters::Dumpers::Engine.build do
111
+ name :stats_totals
112
+ fields record_id: :integer,
113
+ column_id: :integer,
114
+ value: :integer,
115
+ date: :date
116
+
117
+ destination do
118
+ model StatsByDay
119
+ take :record_id, :column_id, :hits, :date
120
+ key_fields :record_id, :column_id, :date
121
+ increment_fields :hits
122
+ map :hits, to: :value
123
+ condition 'target.date = :date'
124
+ source_condition 'column_id = 100'
125
+ end
126
+
127
+ destination do
128
+ model StatsTotal
129
+ take :record_id, :column_id, :hits
130
+ key_fields :record_id, :column_id
131
+ increment_fields :hits
132
+ map :hits, to: :value
133
+ source_condition 'column_id = 100'
134
+ end
135
+
136
+ destination do
137
+ model StatsAggTotal
138
+ take :record_id, :hits
139
+ key_fields :record_id
140
+ increment_fields :hits
141
+ map :hits, to: 'sum(value)'
142
+ group_by :record_id
143
+ source_condition 'column_id = 100'
144
+ end
145
+
146
+ on_before_merge do |dumper, _connection|
147
+ dumper.common_params = {date: dumper.args[:date].strftime('%Y-%m-%d')}
148
+ end
149
+ end
150
+ end
151
+
152
+ before do
153
+ counter.increment(date: prev_date_s, record_id: 1, column_id: 100, subject: '', params: '')
154
+ counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '', params: '')
155
+ counter.increment(date: prev_date_s, record_id: 1, column_id: 200, subject: '', params: '')
156
+ counter.increment(date: prev_date_s, record_id: 2, column_id: 100, subject: nil, params: '')
157
+
158
+ params = {a: 1}.stringify_keys.to_s[1..-2]
159
+ counter.increment(date: prev_date_s, record_id: 3, column_id: 300, subject: nil, params: params)
160
+
161
+ dumper.process!(counter, date: prev_date)
162
+
163
+ counter.increment(date: date_s, record_id: 1, column_id: 100, subject: '', params: '')
164
+ counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '', params: '')
165
+ counter.increment(date: date_s, record_id: 1, column_id: 200, subject: '', params: '')
166
+ counter.increment(date: date_s, record_id: 2, column_id: 100, subject: nil, params: '')
167
+
168
+ dumper.process!(counter, date: date)
169
+ end
170
+
171
+ it { expect(StatsByDay.count).to eq 4 }
172
+ it { expect(StatsByDay.where(record_id: 1, column_id: 100, date: prev_date).first.hits).to eq 1 }
173
+ it { expect(StatsByDay.where(record_id: 2, column_id: 100, date: prev_date).first.hits).to eq 1 }
174
+ it { expect(StatsByDay.where(record_id: 1, column_id: 100, date: date).first.hits).to eq 1 }
175
+ it { expect(StatsByDay.where(record_id: 2, column_id: 100, date: date).first.hits).to eq 1 }
176
+
177
+ it { expect(StatsTotal.count).to eq 2 }
178
+ it { expect(StatsTotal.where(record_id: 1, column_id: 100).first.hits).to eq 2 }
179
+ it { expect(StatsTotal.where(record_id: 2, column_id: 100).first.hits).to eq 2 }
180
+
181
+ it { expect(StatsAggTotal.count).to eq 2 }
182
+ it { expect(StatsAggTotal.where(record_id: 1).first.hits).to eq 2 }
183
+ it { expect(StatsAggTotal.where(record_id: 2).first.hits).to eq 2 }
184
+ end
185
+ end
186
+
187
+ context 'when incremented field class is string' do
106
188
  let(:dumper) do
107
189
  RedisCounters::Dumpers::Engine.build do
108
- name :stats_totals
190
+ name :realtime_stats
109
191
  fields record_id: :integer,
110
192
  column_id: :integer,
111
193
  value: :integer,
112
- date: :date
194
+ params: :string,
195
+ date: :timestamp
113
196
 
114
197
  destination do
115
- model StatsByDay
116
- take :record_id, :column_id, :hits, :date
117
- key_fields :record_id, :column_id, :date
118
- increment_fields :hits
198
+ model RealtimeStat
199
+ take :record_id, :column_id, :date, :hits, :params
200
+ key_fields :record_id, :column_id
201
+ increment_fields :hits, :params
202
+ value_delimiter '; '
119
203
  map :hits, to: :value
120
- condition 'target.date = :date'
121
- source_condition 'column_id = 100'
204
+ condition 'target.date::date = :date::date'
122
205
  end
206
+ end
207
+ end
208
+
209
+ before do
210
+ counter.increment(date: date, record_id: 1, column_id: 100, subject: '', params: 'abc')
211
+ dumper.common_params = {date: date, params: 'abc'}
212
+ dumper.process!(counter, date: date)
213
+
214
+ counter.increment(date: date, record_id: 1, column_id: 100, subject: '', params: 'xyz')
215
+ dumper.common_params = {date: date, params: 'xyz'}
216
+ dumper.process!(counter, date: date)
217
+ end
218
+
219
+ it do
220
+ expect(RealtimeStat.count).to eq 1
221
+ expect(RealtimeStat.first.params).to eq 'xyz; abc'
222
+ end
223
+ end
224
+
225
+ context 'when incremented field class is text' do
226
+ let(:dumper) do
227
+ RedisCounters::Dumpers::Engine.build do
228
+ name :realtime_stats
229
+ fields record_id: :integer,
230
+ column_id: :integer,
231
+ value: :integer,
232
+ params: :text,
233
+ date: :timestamp
123
234
 
124
235
  destination do
125
- model StatsTotal
126
- take :record_id, :column_id, :hits
236
+ model RealtimeStat
237
+ take :record_id, :column_id, :date, :hits, :params
127
238
  key_fields :record_id, :column_id
128
- increment_fields :hits
239
+ increment_fields :hits, :params
129
240
  map :hits, to: :value
130
- source_condition 'column_id = 100'
241
+ condition 'target.date::date = :date::date'
131
242
  end
243
+ end
244
+ end
132
245
 
133
- destination do
134
- model StatsAggTotal
135
- take :record_id, :hits
136
- key_fields :record_id
137
- increment_fields :hits
138
- map :hits, to: 'sum(value)'
139
- group_by :record_id
140
- source_condition 'column_id = 100'
141
- end
246
+ before do
247
+ counter.increment(date: date, record_id: 1, column_id: 100, subject: '', params: 'abc')
248
+ dumper.common_params = {date: date, params: 'abc'}
249
+ dumper.process!(counter, date: date)
250
+
251
+ counter.increment(date: date, record_id: 1, column_id: 100, subject: '', params: 'xyz')
252
+ dumper.common_params = {date: date, params: 'xyz'}
253
+ dumper.process!(counter, date: date)
254
+ end
255
+
256
+ it do
257
+ expect(RealtimeStat.count).to eq 1
258
+ expect(RealtimeStat.first.params).to eq 'xyz,abc'
259
+ end
260
+ end
261
+
262
+ context 'when incremented field class is date or time' do
263
+ let(:current_time) { Date.today.to_time }
264
+ let(:dumper) do
265
+ RedisCounters::Dumpers::Engine.build do
266
+ name :realtime_stats
267
+ fields record_id: :integer,
268
+ column_id: :integer,
269
+ value: :integer,
270
+ params: :string,
271
+ date: :timestamp
142
272
 
143
- on_before_merge do |dumper, _connection|
144
- dumper.common_params = {date: dumper.args[:date].strftime('%Y-%m-%d')}
273
+ destination do
274
+ model RealtimeStat
275
+ take :record_id, :column_id, :hits, :params, :date
276
+ key_fields :record_id, :column_id
277
+ increment_fields :hits, :date
278
+ map :hits, to: :value
279
+ condition 'target.date::date = :date::date'
145
280
  end
146
281
  end
147
282
  end
148
283
 
149
- it { expect(StatsByDay.count).to eq 4 }
150
- it { expect(StatsByDay.where(record_id: 1, column_id: 100, date: prev_date).first.hits).to eq 1 }
151
- it { expect(StatsByDay.where(record_id: 2, column_id: 100, date: prev_date).first.hits).to eq 1 }
152
- it { expect(StatsByDay.where(record_id: 1, column_id: 100, date: date).first.hits).to eq 1 }
153
- it { expect(StatsByDay.where(record_id: 2, column_id: 100, date: date).first.hits).to eq 1 }
284
+ before do
285
+ counter.increment(date: date, record_id: 1, column_id: 100, subject: '', params: '')
286
+ dumper.common_params = {date: current_time}
287
+ dumper.process!(counter, date: date)
154
288
 
155
- it { expect(StatsTotal.count).to eq 2 }
156
- it { expect(StatsTotal.where(record_id: 1, column_id: 100).first.hits).to eq 2 }
157
- it { expect(StatsTotal.where(record_id: 2, column_id: 100).first.hits).to eq 2 }
289
+ counter.increment(date: date, record_id: 1, column_id: 100, subject: '', params: '')
290
+ dumper.common_params = {date: current_time}
291
+ dumper.process!(counter, date: date)
292
+ end
158
293
 
159
- it { expect(StatsAggTotal.count).to eq 2 }
160
- it { expect(StatsAggTotal.where(record_id: 1).first.hits).to eq 2 }
161
- it { expect(StatsAggTotal.where(record_id: 2).first.hits).to eq 2 }
294
+ it 'update incremented date' do
295
+ expect(RealtimeStat.count).to eq 1
296
+ expect(RealtimeStat.first.date).to eq current_time
297
+ end
162
298
  end
163
299
  end
164
300
 
data/spec/spec_helper.rb CHANGED
@@ -1,19 +1,13 @@
1
1
  require 'redis_counters/dumpers'
2
2
 
3
- if ::ActiveRecord::VERSION::MAJOR < 4
4
- require 'activerecord-postgres-hstore'
5
- require 'simple_hstore_accessor'
6
- end
7
-
8
3
  require 'combustion'
9
4
  Combustion.initialize! :active_record
10
5
 
11
6
  require 'rspec/rails'
12
7
  require 'pry-byebug'
13
8
 
14
- require 'mock_redis'
15
9
  require 'redis'
16
- Redis.current = MockRedis.new
10
+ Redis.current = Redis.new(host: ENV['TEST_REDIS_HOST'])
17
11
 
18
12
  RSpec.configure do |config|
19
13
  config.use_transactional_fixtures = true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis_counters-dumpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Merkushin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-13 00:00:00.000000000 Z
11
+ date: 2021-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -44,20 +44,6 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '3.0'
47
- - !ruby/object:Gem::Dependency
48
- name: pg
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: '0'
54
- type: :runtime
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: '0'
61
47
  - !ruby/object:Gem::Dependency
62
48
  name: redis
63
49
  requirement: !ruby/object:Gem::Requirement
@@ -160,16 +146,16 @@ dependencies:
160
146
  name: rspec-rails
161
147
  requirement: !ruby/object:Gem::Requirement
162
148
  requirements:
163
- - - ">="
149
+ - - "~>"
164
150
  - !ruby/object:Gem::Version
165
- version: '3.2'
151
+ version: 3.9.1
166
152
  type: :development
167
153
  prerelease: false
168
154
  version_requirements: !ruby/object:Gem::Requirement
169
155
  requirements:
170
- - - ">="
156
+ - - "~>"
171
157
  - !ruby/object:Gem::Version
172
- version: '3.2'
158
+ version: 3.9.1
173
159
  - !ruby/object:Gem::Dependency
174
160
  name: appraisal
175
161
  requirement: !ruby/object:Gem::Requirement
@@ -184,20 +170,6 @@ dependencies:
184
170
  - - ">="
185
171
  - !ruby/object:Gem::Version
186
172
  version: 1.0.2
187
- - !ruby/object:Gem::Dependency
188
- name: mock_redis
189
- requirement: !ruby/object:Gem::Requirement
190
- requirements:
191
- - - ">="
192
- - !ruby/object:Gem::Version
193
- version: '0'
194
- type: :development
195
- prerelease: false
196
- version_requirements: !ruby/object:Gem::Requirement
197
- requirements:
198
- - - ">="
199
- - !ruby/object:Gem::Version
200
- version: '0'
201
173
  - !ruby/object:Gem::Dependency
202
174
  name: combustion
203
175
  requirement: !ruby/object:Gem::Requirement
@@ -226,20 +198,6 @@ dependencies:
226
198
  - - ">="
227
199
  - !ruby/object:Gem::Version
228
200
  version: '0'
229
- - !ruby/object:Gem::Dependency
230
- name: test-unit
231
- requirement: !ruby/object:Gem::Requirement
232
- requirements:
233
- - - ">="
234
- - !ruby/object:Gem::Version
235
- version: '0'
236
- type: :development
237
- prerelease: false
238
- version_requirements: !ruby/object:Gem::Requirement
239
- requirements:
240
- - - ">="
241
- - !ruby/object:Gem::Version
242
- version: '0'
243
201
  description:
244
202
  email:
245
203
  - bibendi@bk.ru
@@ -270,6 +228,7 @@ files:
270
228
  - lib/redis_counters/dumpers/version.rb
271
229
  - redis_counters-dumpers.gemspec
272
230
  - spec/internal/app/models/nullable_stat.rb
231
+ - spec/internal/app/models/realtime_stat.rb
273
232
  - spec/internal/app/models/stat.rb
274
233
  - spec/internal/app/models/stats_agg_total.rb
275
234
  - spec/internal/app/models/stats_by_day.rb
@@ -298,12 +257,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
298
257
  version: '0'
299
258
  requirements: []
300
259
  rubyforge_project:
301
- rubygems_version: 2.5.1
260
+ rubygems_version: 2.6.1
302
261
  signing_key:
303
262
  specification_version: 4
304
263
  summary: Dump statistics from Redis to DB
305
264
  test_files:
306
265
  - spec/internal/app/models/nullable_stat.rb
266
+ - spec/internal/app/models/realtime_stat.rb
307
267
  - spec/internal/app/models/stat.rb
308
268
  - spec/internal/app/models/stats_agg_total.rb
309
269
  - spec/internal/app/models/stats_by_day.rb