orfeas_lyra 0.9.1 → 0.9.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: 1ad6e90ac8c41a250e5657e98d515ae6dc1c67ac143ac0e09b5aa03da8d519e5
4
- data.tar.gz: 3f901f07baca22e6e7a20d670d2511e6ed29ee0897d9ace09046a744178c4398
3
+ metadata.gz: 4a75016e10096d61497bb69e58b2570d23ca9a99a8206377fe94216d1db26eb9
4
+ data.tar.gz: a139ef32e0dd3e83ba2c5ce1f182e6cb83360f2208faea20a1330536ee63edae
5
5
  SHA512:
6
- metadata.gz: 83812774c35b098d728b340806597d9e7949ae813f3005ab76f6d032628acef6bc38aad567f4c15a50f90f315e0c34a681dedf11b327ed2a60e53f25e7f1fb71
7
- data.tar.gz: f73b3d73337a165cb8160854468ba0d8fc9bfb86678eafa9f463a517cffbdd85a2effce8460bcc2168d85cbea9fabb748ea16a6b5c9f17d7380ba832fe4c5f5c
6
+ metadata.gz: 9d8e2c114fcae82c8dd8735758da868eb4e2aef90f4c7ad53f1385b6f39d8d182f57e9026d8e90d4a283501ae6a7fcdb97889d989183deee427252794fb1d8b4
7
+ data.tar.gz: 6817174882333de4336a7907cae0a47c1690712f85ec1f1cb96cd676e4b6ada397cf17c64a1249a5a96623cc5a33ee60c728f5c92d1ffc80bcede9ac4aa76e42
data/CHANGELOG.md CHANGED
@@ -7,13 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.9.2] - 2026-11-03
11
+
12
+ One fix in Lyra; PAM DSL and PetriFlow are unchanged (0.9.1).
13
+
14
+ ### Fixed
15
+ - **ES-Async read-your-writes no longer races a projection job.** With read-your-writes
16
+ (`each_write: true`), the writer projected its own event without the per-stream lock that
17
+ `AsyncProjectionJob` holds. A job that had read the record's stream before that event
18
+ committed could write the row afterwards, putting it back to the older value until the newer
19
+ event's job ran: a reader in between saw the record step back (an application's suite, run
20
+ with real background projection, read a refund as "approved" just after it was "processed").
21
+ `Lyra::Consistency::ReadYourWrites` now takes the job's lock before projecting, held to the
22
+ end of the writer's transaction. Final states converged before as well. Plain ES-Async (no
23
+ read-your-writes) was not affected. `test/concurrent_same_record_test.rb` reproduces the
24
+ interleaving.
25
+
10
26
  ## [0.9.1] - 2026-11-02
11
27
 
12
28
  Lyra's changes since 0.9.0; PAM DSL and PetriFlow change only in their gem descriptions.
13
29
 
14
30
  ### Released
15
31
  - The gems on RubyGems (`orfeas_lyra`, `orfeas_petri_flow`, `orfeas_pam_dsl`), built from tag
16
- `v0.9.1`
32
+ `v0.9.1` and pushed on 2026-11-02
17
33
 
18
34
  ### Added
19
35
  - **Writes are grouped into causal chains by default** (`config.correlate_writes`, on). Before,
data/README.md CHANGED
@@ -52,7 +52,8 @@ seven configurations:
52
52
  - PostgreSQL. Lyra depends on the `pg` gem; the advisory locks behind Genesis
53
53
  and ES-Lazy, and id reservation in Hijack mode, need PostgreSQL.
54
54
 
55
- The gem names differ from the files to require:
55
+ The gems are on RubyGems, at 0.9.1 (2 November 2026). Their names differ from the
56
+ files to require:
56
57
 
57
58
  ```ruby
58
59
  # Gemfile
@@ -89,12 +89,34 @@ module Lyra
89
89
  (Thread.current[:lyra_pending_writes] || []).each { |write| project(write) }
90
90
  end
91
91
 
92
+ # Projects under the lock AsyncProjectionJob holds per stream, taken
93
+ # in the writer's transaction (or one of its own) and held to its end.
94
+ # A job that had read the stream before this write committed would
95
+ # otherwise write the row after this projection, putting it back to
96
+ # the older value until the newer event's job ran. With the lock, this
97
+ # projection waits for a job in flight; a job that starts after it
98
+ # reads a stream that already holds this write's event.
92
99
  def project(write)
93
- Lyra::Projections::ModelProjection.project(write[:model_class], write[:operation], write[:result])
100
+ model_class = write[:model_class]
101
+ model_class.transaction do
102
+ lock_stream(model_class, write[:result])
103
+ Lyra::Projections::ModelProjection.project(model_class, write[:operation], write[:result])
104
+ end
94
105
  rescue => e
95
106
  Rails.logger.error("Lyra: Failed to ensure projection - #{e.message}")
96
107
  raise if Lyra.config.strict_projections
97
108
  end
109
+
110
+ # The same key AsyncProjectionJob#lock_stream! locks: the record's
111
+ # stream name, from the model id its event carries.
112
+ def lock_stream(model_class, result)
113
+ data = result.events&.first&.data
114
+ model_id = data && (data[:model_id] || data["model_id"])
115
+ return unless model_id
116
+
117
+ stream = Lyra.stream_name(model_class, model_id)
118
+ model_class.with_connection { |c| Lyra::AdvisoryLock.xact_lock(c, stream, purpose: "read-your-writes projection") }
119
+ end
98
120
  end
99
121
  end
100
122
 
data/lib/lyra/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lyra
2
- VERSION = "0.9.1"
2
+ VERSION = "0.9.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orfeas_lyra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michail Pantelelis