dionysus-rb 1.4.0 → 1.4.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/lib/dionysus/producer/karafka_responder_generator.rb +16 -9
- data/lib/dionysus/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: aea1780da49737ea39a412112502ccefec1921bcaa8e4d9e3f4a17c01e359cb1
|
|
4
|
+
data.tar.gz: 0de793797246fa1aa63209eb9713529df3bf3b51aedca2d03be485ab3b140f43
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9ba62b20fdf34088c43f28bfd71e4fa721b4d512125ca030c16c61eb077354aab5751a05c1ce0192708a7fc87ccd3d3af0a63b8a2f06a48ab903858c928d4ce8
|
|
7
|
+
data.tar.gz: d67700b960048a4ea6b272d20d193ba4232115665a5a72d0b2171cec6ba089c3bb451ab36fd5092ffbec55a763fca95fa7b8b7299b3f44263122e58aea26932f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.4.1]
|
|
4
|
+
- Stamp `serialized_at` when the attempt that is actually published begins, not before the retry loop. 1.4.0 takes the stamp once and then re-serializes up to `max_snapshot_attempts` times, so a message can be published a whole retry cycle after its own stamp - and the payload it publishes is the one read last, not the one the stamp describes. Consumers rank duplicates by `[serialized_at, offset]`, so the freshest payload ended up carrying the oldest stamp and losing its group to a staler sibling. That is the failure `serialized_at` was added to prevent, reintroduced by the guard added to prevent a different one.
|
|
5
|
+
- Measured on the affected topic over 65 minutes: 205 of 6,572 messages (3.12%) carried an `updated_at` LATER than their own `serialized_at`, the worst by 1,225 ms. A timestamp cannot describe a moment after the one it was taken at, so that alone proves the stamp preceded the payload.
|
|
6
|
+
- `serialize_consistently` now returns `[payload, read_at]`. The looseness between stamp and payload is bounded by a single serialization pass again, as it was before 1.4.0, rather than by the whole retry cycle - so contended records, which retry most, are no longer the ones stamped most wrongly.
|
|
7
|
+
- Covered end to end against a real broker in `spec/serialized_at_tracks_published_attempt_spec.rb`: a contended publish retries while a competing publish serializes once and stamps later, both are read back off the topic, and the real `RemoveDuplicatesStrategy` is asked which survives. The spec fails on 1.4.0 on both assertions.
|
|
8
|
+
|
|
3
9
|
## [1.4.0]
|
|
4
10
|
|
|
5
11
|
### Fixed
|
data/Gemfile.lock
CHANGED
|
@@ -46,10 +46,10 @@ class Dionysus::Producer::KarafkaResponderGenerator
|
|
|
46
46
|
|
|
47
47
|
record = records.sample
|
|
48
48
|
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
# consumers rank duplicates by this stamp, so it has to describe the attempt actually
|
|
50
|
+
# published - with retries that is the last one, not the first
|
|
51
|
+
payload, read_at = serialize_consistently(records, topic, batch_options)
|
|
52
|
+
serialized_at = config.include_serialized_at_in_payload ? read_at : nil
|
|
53
53
|
|
|
54
54
|
event_payload = {
|
|
55
55
|
event: event,
|
|
@@ -88,26 +88,33 @@ class Dionysus::Producer::KarafkaResponderGenerator
|
|
|
88
88
|
# So serialize, then check whether the records moved underneath it. If they did, the payload
|
|
89
89
|
# is not a snapshot of anything: reload and serialize again. Retries are bounded, and the last
|
|
90
90
|
# attempt is published rather than dropped - a payload that may be torn still beats no message.
|
|
91
|
+
# returns [payload, read_at] - read_at is when the attempt that produced this payload began
|
|
91
92
|
define_method :serialize_consistently do |records, current_topic, batch_options|
|
|
92
|
-
|
|
93
|
+
unless config.publish_consistent_snapshots
|
|
94
|
+
read_at = Time.now.utc
|
|
95
|
+
next [serialize_to_payload(records, current_topic, batch_options), read_at]
|
|
96
|
+
end
|
|
93
97
|
|
|
94
98
|
max_attempts = config.max_snapshot_attempts
|
|
95
99
|
attempts = 0
|
|
96
100
|
loop do
|
|
101
|
+
read_at = Time.now.utc
|
|
97
102
|
before = snapshot_of(records)
|
|
98
103
|
payload = serialize_to_payload(records, current_topic, batch_options)
|
|
99
104
|
attempts += 1
|
|
100
105
|
|
|
101
|
-
|
|
102
|
-
|
|
106
|
+
if before.nil?
|
|
107
|
+
# nothing to compare against, so the guard did not run on this message at all
|
|
108
|
+
break [instrument_snapshot("unsupported", attempts, records, current_topic, payload), read_at]
|
|
109
|
+
end
|
|
103
110
|
if before == committed_snapshot_of(records)
|
|
104
|
-
break instrument_snapshot("consistent", attempts, records, current_topic, payload)
|
|
111
|
+
break [instrument_snapshot("consistent", attempts, records, current_topic, payload), read_at]
|
|
105
112
|
end
|
|
106
113
|
if attempts >= max_attempts
|
|
107
114
|
# published anyway: a payload that may be torn beats no message. Nothing downstream can
|
|
108
115
|
# tell this apart from a clean one - the payload carries no marker and the consumer sees
|
|
109
116
|
# an ordinary message - so this counter is the only place the outcome is ever visible.
|
|
110
|
-
break instrument_snapshot("exhausted", attempts, records, current_topic, payload)
|
|
117
|
+
break [instrument_snapshot("exhausted", attempts, records, current_topic, payload), read_at]
|
|
111
118
|
end
|
|
112
119
|
|
|
113
120
|
records.each { |record| record.reload if record.is_a?(ActiveRecord::Base) && record.persisted? }
|
data/lib/dionysus/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dionysus-rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.4.
|
|
4
|
+
version: 1.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Karol Galanciak
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|