deimos-ruby 2.6.0 → 2.6.1

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: 3399390b0e3dc85c67c95c4d633d3ce65efb80258848e73c6b0fa5d9244db13e
4
- data.tar.gz: d236d19cd353f581121dbf561cba34ff78a192bd636ac992fcb1ad87b5913375
3
+ metadata.gz: 132519f800025ce3300467213dfaa1136cbbb1ffe9c17074a09c84fd5292c151
4
+ data.tar.gz: cee617e162f21cee7e7d62c0c31a9b37451273a42be8d4007e94fb998b94ddb2
5
5
  SHA512:
6
- metadata.gz: 502f900a5d5220c55d13bbc50ab329c826d3da953b14adfbaaaf1668e229d2ede46268729ed3c7bc631045feb6927fe85126a6b990f28b4f00630efdb0bb5501
7
- data.tar.gz: 44d082485bfb68be5b2c49f228ab29626eb5c7b80b98873284a7844fba55c881ac805d0ce9db2c9d2f44f8b68eb781f541a5d1d0099b94f2f7ee236a29197093
6
+ metadata.gz: 865fd30cd8674ab0b311664f1ce0692c043f46fd742e2d52cc5c72f62d91e9ccd908bed6c97a27eb0d81702f7c1b866ccd225ebde2f78ea2d73e8ec50f22fbad
7
+ data.tar.gz: 68c968a36f4eb6688d5877eb6514e4a8abe981336f2847b246aded7aeb3521ce2d92583bac1366b36865d7eb8e95f8c9133d79395f5e68f5ce56947788f47d65
data/CHANGELOG.md CHANGED
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## Unreleased
9
+
10
+ ## 2.6.1 - 2026-09-03
11
+
12
+ - Fix: `KafkaTopicInfo.lock` only attempts the `INSERT` when the topic row is missing, instead of relying on a unique-index failure. On MySQL a failed insert still consumes an auto-increment value, so the old behaviour burned an ID on every lock attempt and could exhaust the ID space.
13
+ - Fix: `KafkaSource#import_without_validations_or_callbacks` accepts a variable number of arguments, so it works with both `activerecord-import` 2.3+ (which prepends a `conn` argument) and earlier versions. Previously an app on 2.3+ raised `ArgumentError: wrong number of arguments` on any import with `kafka_config[:import]` enabled.
14
+
8
15
  ## 2.6.0 - 2026-08-13
9
16
 
10
17
  - Breaking: a failed batch database write is now retried one record at a time, so one unpersistable record no longer loses the whole batch. `Deimos::BatchFallbackError` is raised naming the keys that still failed.
@@ -88,10 +88,13 @@ end
88
88
  # Basically we want to first do the import, then reload the records
89
89
  # and send them to Kafka.
90
90
  # @!visibility private
91
- def import_without_validations_or_callbacks(column_names,
92
- array_of_attributes,
93
- options={})
91
+ #
92
+ # activerecord-import 2.3+ prepends a `conn` arg to this method - accept a splat and
93
+ # grab the last 3 args (column_names, array_of_attributes, options) either way.
94
+ def import_without_validations_or_callbacks(*args)
94
95
  results = super
96
+ column_names, array_of_attributes, options = args.last(3)
97
+ options ||= {}
95
98
  if !self.kafka_config[:import] || array_of_attributes.empty?
96
99
  return results
97
100
  end
@@ -16,11 +16,15 @@ module Deimos
16
16
  # @param lock_id [String]
17
17
  # @return [Boolean]
18
18
  def lock(topic, lock_id) # rubocop:disable Naming/PredicateMethod
19
- # Try to create it - it's fine if it already exists
20
- begin
21
- self.create!(topic: topic, last_processed_at: Time.zone.now)
22
- rescue ActiveRecord::RecordNotUnique
23
- # continue on
19
+ # Only attempt the insert if the row is missing. On MySQL a failed
20
+ # insert still consumes an auto-increment value, so retrying it on
21
+ # every lock attempt would eventually exhaust the ID space.
22
+ unless self.exists?(topic: topic)
23
+ begin
24
+ self.create!(topic: topic, last_processed_at: Time.zone.now)
25
+ rescue ActiveRecord::RecordNotUnique
26
+ # another process created it in the meantime - continue on
27
+ end
24
28
  end
25
29
 
26
30
  # Lock the record
@@ -12,11 +12,11 @@ module Deimos
12
12
  # @return [Integer]
13
13
  attr_accessor :partition_key
14
14
  # @return [String]
15
- attr_accessor :encoded_key
15
+ attr_accessor :encoded_key
16
16
  # @return [String]
17
- attr_accessor :encoded_payload
17
+ attr_accessor :encoded_payload
18
18
  # @return [String]
19
- attr_accessor :topic
19
+ attr_accessor :topic
20
20
 
21
21
  # @param payload [Hash]
22
22
  # @param topic [String]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Deimos
4
- VERSION = '2.6.0'
4
+ VERSION = '2.6.1'
5
5
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Lint/ConstantDefinitionInBlock
3
+ # rubocop:disable-next Lint/ConstantDefinitionInBlock
4
4
  module ActiveRecordBatchConsumerTest # rubocop:disable Metrics/ModuleLength
5
5
  describe Deimos::ActiveRecordConsumer,
6
6
  'Batch Consumer with MySQL handling associations',
@@ -321,4 +321,3 @@ module ActiveRecordBatchConsumerTest # rubocop:disable Metrics/ModuleLength
321
321
  end
322
322
  end
323
323
  end
324
- # rubocop:enable Lint/ConstantDefinitionInBlock
@@ -223,7 +223,7 @@ RSpec.describe Deimos::ActiveRecordConsume::MassUpdater do
223
223
  WidgetFidget.reset_column_information
224
224
  end
225
225
 
226
- # rubocop:disable RSpec/ExampleLength
226
+ # rubocop:disable-next RSpec/ExampleLength
227
227
  it 'should backfill the associations when upserting primary records' do
228
228
  batch = Deimos::ActiveRecordConsume::BatchRecordList.new(
229
229
  [
@@ -275,7 +275,6 @@ RSpec.describe Deimos::ActiveRecordConsume::MassUpdater do
275
275
  expect(widget_fidget.note).to eq("Stuff #{ind + 1}")
276
276
  end
277
277
  end
278
- # rubocop:enable RSpec/ExampleLength
279
278
 
280
279
  end
281
280
 
@@ -3,7 +3,7 @@
3
3
  require 'date'
4
4
 
5
5
  # Wrapped in a module to prevent class leakage
6
- # rubocop:disable Metrics/ModuleLength
6
+ # rubocop:disable-next Metrics/ModuleLength
7
7
  module ActiveRecordConsumerTest
8
8
  describe Deimos::ActiveRecordConsumer, 'Message Consumer' do
9
9
  before(:all) do
@@ -299,4 +299,3 @@ module ActiveRecordConsumerTest
299
299
  end
300
300
  end
301
301
  end
302
- # rubocop:enable Metrics/ModuleLength
@@ -5,7 +5,7 @@ require 'activerecord-import'
5
5
  # Wrap in a module so our classes don't leak out afterwards
6
6
  module KafkaSourceSpec
7
7
  RSpec.describe Deimos::KafkaSource do
8
- # rubocop:disable Lint/ConstantDefinitionInBlock
8
+ # rubocop:disable-next Lint/ConstantDefinitionInBlock
9
9
  before(:all) do
10
10
  ActiveRecord::Base.connection.create_table(:widgets, force: true) do |t|
11
11
  t.integer(:widget_id)
@@ -42,7 +42,6 @@ module KafkaSourceSpec
42
42
  end
43
43
  Widget.reset_column_information
44
44
  end
45
- # rubocop:enable Lint/ConstantDefinitionInBlock
46
45
 
47
46
  after(:all) do
48
47
  ActiveRecord::Base.connection.drop_table(:widgets)
@@ -11,6 +11,12 @@ each_db_config(Deimos::KafkaTopicInfo) do
11
11
  expect(described_class.last.locked_by).to eq('def')
12
12
  end
13
13
 
14
+ it 'should not attempt to create the record if it already exists' do
15
+ described_class.create!(topic: 'my-topic', last_processed_at: Time.zone.now)
16
+ expect(described_class).not_to receive(:create!)
17
+ expect(described_class.lock('my-topic', 'abc')).to be_truthy
18
+ end
19
+
14
20
  it 'should raise an error if the create fails for a non-unique reason' do
15
21
  allow(described_class).to receive(:create!).and_raise(ActiveRecord::ActiveRecordError, 'some other error')
16
22
  expect { described_class.lock('my-topic', 'abc') }.to raise_error(ActiveRecord::ActiveRecordError)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Style/GlobalVars
3
+ # rubocop:disable-next Style/GlobalVars
4
4
  RSpec.describe Karafka::Routing::Topic do
5
5
  before(:each) do
6
6
  KarafkaApp.routes.clear
@@ -150,4 +150,3 @@ RSpec.describe Karafka::Routing::Topic do
150
150
  end
151
151
 
152
152
  end
153
- # rubocop:enable Style/GlobalVars
@@ -137,7 +137,7 @@ each_db_config(Deimos::Utils::OutboxProducer) do
137
137
  end
138
138
 
139
139
  # using expect(x).to have_received(:y).ordered doesn't work
140
- # rubocop:disable RSpec/StubbedMock
140
+ # rubocop:disable-next RSpec/StubbedMock
141
141
  it 'should complete successfully' do # rubocop:disable RSpec/ExampleLength
142
142
  messages = (1..4).map do |i|
143
143
  Deimos::KafkaMessage.new(
@@ -203,7 +203,6 @@ each_db_config(Deimos::Utils::OutboxProducer) do
203
203
  with('my-topic', 'abc').once
204
204
  producer.process_topic('my-topic')
205
205
  end
206
- # rubocop:enable RSpec/StubbedMock
207
206
 
208
207
  it 'should register an error if it gets an error' do
209
208
  allow(producer).to receive(:retrieve_messages).and_raise('OH NOES')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deimos-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Orner