pgoutput-source-adapter 0.3.0 → 0.3.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: 96fa814d19258cf12c3f2d6398f72f21f1a2dfab59e89562b880f26fbb7bf1cd
4
- data.tar.gz: 300f6a751391ee90ba84dfdbe743839e605fb6655aafc5057f9b87a1e25c3faf
3
+ metadata.gz: 025fc15b43b2a30151173ec6279c863a5ba458efb9d9da71e5ecd96905be6792
4
+ data.tar.gz: 265309ad03d49658717d8f147a01c8833baa87e22283d0cab8a3adae3d2f03fa
5
5
  SHA512:
6
- metadata.gz: 314c92d8ec4d3853056f4c69d99eefb6794aaefbc58a1b5f9e0b2de25c372cce1e8c4864210ade04400d23feb60fc47d68d535c1df901d7ef60a373bc4c735b8
7
- data.tar.gz: 88c5f21bc01667b196a1b347e176cca6aa7caa655a058fa1550bdee3bcb3b88c511fd9371225f5a95fe585dac572a219b46a14a7135e956c97ac47fd8466e986
6
+ metadata.gz: ddb9db7349022b0843871b4a23aebb8399ea3ba74820651f4de44e58b5fd0d5d7f89ab69ee2af64fe3f048c097defa3f2247d910254f75f0fa956d286436d8d5
7
+ data.tar.gz: 3f16c11504e312e0c6a771af39991b456f8128ed197dfce608ca28f027f1dd5ddc5722175244ef889fd2bba36b0429ef811b450cfe8ada6e3697ccf6978bbcff
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.1] - 2026-07-19
4
+
5
+ ### Fixed
6
+
7
+ - Assign stable, zero-based `ChangeEvent#sequence_number` values to row events
8
+ within each transaction so otherwise identical changes remain distinct.
9
+
10
+ ### Quality
11
+
12
+ - Added coverage for identical-event uniqueness, replay determinism, and
13
+ sequence reset between transactions.
14
+
15
+ ### Documentation
16
+
17
+ - Documented transaction-local sequence-number semantics for downstream
18
+ deterministic event IDs.
19
+
3
20
  ## [0.3.0] - 2026-07-17
4
21
 
5
22
  ### Added
data/README.md CHANGED
@@ -105,6 +105,13 @@ transaction are yielded immediately; changes between `Begin` and `Commit` are
105
105
  yielded as a `CDC::Core::TransactionEnvelope`. `normalize_many` uses the same
106
106
  normalization path for finite batches.
107
107
 
108
+ Each change inside a transaction receives a stable, zero-based
109
+ `sequence_number`. The ordinal follows decoded row-event order, resets at each
110
+ `Begin`, and is reproduced when the same transaction input is replayed. Changes
111
+ normalized outside transaction boundaries retain a `nil` sequence number.
112
+ Downstream consumers can include this discriminator in deterministic event IDs
113
+ so otherwise identical changes in the same transaction remain distinct.
114
+
108
115
  ## Primary keys
109
116
 
110
117
  For update and delete events, pgoutput may provide an old-key tuple. When it
@@ -83,12 +83,14 @@ module Pgoutput
83
83
  # envelopes are desired.
84
84
  #
85
85
  # @param event [Object] a Pgoutput::Decoder::Events object.
86
+ # @param sequence_number [Integer, nil] stable zero-based ordinal within
87
+ # the event's transaction.
86
88
  # @return [CDC::Core::ChangeEvent, nil] normalized row change event, or
87
89
  # nil for transaction boundary events.
88
90
  # @raise [Pgoutput::SourceAdapter::Error] when the decoded event type is
89
91
  # unsupported.
90
92
  # rubocop:disable Metrics/MethodLength
91
- def normalize(event, source_position: nil)
93
+ def normalize(event, source_position: nil, sequence_number: nil)
92
94
  case event_name(event)
93
95
  when 'Insert'
94
96
  change_event(
@@ -97,7 +99,8 @@ module Pgoutput
97
99
  old_values: nil,
98
100
  new_values: event.values,
99
101
  primary_key: primary_key_for(event, event.values),
100
- source_position: source_position
102
+ source_position: source_position,
103
+ sequence_number: sequence_number
101
104
  )
102
105
  when 'Update'
103
106
  old_values = event.old_values || event.old_key
@@ -108,7 +111,8 @@ module Pgoutput
108
111
  old_values: old_values,
109
112
  new_values: event.new_values,
110
113
  primary_key: primary_key_for(event, event.new_values),
111
- source_position: source_position
114
+ source_position: source_position,
115
+ sequence_number: sequence_number
112
116
  )
113
117
  when 'Delete'
114
118
  old_values = event.old_values || event.old_key
@@ -119,7 +123,8 @@ module Pgoutput
119
123
  old_values: old_values,
120
124
  new_values: nil,
121
125
  primary_key: primary_key_for(event, old_values),
122
- source_position: source_position
126
+ source_position: source_position,
127
+ sequence_number: sequence_number
123
128
  )
124
129
  when 'Begin', 'Commit'
125
130
  nil
@@ -212,7 +217,12 @@ module Pgoutput
212
217
  transaction_events = []
213
218
  transaction_metadata = {}
214
219
  else
215
- normalized = normalize(event, source_position: source_position)
220
+ normalized = if transaction_id
221
+ normalize(event, source_position: source_position,
222
+ sequence_number: transaction_events.length)
223
+ else
224
+ normalize(event, source_position: source_position)
225
+ end
216
226
  next if normalized.nil?
217
227
 
218
228
  if transaction_id
@@ -231,7 +241,8 @@ module Pgoutput
231
241
  # rubocop:enable Metrics/CyclomaticComplexity
232
242
  # rubocop:enable Metrics/MethodLength
233
243
 
234
- def change_event(event, operation:, old_values:, new_values:, primary_key:, source_position:)
244
+ def change_event(event, operation:, old_values:, new_values:, primary_key:, source_position:,
245
+ sequence_number:)
235
246
  share(
236
247
  CDC::Core::ChangeEvent.new(
237
248
  operation: operation,
@@ -242,6 +253,7 @@ module Pgoutput
242
253
  primary_key: primary_key,
243
254
  transaction_id: event.transaction_id,
244
255
  commit_lsn: lsn_string(source_position),
256
+ sequence_number: sequence_number,
245
257
  metadata: metadata_for(event)
246
258
  )
247
259
  )
@@ -5,6 +5,6 @@ module Pgoutput
5
5
  # Current pgoutput-source-adapter gem version.
6
6
  #
7
7
  # @return [String] semantic version published to RubyGems.
8
- VERSION = '0.3.0'
8
+ VERSION = '0.3.1'
9
9
  end
10
10
  end
@@ -46,7 +46,7 @@ module Pgoutput
46
46
  #
47
47
  # @param event [Object] a Pgoutput::Decoder::Events object.
48
48
  # @return [CDC::Core::ChangeEvent, nil]
49
- def normalize: (untyped event, ?source_position: untyped) -> untyped
49
+ def normalize: (untyped event, ?source_position: untyped, ?sequence_number: Integer?) -> untyped
50
50
 
51
51
  # Pair a decoded event with its transport-level source position.
52
52
  def stream_event: (untyped event, ?source_position: untyped) -> StreamEvent
@@ -72,7 +72,7 @@ module Pgoutput
72
72
 
73
73
  def normalize_stream: (untyped events, flush_incomplete: bool) { (untyped work) -> untyped } -> void
74
74
 
75
- def change_event: (untyped event, operation: untyped, old_values: untyped, new_values: untyped, primary_key: untyped, source_position: untyped) -> untyped
75
+ def change_event: (untyped event, operation: untyped, old_values: untyped, new_values: untyped, primary_key: untyped, source_position: untyped, sequence_number: Integer?) -> untyped
76
76
 
77
77
  def transaction_envelope: (untyped event, transaction_id: untyped, events: untyped, metadata: untyped, ?source_position: untyped) -> untyped
78
78
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgoutput-source-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken C. Demanawa