yes-core 2.8.0 → 2.8.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 +3 -0
- data/lib/yes/core/command_handling/read_model_revision_guard.rb +26 -4
- data/lib/yes/core/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 556abdbb646c43a30ef36450a66d72b26b702ab1041bfce62701cbec40e72e26
|
|
4
|
+
data.tar.gz: 15c8870cbb4b60e6b8097479386aa99a6d113fae5950b1d907821e78063f40c4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 260dc63645964b5a0efa9e2da46e0c7e00b5aed59f13393e80db402f889e73246818573e368038afbea1318d264a6a40a73a68108dcd2c24b14f97531200a3c1
|
|
7
|
+
data.tar.gz: bf0561d95288742beb14f5cfd8fe724c7abb52c727a3de97c579171a6fffd3c4f594e4c29d204e4f99a140499ff7dec6acf2aaabb3db5895a85ca5f985fb578f
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,9 @@ module Yes
|
|
|
8
8
|
# Ensures that read model revisions match expected event revisions
|
|
9
9
|
# Uses ExponentialRetrier for retry logic with exponential backoff
|
|
10
10
|
# This handles eventual consistency between the event store and read model databases
|
|
11
|
+
#
|
|
12
|
+
# Waiting for the expected revision happens without a lock. Only the final check and the block run
|
|
13
|
+
# while the read model row is locked, see {#call}.
|
|
11
14
|
class ReadModelRevisionGuard
|
|
12
15
|
# Error raised when revision guard fails after maximum retries
|
|
13
16
|
class RevisionMismatchError < Yes::Core::Error; end
|
|
@@ -96,7 +99,11 @@ module Yes
|
|
|
96
99
|
|
|
97
100
|
# Executes the guard logic with retry mechanism
|
|
98
101
|
#
|
|
99
|
-
#
|
|
102
|
+
# Once the revision matches, the row is locked, reloaded and checked again before the block runs. Without
|
|
103
|
+
# that, two writers applying the same event (for example a slow command and a concurrent recovery) can both
|
|
104
|
+
# pass the check; the later one then writes its stale copy over the newer state and resets the revision.
|
|
105
|
+
#
|
|
106
|
+
# @yield Block to execute when revisions match, runs while the read model row is locked
|
|
100
107
|
# @return [Object] Result of the block execution
|
|
101
108
|
# @raise [RevisionMismatchError] When revisions don't match after maximum retries
|
|
102
109
|
# @raise [TimeoutError] When timeout is exceeded
|
|
@@ -108,9 +115,8 @@ module Yes
|
|
|
108
115
|
retrier.call(
|
|
109
116
|
condition_check: -> { check_revision_and_return_match_status },
|
|
110
117
|
failure_message: revision_mismatch_message,
|
|
111
|
-
timeout_message: timeout_message
|
|
112
|
-
|
|
113
|
-
)
|
|
118
|
+
timeout_message: timeout_message
|
|
119
|
+
) { with_row_lock(&) }
|
|
114
120
|
rescue Yes::Core::Utils::ExponentialRetrier::RetryFailedError => e
|
|
115
121
|
raise RevisionMismatchError, e.message
|
|
116
122
|
rescue Yes::Core::Utils::ExponentialRetrier::TimeoutError => e
|
|
@@ -122,6 +128,22 @@ module Yes
|
|
|
122
128
|
|
|
123
129
|
attr_reader :read_model, :revision_column
|
|
124
130
|
|
|
131
|
+
# Locks and reloads the read model row, re-checks the revision and yields.
|
|
132
|
+
# The lock is held until the surrounding transaction (if any) ends.
|
|
133
|
+
#
|
|
134
|
+
# @yield Block to execute while the row is locked
|
|
135
|
+
# @return [Object] Result of the block execution
|
|
136
|
+
# @raise [RevisionAlreadyAppliedError] When another writer applied the revision in the meantime
|
|
137
|
+
# @raise [RevisionMismatchError] When the locked row is behind the expected revision
|
|
138
|
+
def with_row_lock
|
|
139
|
+
read_model.with_lock do
|
|
140
|
+
check_revision_status!
|
|
141
|
+
raise RevisionMismatchError, revision_mismatch_message unless revision_matches?
|
|
142
|
+
|
|
143
|
+
yield
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
125
147
|
# Creates the retrier with custom logging context
|
|
126
148
|
#
|
|
127
149
|
# @return [Yes::Core::Utils::ExponentialRetrier] Configured retrier instance
|
data/lib/yes/core/version.rb
CHANGED