deimos-ruby 1.6.1 → 1.6.2

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 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