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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.release-please-manifest.json +1 -1
  3. data/.specify/feature.json +1 -1
  4. data/CHANGELOG.md +196 -0
  5. data/CLAUDE.md +1 -1
  6. data/README.md +47 -11
  7. data/lib/ruby_reactor/dsl/async_macros.rb +30 -1
  8. data/lib/ruby_reactor/dsl/async_reactor_builder.rb +12 -6
  9. data/lib/ruby_reactor/dsl/compose_builder.rb +12 -6
  10. data/lib/ruby_reactor/dsl/interrupt_builder.rb +1 -3
  11. data/lib/ruby_reactor/dsl/map_builder.rb +0 -2
  12. data/lib/ruby_reactor/dsl/step_builder.rb +91 -19
  13. data/lib/ruby_reactor/error/argument_resolution_error.rb +19 -0
  14. data/lib/ruby_reactor/error/rescuable.rb +28 -0
  15. data/lib/ruby_reactor/executor/compensation_manager.rb +30 -26
  16. data/lib/ruby_reactor/executor/result_handler.rb +18 -16
  17. data/lib/ruby_reactor/executor/step_coordination.rb +11 -8
  18. data/lib/ruby_reactor/executor/step_executor.rb +59 -49
  19. data/lib/ruby_reactor/executor.rb +38 -4
  20. data/lib/ruby_reactor/map/collector.rb +21 -11
  21. data/lib/ruby_reactor/map/dispatcher.rb +29 -3
  22. data/lib/ruby_reactor/map/element_executor.rb +9 -3
  23. data/lib/ruby_reactor/map/helpers.rb +32 -2
  24. data/lib/ruby_reactor/map/result_enumerator.rb +18 -12
  25. data/lib/ruby_reactor/reactor.rb +24 -0
  26. data/lib/ruby_reactor/rspec/matchers.rb +19 -3
  27. data/lib/ruby_reactor/step/compose_step.rb +7 -1
  28. data/lib/ruby_reactor/step/map_step.rb +109 -4
  29. data/lib/ruby_reactor/step.rb +7 -0
  30. data/lib/ruby_reactor/step_worker.rb +46 -22
  31. data/lib/ruby_reactor/storage/adapter.rb +4 -0
  32. data/lib/ruby_reactor/storage/redis_adapter.rb +9 -0
  33. data/lib/ruby_reactor/storage/redis_reactor_scan.rb +1 -1
  34. data/lib/ruby_reactor/version.rb +1 -1
  35. data/lib/ruby_reactor/web/api.rb +1 -1
  36. data/lib/ruby_reactor/web/public/assets/{index-CeZU-ESu.js → index-CQbgHtd0.js} +10 -10
  37. data/lib/ruby_reactor/web/public/index.html +1 -1
  38. data/lib/ruby_reactor/worker.rb +3 -1
  39. data/lib/ruby_reactor.rb +17 -6
  40. data/specs/007-execution-flow-analysis/analysis/README.md +147 -0
  41. data/specs/007-execution-flow-analysis/analysis/execution-order.md +359 -0
  42. data/specs/007-execution-flow-analysis/analysis/findings-and-options.md +502 -0
  43. data/specs/007-execution-flow-analysis/analysis/invariants.md +109 -0
  44. data/specs/007-execution-flow-analysis/checklists/requirements.md +39 -0
  45. data/specs/007-execution-flow-analysis/contracts/report-structure.md +71 -0
  46. data/specs/007-execution-flow-analysis/data-model.md +83 -0
  47. data/specs/007-execution-flow-analysis/evidence/harness.rb +229 -0
  48. data/specs/007-execution-flow-analysis/evidence/output.txt +333 -0
  49. data/specs/007-execution-flow-analysis/evidence/probes/01_plain.rb +122 -0
  50. data/specs/007-execution-flow-analysis/evidence/probes/02_compose.rb +182 -0
  51. data/specs/007-execution-flow-analysis/evidence/probes/03_map.rb +232 -0
  52. data/specs/007-execution-flow-analysis/evidence/probes/04_async.rb +132 -0
  53. data/specs/007-execution-flow-analysis/evidence/probes/05_background.rb +58 -0
  54. data/specs/007-execution-flow-analysis/evidence/probes/06_coordination.rb +158 -0
  55. data/specs/007-execution-flow-analysis/evidence/probes/07_interrupts_manual.rb +185 -0
  56. data/specs/007-execution-flow-analysis/evidence/run.rb +15 -0
  57. data/specs/007-execution-flow-analysis/plan.md +127 -0
  58. data/specs/007-execution-flow-analysis/quickstart.md +51 -0
  59. data/specs/007-execution-flow-analysis/research.md +202 -0
  60. data/specs/007-execution-flow-analysis/spec.md +270 -0
  61. data/specs/007-execution-flow-analysis/tasks.md +257 -0
  62. data/specs/008-rollback-reliability/checklists/requirements.md +43 -0
  63. data/specs/008-rollback-reliability/contracts/api-surface.md +126 -0
  64. data/specs/008-rollback-reliability/contracts/rollback-semantics.md +76 -0
  65. data/specs/008-rollback-reliability/data-model.md +139 -0
  66. data/specs/008-rollback-reliability/plan.md +233 -0
  67. data/specs/008-rollback-reliability/quickstart.md +105 -0
  68. data/specs/008-rollback-reliability/research.md +653 -0
  69. data/specs/008-rollback-reliability/spec.md +561 -0
  70. data/specs/008-rollback-reliability/tasks.md +1110 -0
  71. data/specs/future_improvements.md +48 -0
  72. metadata +35 -2
@@ -0,0 +1,105 @@
1
+ # Quickstart: Validating Reliable Rollback
2
+
3
+ This guide checks that the feature does what [spec.md](spec.md) promises.
4
+
5
+ - Behavior contract: [contracts/rollback-semantics.md](contracts/rollback-semantics.md)
6
+ - API changes: [contracts/api-surface.md](contracts/api-surface.md)
7
+
8
+ ## Prerequisites
9
+
10
+ ```sh
11
+ docker start ruby_reactor_redis_test 2>/dev/null \
12
+ || docker run -d --name rr-test-redis -p 6780:6379 redis:7-alpine
13
+ bundle install
14
+ ```
15
+
16
+ Don't run the gem suite and the demo suite at the same time against the same test Redis. Their
17
+ per-example flushes wipe each other's state.
18
+
19
+ ## 1. Feature specs (SC-001, SC-003, SC-005)
20
+
21
+ ```sh
22
+ bundle exec rspec spec/ruby_reactor/rollback
23
+ bundle exec rspec spec/ruby_reactor/dsl/async_step_spec.rb
24
+ ```
25
+
26
+ **Expected**: all green. Each example fails when run against baseline `faf90e8d`. That is the
27
+ Red step: check it once by running the new files on a checkout of the baseline.
28
+
29
+ | File | Proves |
30
+ |---|---|
31
+ | `map_rollback_spec.rb` | US1: inline and fan-out map compensate and undo, `fail_fast false`, collect failure, nested map/compose, manual undo, element rollback failure attribution |
32
+ | `map_fan_out_settle_spec.rb` | US1-3 / SC-003: 100 seeded shuffled drain orders, 0 completed elements left with a non-empty undo stack. Skipped slots stop the sweeper from re-dispatching |
33
+ | `compose_retry_spec.rb` | US2: `retries` on `compose`/`async_reactor` rejected; a child step's own retries; a failed child is not re-run; park/resume does not re-run |
34
+ | `failure_rollback_spec.rb` | US3: transform, source and result path raising; unknown errors; non-`StandardError` exceptions (`NotImplementedError`, `SystemStackError`, custom `Exception`) in a body, a transform, a compensate and an undo; `CompensationError` attribution; worker-side resolution |
35
+ | `aborted_execution_spec.rb` | US3-5: an `Interrupt` re-raised unchanged, status `aborted`, skipped by the sweeper, `Reactor#undo` rolls it back; an interruption mid-rollback keeps only the entries not yet undone; an enclosing `Timeout.timeout` still fires |
36
+ | `removed_dsl_spec.rb` | US6: `where`/`guard` rejected on `step`, `async_step` and `interrupt`; `Skipped` from the body continues the reactor |
37
+ | `async_step_compensate_spec.rb` | US4: compensate once after the final attempt, not on a retried success, no double compensation with a reader, inline `undo` rejected, class `undo` warned, `compensation` on the unit record |
38
+
39
+ ## 2. Slow scale check (SC-006)
40
+
41
+ ```sh
42
+ bundle exec rspec spec/ruby_reactor/rollback --tag slow
43
+ ```
44
+
45
+ **Expected**: a 10,000-element map fails after all elements succeed (its collect step raises) and
46
+ rolls every element back. There is no `ContextTooLargeError`, and the parent context size is about
47
+ the same as for a 10-element map.
48
+
49
+ ## 3. 007 regression harness (SC-002)
50
+
51
+ ```sh
52
+ bundle exec ruby specs/007-execution-flow-analysis/evidence/run.rb \
53
+ | tee specs/007-execution-flow-analysis/evidence/output.txt
54
+ ```
55
+
56
+ **Expected**: `64 scenarios, 64 match, 0 mismatch` (S-edge-03b is new in the 2026-09-27 revision).
57
+
58
+ - Only the scenarios listed in [contracts/rollback-semantics.md §3](contracts/rollback-semantics.md#3-canonical-sequences-old--new)
59
+ have their `expected:` sequences updated.
60
+ - `git diff` on the probe files must touch only those scenario ids.
61
+
62
+ ## 4. Full suite and style (SC-009)
63
+
64
+ ```sh
65
+ bundle exec rspec
66
+ bundle exec rubocop
67
+ ```
68
+
69
+ ## 5. Demo acceptance (Constitution VI, SC-009)
70
+
71
+ Use an isolated compose project, because the fixed container names collide across worktrees.
72
+ Create an override file that gives unique `container_name`s and `ports: !reset []` for
73
+ `demo-redis` and `demo-app`, then:
74
+
75
+ ```sh
76
+ docker compose -p rr_rollback -f docker-compose.yml -f /tmp/rr_rollback.override.yml \
77
+ up -d --build demo-redis demo-sidekiq
78
+ docker compose -p rr_rollback -f docker-compose.yml -f /tmp/rr_rollback.override.yml \
79
+ run --rm --no-deps demo-app bash -c "bin/rails db:prepare && bin/rails demo:rollback_reliability"
80
+ docker compose -p rr_rollback -f docker-compose.yml -f /tmp/rr_rollback.override.yml \
81
+ run --rm --no-deps demo-app bash -c "bundle exec rspec spec/reactors/map_refund_demo_reactor_spec.rb spec/reactors/compose_retry_demo_reactor_spec.rb spec/reactors/argument_failure_demo_reactor_spec.rb spec/reactors/async_step_compensate_demo_reactor_spec.rb"
82
+ ```
83
+
84
+ **Expected** output of `demo:rollback_reliability`, one block per scenario:
85
+
86
+ - **Map refund**: charges for orders 0..N-1 are refunded when order N fails, and all of them are
87
+ refunded when the post-map step fails.
88
+ - **Compose retry**: the child's flaky step retries inside the child. The child's first step runs
89
+ once. A later failure undoes each child step once.
90
+ - **Argument failure**: the earlier step is undone, and the failure names the step whose transform
91
+ raised. A step class that raises a non-`StandardError` (`NotImplementedError`) is rolled back the
92
+ same way.
93
+ - **`async_step` compensate**: the unit's record shows `compensation.status = completed` after its
94
+ retries are exhausted.
95
+
96
+ `demo:all` includes the new task.
97
+
98
+ ## 6. Documentation check (SC-007)
99
+
100
+ Search the README and `./documentation` for `where`, `guard`, `ConditionError`, and `retries` inside
101
+ a `compose`/`async_reactor`: the only hits are migration notes (SC-011).
102
+
103
+ For each row in 007 [findings-and-options.md §2](../007-execution-flow-analysis/analysis/findings-and-options.md#2-documentation-audit)
104
+ tied to F-01..F-06 or F-13, open the cited README/documentation line and confirm it describes the
105
+ new behavior. The 007 `invariants.md` shows INV-06, 07, 13, 19, 20, 22 and 24 as **HOLDS**.