yes-core 2.5.0 → 2.6.0

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: 657f96d2dc9f3d762a91b42976783cfead117aae5be6473e547b4e1568cc8e83
4
- data.tar.gz: 0c5b51b64f133b09cf14ef1d9c99fc7fcdd94f67f479f410dca443545b13ce56
3
+ metadata.gz: 7c8f35e4035dc9922ec9a9cd70d87d17147053e62636a8dfcd305f4d17107783
4
+ data.tar.gz: 27f5bce1fbb5b148043020b9197716d591c6108026679d28c9227194cb597423
5
5
  SHA512:
6
- metadata.gz: cecd619ffb8384612a3ad7a1640fbe6ed9f8d8b73b01f0da6bc8d1892bce474af92274444d8a3c7b16e1bfc622a1cadccbc793f51d61196dd48a57abbd3e0ec5
7
- data.tar.gz: a8f5aee284c9e77715b839b395e4aefa99375275d76d47f9003e9aaf510cd77db88c5fc39c37046523247a01e958c8e1e689da8afc0044bb0928692bd311147c
6
+ metadata.gz: 92ab4144796e842ee51cc15c9edd1a34a61c652dd13731ca2c3ee286014e886559514e017d8bfcf2016d1271a602da50a9ca259e7039af870d7bd21671872844
7
+ data.tar.gz: 3b66c7247e0322a96ddef754167af357ba10f2e7951ff7a941e99e9c8cdac87e810c86a37d5ed84d1e3c31e6869ca3272cd2fcd5def17bf48448eea2380cd4f8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.6.0] - 2026-10-28
4
+ - See root CHANGELOG.md for details.
5
+
3
6
  ## [2.5.0] - 2026-10-08
4
7
  - See root CHANGELOG.md for details.
5
8
 
@@ -23,7 +23,13 @@ module Yes
23
23
  READ_MODEL_CLASS_REGEXP =
24
24
  /(?<context>\w+)::ReadModels::(?<version>V\d+)?(::)?(?<aggregate>\w+)/
25
25
 
26
- # Based on event type class it distributes event to a proper event handler
26
+ # Column of the read model that holds the revision of the last processed event of its stream
27
+ REVISION_COLUMN = :revision
28
+
29
+ # Based on event type class it distributes event to a proper event handler. After the handler ran, the
30
+ # stream revision of the event is stored in the read model's `revision` column (see #write_stream_revision).
31
+ # Events that were not handled (no handler, locale not available) do not change the revision, because
32
+ # the read model does not reflect them.
27
33
  # @param event [Yes::Core::Event]
28
34
  # @param read_model [ActiveRecord::Base] AR object
29
35
  # @return [void]
@@ -47,6 +53,8 @@ module Yes
47
53
  ensure
48
54
  otl_record_processed(read_model, event, handler)
49
55
  end
56
+
57
+ write_stream_revision(read_model, event)
50
58
  end
51
59
  otl_trackable :call, OpenTelemetry::OtlSpan::OtlData.new(
52
60
  span_kind: :consumer,
@@ -172,6 +180,30 @@ module Yes
172
180
  READ_MODEL_CLASS_REGEXP.match(self.class.to_s)
173
181
  end
174
182
 
183
+ # Stores the stream revision of the event in the read model's `revision` column, so a consumer can tell
184
+ # how far a read model fed by a subscription has caught up with its stream. It only moves forward and
185
+ # skips read models without the column. Per-aggregate columns (e.g. `shop_order_revision`) belong to
186
+ # the aggregates that write them and are never touched here.
187
+ # It only writes for events of the read model's own stream: a builder may also react to events of
188
+ # other streams (e.g. a product event for an order item), whose revision says nothing about this row.
189
+ # Only the stream id is compared, not the context or the stream name. A read model fed by two streams
190
+ # that share the same id would get a mixed revision, so such read models must not rely on it.
191
+ # A read model whose `revision` column an aggregate writes must not also be fed by a builder:
192
+ # use per-aggregate revision columns or project the events through the aggregate instead.
193
+ # @param read_model [ActiveRecord::Base, nil] the read model, nil if the event maps to no row
194
+ # @param event [Yes::Core::Event] the event that was handled
195
+ # @return [void]
196
+ def write_stream_revision(read_model, event)
197
+ revision = event.stream_revision
198
+ return unless revision && read_model&.persisted? && read_model.has_attribute?(REVISION_COLUMN)
199
+ return unless event.stream&.stream_id == read_model.id
200
+
201
+ # a nullable column may still be NULL before the first event
202
+ return unless revision > (read_model[REVISION_COLUMN] || -1)
203
+
204
+ read_model.update_column(REVISION_COLUMN, revision)
205
+ end
206
+
175
207
  # @param locale [Symbol] locale to check
176
208
  # @return [Boolean] true if locale is available
177
209
  def correct_locale?(locale)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Yes
4
4
  module Core
5
- VERSION = '2.5.0'
5
+ VERSION = '2.6.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yes-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nico Ritsche