ruby_reactor 0.8.4 → 0.8.5
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/.release-please-manifest.json +1 -1
- data/.specify/feature.json +1 -1
- data/CHANGELOG.md +196 -0
- data/CLAUDE.md +1 -1
- data/README.md +47 -11
- data/lib/ruby_reactor/dsl/async_macros.rb +30 -1
- data/lib/ruby_reactor/dsl/async_reactor_builder.rb +12 -6
- data/lib/ruby_reactor/dsl/compose_builder.rb +12 -6
- data/lib/ruby_reactor/dsl/interrupt_builder.rb +1 -3
- data/lib/ruby_reactor/dsl/map_builder.rb +0 -2
- data/lib/ruby_reactor/dsl/step_builder.rb +91 -19
- data/lib/ruby_reactor/error/argument_resolution_error.rb +19 -0
- data/lib/ruby_reactor/error/rescuable.rb +28 -0
- data/lib/ruby_reactor/executor/compensation_manager.rb +30 -26
- data/lib/ruby_reactor/executor/result_handler.rb +18 -16
- data/lib/ruby_reactor/executor/step_coordination.rb +11 -8
- data/lib/ruby_reactor/executor/step_executor.rb +59 -49
- data/lib/ruby_reactor/executor.rb +38 -4
- data/lib/ruby_reactor/map/collector.rb +21 -11
- data/lib/ruby_reactor/map/dispatcher.rb +29 -3
- data/lib/ruby_reactor/map/element_executor.rb +9 -3
- data/lib/ruby_reactor/map/helpers.rb +32 -2
- data/lib/ruby_reactor/map/result_enumerator.rb +18 -12
- data/lib/ruby_reactor/reactor.rb +24 -0
- data/lib/ruby_reactor/rspec/matchers.rb +19 -3
- data/lib/ruby_reactor/step/compose_step.rb +7 -1
- data/lib/ruby_reactor/step/map_step.rb +109 -4
- data/lib/ruby_reactor/step.rb +7 -0
- data/lib/ruby_reactor/step_worker.rb +46 -22
- data/lib/ruby_reactor/storage/adapter.rb +4 -0
- data/lib/ruby_reactor/storage/redis_adapter.rb +9 -0
- data/lib/ruby_reactor/storage/redis_reactor_scan.rb +1 -1
- data/lib/ruby_reactor/version.rb +1 -1
- data/lib/ruby_reactor/web/api.rb +1 -1
- data/lib/ruby_reactor/web/public/assets/{index-CeZU-ESu.js → index-CQbgHtd0.js} +10 -10
- data/lib/ruby_reactor/web/public/index.html +1 -1
- data/lib/ruby_reactor/worker.rb +3 -1
- data/lib/ruby_reactor.rb +17 -6
- data/specs/007-execution-flow-analysis/analysis/README.md +147 -0
- data/specs/007-execution-flow-analysis/analysis/execution-order.md +359 -0
- data/specs/007-execution-flow-analysis/analysis/findings-and-options.md +502 -0
- data/specs/007-execution-flow-analysis/analysis/invariants.md +109 -0
- data/specs/007-execution-flow-analysis/checklists/requirements.md +39 -0
- data/specs/007-execution-flow-analysis/contracts/report-structure.md +71 -0
- data/specs/007-execution-flow-analysis/data-model.md +83 -0
- data/specs/007-execution-flow-analysis/evidence/harness.rb +229 -0
- data/specs/007-execution-flow-analysis/evidence/output.txt +333 -0
- data/specs/007-execution-flow-analysis/evidence/probes/01_plain.rb +122 -0
- data/specs/007-execution-flow-analysis/evidence/probes/02_compose.rb +182 -0
- data/specs/007-execution-flow-analysis/evidence/probes/03_map.rb +232 -0
- data/specs/007-execution-flow-analysis/evidence/probes/04_async.rb +132 -0
- data/specs/007-execution-flow-analysis/evidence/probes/05_background.rb +58 -0
- data/specs/007-execution-flow-analysis/evidence/probes/06_coordination.rb +158 -0
- data/specs/007-execution-flow-analysis/evidence/probes/07_interrupts_manual.rb +185 -0
- data/specs/007-execution-flow-analysis/evidence/run.rb +15 -0
- data/specs/007-execution-flow-analysis/plan.md +127 -0
- data/specs/007-execution-flow-analysis/quickstart.md +51 -0
- data/specs/007-execution-flow-analysis/research.md +202 -0
- data/specs/007-execution-flow-analysis/spec.md +270 -0
- data/specs/007-execution-flow-analysis/tasks.md +257 -0
- data/specs/008-rollback-reliability/checklists/requirements.md +43 -0
- data/specs/008-rollback-reliability/contracts/api-surface.md +126 -0
- data/specs/008-rollback-reliability/contracts/rollback-semantics.md +76 -0
- data/specs/008-rollback-reliability/data-model.md +139 -0
- data/specs/008-rollback-reliability/plan.md +233 -0
- data/specs/008-rollback-reliability/quickstart.md +105 -0
- data/specs/008-rollback-reliability/research.md +653 -0
- data/specs/008-rollback-reliability/spec.md +561 -0
- data/specs/008-rollback-reliability/tasks.md +1110 -0
- data/specs/future_improvements.md +48 -0
- metadata +35 -2
|
@@ -248,3 +248,51 @@ Direction:
|
|
|
248
248
|
|
|
249
249
|
Spec: compose → fan-out map, with and without a park after the map. The root completes either
|
|
250
250
|
way.
|
|
251
|
+
|
|
252
|
+
## Rollback follow-ups (008)
|
|
253
|
+
|
|
254
|
+
Raised while implementing specs/008-rollback-reliability. None blocks it.
|
|
255
|
+
|
|
256
|
+
- **Sweeper re-enqueues in-progress inline runs.** `RubyReactor::Sweeper` re-enqueues any
|
|
257
|
+
top-level context that is `running` with no `async:` lock. A run still executing in the
|
|
258
|
+
caller's process never holds that lock, so a sweep during it enqueues a worker that resumes the
|
|
259
|
+
same run forward. Pre-existing; 008 only keeps `aborted` runs out of it. Direction: mark
|
|
260
|
+
caller-process runs (the `inline_async_execution` inverse) so the sweeper skips them until they
|
|
261
|
+
are stale by a timestamp, or give them their own liveness lock.
|
|
262
|
+
- **Map-level `undo_all` override.** Map rollback always replays each element's own step `undo`s.
|
|
263
|
+
A bulk refund API may want one call for all elements instead. Direction: an optional
|
|
264
|
+
`undo_all { |completed_results| ... }` on `map` that replaces the per-element replay.
|
|
265
|
+
- **Rollback fan-out for very large maps.** Map rollback is serial, in the process that detected
|
|
266
|
+
the failure, so its time is linear in the number of completed elements (10,000 elements take
|
|
267
|
+
about a minute in the test suite). Direction: enqueue one rollback job per element (or per
|
|
268
|
+
batch) and resolve the parent's failure once they report back.
|
|
269
|
+
- **A resume for a second pending interrupt while the first is executing.** A reactor paused at
|
|
270
|
+
several ready interrupts takes their resumes one at a time: each accepted resume marks the run
|
|
271
|
+
`running` (008 FR-032), and the run pauses again at the interrupts still pending. A resume that
|
|
272
|
+
arrives for another pending interrupt while the first resume is still executing is rejected
|
|
273
|
+
("the reactor is running"). Interrupt steps have no body, so that window is short, but a caller
|
|
274
|
+
resuming two interrupts at once can hit it. Direction: accept it for an interrupt that has not
|
|
275
|
+
executed yet (store its payload and let the running resume pick it up), or return a retryable
|
|
276
|
+
error.
|
|
277
|
+
- **An interrupted `compensate` of the failing step is not re-run.** An interruption (signal, exit,
|
|
278
|
+
out of memory) during the failing step's own `compensate` leaves the run `aborted`. A manual
|
|
279
|
+
`Reactor.undo(id)` undoes the completed steps but never re-runs that `compensate`, so the step
|
|
280
|
+
can stay half-compensated. Pre-existing (008 R-08). Direction: record the failing step on the
|
|
281
|
+
aborted run and have manual undo re-run its `compensate` before the undo stack.
|
|
282
|
+
- **Recover a resume contended on a lock.** An inline `continue` that cannot take the reactor's
|
|
283
|
+
`with_lock` or `with_semaphore` raises its `AcquisitionError` and leaves the run `paused`; the
|
|
284
|
+
caller has to retry it (008 review, 2026-09-30). A webhook sender that does not retry loses the
|
|
285
|
+
resume. Direction:
|
|
286
|
+
- Validate the payload first, synchronously in the calling process, as `resume: :background`
|
|
287
|
+
does today. An invalid payload returns its validation failure to the caller (the webhook),
|
|
288
|
+
and nothing is stored or enqueued.
|
|
289
|
+
- Only a valid payload is stored and handed off. On contention, mark the run `running` and give
|
|
290
|
+
the resume to a worker. The worker snoozes on the contended lock without spending retries and
|
|
291
|
+
resumes once the lock is free. The deferred resume never re-validates the payload, so it
|
|
292
|
+
cannot fail on validation after the caller was told it was accepted.
|
|
293
|
+
- `continue` returns a `DispatchResult` instead of raising, and a second `continue` is rejected
|
|
294
|
+
as for any running resume.
|
|
295
|
+
- **Two resumes in the same instant.** Two `continue` calls that both read `paused` before either
|
|
296
|
+
saves `running` are separated only by the per-run context lock, which inline Sidekiq testing
|
|
297
|
+
skips. Accepted for now (008 review, 2026-09-27). Direction: claim the resume with an atomic
|
|
298
|
+
status compare-and-set.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_reactor
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Artur
|
|
@@ -169,6 +169,7 @@ files:
|
|
|
169
169
|
- lib/ruby_reactor/dsl/step_builder.rb
|
|
170
170
|
- lib/ruby_reactor/dsl/template_helpers.rb
|
|
171
171
|
- lib/ruby_reactor/dsl/validation_helpers.rb
|
|
172
|
+
- lib/ruby_reactor/error/argument_resolution_error.rb
|
|
172
173
|
- lib/ruby_reactor/error/async_result_pending.rb
|
|
173
174
|
- lib/ruby_reactor/error/async_wait_timeout_error.rb
|
|
174
175
|
- lib/ruby_reactor/error/base.rb
|
|
@@ -180,6 +181,7 @@ files:
|
|
|
180
181
|
- lib/ruby_reactor/error/execution_parked.rb
|
|
181
182
|
- lib/ruby_reactor/error/input_validation_error.rb
|
|
182
183
|
- lib/ruby_reactor/error/reactor_contention_park.rb
|
|
184
|
+
- lib/ruby_reactor/error/rescuable.rb
|
|
183
185
|
- lib/ruby_reactor/error/schema_version_error.rb
|
|
184
186
|
- lib/ruby_reactor/error/step_contention_park.rb
|
|
185
187
|
- lib/ruby_reactor/error/step_failure_error.rb
|
|
@@ -264,7 +266,7 @@ files:
|
|
|
264
266
|
- lib/ruby_reactor/web/config.ru
|
|
265
267
|
- lib/ruby_reactor/web/coordination_serializer.rb
|
|
266
268
|
- lib/ruby_reactor/web/public/assets/index-BQvIWPdx.css
|
|
267
|
-
- lib/ruby_reactor/web/public/assets/index-
|
|
269
|
+
- lib/ruby_reactor/web/public/assets/index-CQbgHtd0.js
|
|
268
270
|
- lib/ruby_reactor/web/public/index.html
|
|
269
271
|
- lib/ruby_reactor/web/public/vite.svg
|
|
270
272
|
- lib/ruby_reactor/worker.rb
|
|
@@ -279,6 +281,37 @@ files:
|
|
|
279
281
|
- specs/006-step-retry-declarations/research.md
|
|
280
282
|
- specs/006-step-retry-declarations/spec.md
|
|
281
283
|
- specs/006-step-retry-declarations/tasks.md
|
|
284
|
+
- specs/007-execution-flow-analysis/analysis/README.md
|
|
285
|
+
- specs/007-execution-flow-analysis/analysis/execution-order.md
|
|
286
|
+
- specs/007-execution-flow-analysis/analysis/findings-and-options.md
|
|
287
|
+
- specs/007-execution-flow-analysis/analysis/invariants.md
|
|
288
|
+
- specs/007-execution-flow-analysis/checklists/requirements.md
|
|
289
|
+
- specs/007-execution-flow-analysis/contracts/report-structure.md
|
|
290
|
+
- specs/007-execution-flow-analysis/data-model.md
|
|
291
|
+
- specs/007-execution-flow-analysis/evidence/harness.rb
|
|
292
|
+
- specs/007-execution-flow-analysis/evidence/output.txt
|
|
293
|
+
- specs/007-execution-flow-analysis/evidence/probes/01_plain.rb
|
|
294
|
+
- specs/007-execution-flow-analysis/evidence/probes/02_compose.rb
|
|
295
|
+
- specs/007-execution-flow-analysis/evidence/probes/03_map.rb
|
|
296
|
+
- specs/007-execution-flow-analysis/evidence/probes/04_async.rb
|
|
297
|
+
- specs/007-execution-flow-analysis/evidence/probes/05_background.rb
|
|
298
|
+
- specs/007-execution-flow-analysis/evidence/probes/06_coordination.rb
|
|
299
|
+
- specs/007-execution-flow-analysis/evidence/probes/07_interrupts_manual.rb
|
|
300
|
+
- specs/007-execution-flow-analysis/evidence/run.rb
|
|
301
|
+
- specs/007-execution-flow-analysis/plan.md
|
|
302
|
+
- specs/007-execution-flow-analysis/quickstart.md
|
|
303
|
+
- specs/007-execution-flow-analysis/research.md
|
|
304
|
+
- specs/007-execution-flow-analysis/spec.md
|
|
305
|
+
- specs/007-execution-flow-analysis/tasks.md
|
|
306
|
+
- specs/008-rollback-reliability/checklists/requirements.md
|
|
307
|
+
- specs/008-rollback-reliability/contracts/api-surface.md
|
|
308
|
+
- specs/008-rollback-reliability/contracts/rollback-semantics.md
|
|
309
|
+
- specs/008-rollback-reliability/data-model.md
|
|
310
|
+
- specs/008-rollback-reliability/plan.md
|
|
311
|
+
- specs/008-rollback-reliability/quickstart.md
|
|
312
|
+
- specs/008-rollback-reliability/research.md
|
|
313
|
+
- specs/008-rollback-reliability/spec.md
|
|
314
|
+
- specs/008-rollback-reliability/tasks.md
|
|
282
315
|
- specs/future_improvements.md
|
|
283
316
|
- specs/scoped_rspec_matchers.md
|
|
284
317
|
- specs/specs-inputs-by-method-md-piped-wigderson.md
|