deimos-ruby 1.6.1 → 1.6.2

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: '0226368aa5a493ec167e0cd4b0d03eeb8ac9e3efe8c2518fbe869275f6b7b10b'
4
- data.tar.gz: 94afab34fb599d3cc0a5336a0af1ab8458621c8655c22de6882d1b87a645d8bf
3
+ metadata.gz: 53aab4ddcc19808cf7149ed226de9b7ddda07d12ed4237c157cce75780379c6c
4
+ data.tar.gz: 74ebf879894b88fc4ce5082d4f8b82f8f79a0ef581bf368f25423a755d71d635
5
5
  SHA512:
6
- metadata.gz: ee0516157c9fedd3e0ad9ff5dab95afbd9d3eee0975c899ede0f8104c1c9b5e992117221a8e42772f397abc3b8e70c755a90423a8d3daf93fd949751b3095f38
7
- data.tar.gz: e42ad9fca0314bfa6cf5f764f7369a22a28d60c4d395b219df2d0c1ad1bb0c2d45a37d9e5eeb76984dbd7d122f211f4f8bbf8a5d0198108346bc8c16df795266
6
+ metadata.gz: 4c0fa67f0b958ddc3083c278c5c195f896b134f822168df245e906e89f5f5414f063175e2ed1a444891a210d28e7a0d96836806b6ba2efd6f55bf46d929450c1
7
+ data.tar.gz: 9fc31899551ec75dc0ca1e7ac02cc3f4ed429ec8eb25f42057024d2dc9cde5bef70eabafcf8276e7a8a4ae2b7a88b4efff5efe047715612bd5f5480ce1f52576
data/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## UNRELEASED
9
9
 
10
+ ## 1.6.2 - 2020-05-04
11
+ ### Fixes :wrench:
12
+ - When saving records via `ActiveRecordConsumer`, update `updated_at` to today's time
13
+ even if nothing else was saved.
14
+ - When logging payloads and metadata, decode them first.
15
+ - Fixes bug in `KafkaSource` that crashes when importing a mix of existing and new records with the `:on_duplicate_key_update` option.
16
+
10
17
  ## [1.6.1] - 2020-04-20
11
18
  ### Fixes :wrench:
12
19
  - Re-consuming a message after crashing would try to re-decode message keys.
data/Gemfile.lock CHANGED
@@ -9,45 +9,45 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- actioncable (5.2.4)
13
- actionpack (= 5.2.4)
12
+ actioncable (5.2.4.2)
13
+ actionpack (= 5.2.4.2)
14
14
  nio4r (~> 2.0)
15
15
  websocket-driver (>= 0.6.1)
16
- actionmailer (5.2.4)
17
- actionpack (= 5.2.4)
18
- actionview (= 5.2.4)
19
- activejob (= 5.2.4)
16
+ actionmailer (5.2.4.2)
17
+ actionpack (= 5.2.4.2)
18
+ actionview (= 5.2.4.2)
19
+ activejob (= 5.2.4.2)
20
20
  mail (~> 2.5, >= 2.5.4)
21
21
  rails-dom-testing (~> 2.0)
22
- actionpack (5.2.4)
23
- actionview (= 5.2.4)
24
- activesupport (= 5.2.4)
25
- rack (~> 2.0)
22
+ actionpack (5.2.4.2)
23
+ actionview (= 5.2.4.2)
24
+ activesupport (= 5.2.4.2)
25
+ rack (~> 2.0, >= 2.0.8)
26
26
  rack-test (>= 0.6.3)
27
27
  rails-dom-testing (~> 2.0)
28
28
  rails-html-sanitizer (~> 1.0, >= 1.0.2)
29
- actionview (5.2.4)
30
- activesupport (= 5.2.4)
29
+ actionview (5.2.4.2)
30
+ activesupport (= 5.2.4.2)
31
31
  builder (~> 3.1)
32
32
  erubi (~> 1.4)
33
33
  rails-dom-testing (~> 2.0)
34
34
  rails-html-sanitizer (~> 1.0, >= 1.0.3)
35
- activejob (5.2.4)
36
- activesupport (= 5.2.4)
35
+ activejob (5.2.4.2)
36
+ activesupport (= 5.2.4.2)
37
37
  globalid (>= 0.3.6)
38
- activemodel (5.2.4)
39
- activesupport (= 5.2.4)
40
- activerecord (5.2.4)
41
- activemodel (= 5.2.4)
42
- activesupport (= 5.2.4)
38
+ activemodel (5.2.4.2)
39
+ activesupport (= 5.2.4.2)
40
+ activerecord (5.2.4.2)
41
+ activemodel (= 5.2.4.2)
42
+ activesupport (= 5.2.4.2)
43
43
  arel (>= 9.0)
44
44
  activerecord-import (1.0.3)
45
45
  activerecord (>= 3.2)
46
- activestorage (5.2.4)
47
- actionpack (= 5.2.4)
48
- activerecord (= 5.2.4)
46
+ activestorage (5.2.4.2)
47
+ actionpack (= 5.2.4.2)
48
+ activerecord (= 5.2.4.2)
49
49
  marcel (~> 0.3.1)
50
- activesupport (5.2.4)
50
+ activesupport (5.2.4.2)
51
51
  concurrent-ruby (~> 1.0, >= 1.0.2)
52
52
  i18n (>= 0.7, < 2)
53
53
  minitest (~> 5.1)
@@ -64,7 +64,7 @@ GEM
64
64
  concurrent-ruby (1.1.5)
65
65
  concurrent-ruby-ext (1.1.5)
66
66
  concurrent-ruby (= 1.1.5)
67
- crass (1.0.5)
67
+ crass (1.0.6)
68
68
  ddtrace (0.30.0)
69
69
  msgpack
70
70
  diff-lcs (1.3)
@@ -94,7 +94,7 @@ GEM
94
94
  guard-rubocop (1.3.0)
95
95
  guard (~> 2.0)
96
96
  rubocop (~> 0.20)
97
- i18n (1.7.0)
97
+ i18n (1.8.2)
98
98
  concurrent-ruby (~> 1.0)
99
99
  jaro_winkler (1.5.4)
100
100
  listen (3.2.1)
@@ -104,7 +104,7 @@ GEM
104
104
  logging (2.2.2)
105
105
  little-plugger (~> 1.1)
106
106
  multi_json (~> 1.10)
107
- loofah (2.4.0)
107
+ loofah (2.5.0)
108
108
  crass (~> 1.0.2)
109
109
  nokogiri (>= 1.5.9)
110
110
  lumberjack (1.0.13)
@@ -113,16 +113,16 @@ GEM
113
113
  marcel (0.3.3)
114
114
  mimemagic (~> 0.3.2)
115
115
  method_source (0.9.2)
116
- mimemagic (0.3.3)
116
+ mimemagic (0.3.4)
117
117
  mini_mime (1.0.2)
118
118
  mini_portile2 (2.4.0)
119
- minitest (5.13.0)
119
+ minitest (5.14.0)
120
120
  msgpack (1.3.1)
121
121
  multi_json (1.14.1)
122
122
  mysql2 (0.5.3)
123
123
  nenv (0.3.0)
124
124
  nio4r (2.5.2)
125
- nokogiri (1.10.8)
125
+ nokogiri (1.10.9)
126
126
  mini_portile2 (~> 2.4.0)
127
127
  notiffany (0.1.3)
128
128
  nenv (~> 0.1)
@@ -142,30 +142,30 @@ GEM
142
142
  pry (0.12.2)
143
143
  coderay (~> 1.1.0)
144
144
  method_source (~> 0.9.0)
145
- rack (2.0.8)
145
+ rack (2.2.2)
146
146
  rack-test (1.1.0)
147
147
  rack (>= 1.0, < 3)
148
- rails (5.2.4)
149
- actioncable (= 5.2.4)
150
- actionmailer (= 5.2.4)
151
- actionpack (= 5.2.4)
152
- actionview (= 5.2.4)
153
- activejob (= 5.2.4)
154
- activemodel (= 5.2.4)
155
- activerecord (= 5.2.4)
156
- activestorage (= 5.2.4)
157
- activesupport (= 5.2.4)
148
+ rails (5.2.4.2)
149
+ actioncable (= 5.2.4.2)
150
+ actionmailer (= 5.2.4.2)
151
+ actionpack (= 5.2.4.2)
152
+ actionview (= 5.2.4.2)
153
+ activejob (= 5.2.4.2)
154
+ activemodel (= 5.2.4.2)
155
+ activerecord (= 5.2.4.2)
156
+ activestorage (= 5.2.4.2)
157
+ activesupport (= 5.2.4.2)
158
158
  bundler (>= 1.3.0)
159
- railties (= 5.2.4)
159
+ railties (= 5.2.4.2)
160
160
  sprockets-rails (>= 2.0.0)
161
161
  rails-dom-testing (2.0.3)
162
162
  activesupport (>= 4.2.0)
163
163
  nokogiri (>= 1.6)
164
164
  rails-html-sanitizer (1.3.0)
165
165
  loofah (~> 2.3)
166
- railties (5.2.4)
167
- actionpack (= 5.2.4)
168
- activesupport (= 5.2.4)
166
+ railties (5.2.4.2)
167
+ actionpack (= 5.2.4.2)
168
+ activesupport (= 5.2.4.2)
169
169
  method_source
170
170
  rake (>= 0.8.7)
171
171
  thor (>= 0.19.0, < 2.0)
@@ -212,7 +212,7 @@ GEM
212
212
  sqlite3 (1.4.1)
213
213
  thor (1.0.1)
214
214
  thread_safe (0.3.6)
215
- tzinfo (1.2.5)
215
+ tzinfo (1.2.7)
216
216
  thread_safe (~> 0.1)
217
217
  unicode-display_width (1.6.0)
218
218
  websocket-driver (0.7.1)
@@ -235,7 +235,7 @@ DEPENDENCIES
235
235
  guard-rubocop (~> 1)
236
236
  mysql2 (~> 0.5)
237
237
  pg (~> 1.1)
238
- rails (~> 5.2)
238
+ rails (~> 5.2, >= 5.2.4.2)
239
239
  rake (~> 13)
240
240
  rspec (~> 3)
241
241
  rspec_junit_formatter (~> 0.3)
data/deimos-ruby.gemspec CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency('guard-rubocop', '~> 1')
34
34
  spec.add_development_dependency('mysql2', '~> 0.5')
35
35
  spec.add_development_dependency('pg', '~> 1.1')
36
- spec.add_development_dependency('rails', '~> 5.2')
36
+ spec.add_development_dependency('rails', '~> 5.2', '>= 5.2.4.2')
37
37
  spec.add_development_dependency('rake', '~> 13')
38
38
  spec.add_development_dependency('rspec', '~> 3')
39
39
  spec.add_development_dependency('rspec_junit_formatter', '~>0.3')
@@ -51,7 +51,7 @@ module Deimos
51
51
  record.send("#{k}=", v)
52
52
  end
53
53
  record.created_at ||= Time.zone.now if record.respond_to?(:created_at)
54
- record.updated_at ||= Time.zone.now if record.respond_to?(:updated_at)
54
+ record.updated_at = Time.zone.now if record.respond_to?(:updated_at)
55
55
  record.save!
56
56
  end
57
57
 
@@ -15,12 +15,12 @@ module Deimos
15
15
 
16
16
  # :nodoc:
17
17
  def around_consume(payload, metadata)
18
- _received_message(payload, metadata)
19
18
  benchmark = Benchmark.measure do
20
19
  _with_error_span(payload, metadata) do
21
20
  new_metadata = metadata.dup
22
21
  new_metadata[:key] = decode_key(metadata[:key]) if self.class.config[:key_configured]
23
22
  decoded_payload = payload ? self.class.decoder.decode(payload) : nil
23
+ _received_message(payload, metadata)
24
24
  yield decoded_payload, new_metadata
25
25
  end
26
26
  end
@@ -93,31 +93,37 @@ module Deimos
93
93
 
94
94
  # This will contain an array of hashes, where each hash is the actual
95
95
  # attribute hash that created the object.
96
- ids = if results.is_a?(Array)
97
- results[1]
98
- elsif results.respond_to?(:ids)
99
- results.ids
100
- else
101
- []
102
- end
103
- if ids.blank?
104
- # re-fill IDs based on what was just entered into the DB.
105
- if self.connection.adapter_name.downcase =~ /sqlite/
106
- last_id = self.connection.select_value('select last_insert_rowid()')
107
- ids = ((last_id - array_of_attributes.size + 1)..last_id).to_a
108
- else # mysql
109
- last_id = self.connection.select_value('select LAST_INSERT_ID()')
110
- ids = (last_id..(last_id + array_of_attributes.size)).to_a
111
- end
112
- end
113
96
  array_of_hashes = []
114
- array_of_attributes.each_with_index do |array, i|
115
- hash = column_names.zip(array).to_h.with_indifferent_access
116
- hash[self.primary_key] = ids[i] if hash[self.primary_key].blank?
117
- array_of_hashes << hash
97
+ array_of_attributes.each do |array|
98
+ array_of_hashes << column_names.zip(array).to_h.with_indifferent_access
99
+ end
100
+ hashes_with_id, hashes_without_id = array_of_hashes.partition { |arr| arr[:id].present? }
101
+
102
+ self.kafka_producers.each { |p| p.send_events(hashes_with_id) }
103
+
104
+ if hashes_without_id.any?
105
+ if options[:on_duplicate_key_update].present? &&
106
+ options[:on_duplicate_key_update] != [:updated_at]
107
+ unique_columns = column_names.map(&:to_s) -
108
+ options[:on_duplicate_key_update].map(&:to_s) - %w(id created_at)
109
+ records = hashes_without_id.map do |hash|
110
+ self.where(unique_columns.map { |c| [c, hash[c]] }.to_h).first
111
+ end
112
+ self.kafka_producers.each { |p| p.send_events(records) }
113
+ else
114
+ # re-fill IDs based on what was just entered into the DB.
115
+ last_id = if self.connection.adapter_name.downcase =~ /sqlite/
116
+ self.connection.select_value('select last_insert_rowid()') -
117
+ hashes_without_id.size + 1
118
+ else # mysql
119
+ self.connection.select_value('select LAST_INSERT_ID()')
120
+ end
121
+ hashes_without_id.each_with_index do |attrs, i|
122
+ attrs[:id] = last_id + i
123
+ end
124
+ self.kafka_producers.each { |p| p.send_events(hashes_without_id) }
125
+ end
118
126
  end
119
-
120
- self.kafka_producers.each { |p| p.send_events(array_of_hashes) }
121
127
  results
122
128
  end
123
129
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Deimos
4
- VERSION = '1.6.1'
4
+ VERSION = '1.6.2'
5
5
  end
@@ -22,6 +22,10 @@ module ActiveRecordProducerTest
22
22
  Widget.reset_column_information
23
23
  end
24
24
 
25
+ before(:each) do
26
+ Widget.delete_all
27
+ end
28
+
25
29
  after(:all) do
26
30
  ActiveRecord::Base.connection.drop_table(:widgets)
27
31
  end
@@ -101,6 +105,21 @@ module ActiveRecordProducerTest
101
105
 
102
106
  end
103
107
 
108
+ it 'should update only updated_at' do
109
+ travel_to Time.local(2020, 5, 5, 5, 5, 5)
110
+ widget1 = Widget.create!(test_id: 'id1', some_int: 3)
111
+ expect(widget1.updated_at.in_time_zone).to eq(Time.local(2020, 5, 5, 5, 5, 5))
112
+
113
+ travel 1.day
114
+ test_consume_message(MyCustomFetchConsumer, {
115
+ test_id: 'id1',
116
+ some_int: 3
117
+ }, { call_original: true })
118
+ expect(widget1.reload.updated_at.in_time_zone).
119
+ to eq(Time.local(2020, 5, 6, 5, 5, 5))
120
+ travel_back
121
+ end
122
+
104
123
  it 'should find widgets by custom logic' do
105
124
  widget1 = Widget.create!(test_id: 'id1')
106
125
  expect(widget1.some_int).to be_nil
@@ -126,6 +126,59 @@ module KafkaSourceSpec
126
126
  }, widgets[2].id)
127
127
  end
128
128
 
129
+ it 'should send events on import with on_duplicate_key_update and existing records' do
130
+ widget1 = Widget.create(widget_id: 1, name: 'Widget 1')
131
+ widget2 = Widget.create(widget_id: 2, name: 'Widget 2')
132
+ widget1.name = 'New Widget 1'
133
+ widget2.name = 'New Widget 2'
134
+ Widget.import([widget1, widget2], on_duplicate_key_update: %i(widget_id name))
135
+
136
+ expect('my-topic').to have_sent({
137
+ widget_id: 1,
138
+ name: 'New Widget 1',
139
+ id: widget1.id,
140
+ created_at: anything,
141
+ updated_at: anything
142
+ }, widget1.id)
143
+ expect('my-topic').to have_sent({
144
+ widget_id: 2,
145
+ name: 'New Widget 2',
146
+ id: widget2.id,
147
+ created_at: anything,
148
+ updated_at: anything
149
+ }, widget2.id)
150
+ end
151
+
152
+ it 'should not fail when mixing existing and new records for import :on_duplicate_key_update' do
153
+ widget1 = Widget.create(widget_id: 1, name: 'Widget 1')
154
+ expect('my-topic').to have_sent({
155
+ widget_id: 1,
156
+ name: 'Widget 1',
157
+ id: widget1.id,
158
+ created_at: anything,
159
+ updated_at: anything
160
+ }, widget1.id)
161
+
162
+ widget2 = Widget.new(widget_id: 2, name: 'Widget 2')
163
+ widget1.name = 'New Widget 1'
164
+ Widget.import([widget1, widget2], on_duplicate_key_update: %i(widget_id))
165
+ widgets = Widget.all
166
+ expect('my-topic').to have_sent({
167
+ widget_id: 1,
168
+ name: 'New Widget 1',
169
+ id: widgets[0].id,
170
+ created_at: anything,
171
+ updated_at: anything
172
+ }, widgets[0].id)
173
+ expect('my-topic').to have_sent({
174
+ widget_id: 2,
175
+ name: 'Widget 2',
176
+ id: widgets[1].id,
177
+ created_at: anything,
178
+ updated_at: anything
179
+ }, widgets[1].id)
180
+ end
181
+
129
182
  it 'should send events even if the save fails' do
130
183
  widget = Widget.create!(widget_id: 1, name: 'widget')
131
184
  expect('my-topic').to have_sent({
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deimos-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
4
+ version: 1.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Orner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-20 00:00:00.000000000 Z
11
+ date: 2020-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: avro_turf
@@ -213,6 +213,9 @@ dependencies:
213
213
  - - "~>"
214
214
  - !ruby/object:Gem::Version
215
215
  version: '5.2'
216
+ - - ">="
217
+ - !ruby/object:Gem::Version
218
+ version: 5.2.4.2
216
219
  type: :development
217
220
  prerelease: false
218
221
  version_requirements: !ruby/object:Gem::Requirement
@@ -220,6 +223,9 @@ dependencies:
220
223
  - - "~>"
221
224
  - !ruby/object:Gem::Version
222
225
  version: '5.2'
226
+ - - ">="
227
+ - !ruby/object:Gem::Version
228
+ version: 5.2.4.2
223
229
  - !ruby/object:Gem::Dependency
224
230
  name: rake
225
231
  requirement: !ruby/object:Gem::Requirement