active_durable 0.5.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 +7 -0
- data/CHANGELOG.md +131 -0
- data/LICENSE.txt +21 -0
- data/README.md +630 -0
- data/Rakefile +12 -0
- data/app/controllers/active_durable/application_controller.rb +25 -0
- data/app/controllers/active_durable/executions_controller.rb +59 -0
- data/app/helpers/active_durable/dashboard_helper.rb +163 -0
- data/app/views/active_durable/executions/index.html.erb +90 -0
- data/app/views/active_durable/executions/show.html.erb +197 -0
- data/app/views/layouts/active_durable/application.html.erb +422 -0
- data/config/routes.rb +13 -0
- data/lib/active_durable/configuration.rb +59 -0
- data/lib/active_durable/engine.rb +24 -0
- data/lib/active_durable/errors.rb +61 -0
- data/lib/active_durable/execution.rb +43 -0
- data/lib/active_durable/flow.rb +277 -0
- data/lib/active_durable/flow_parallel.rb +200 -0
- data/lib/active_durable/lease.rb +50 -0
- data/lib/active_durable/notebook.rb +100 -0
- data/lib/active_durable/open_telemetry.rb +94 -0
- data/lib/active_durable/operations.rb +111 -0
- data/lib/active_durable/parallel.rb +54 -0
- data/lib/active_durable/record.rb +13 -0
- data/lib/active_durable/registry.rb +89 -0
- data/lib/active_durable/retry_policy.rb +42 -0
- data/lib/active_durable/run_job.rb +12 -0
- data/lib/active_durable/runner.rb +157 -0
- data/lib/active_durable/serializer.rb +40 -0
- data/lib/active_durable/signal_record.rb +20 -0
- data/lib/active_durable/step.rb +34 -0
- data/lib/active_durable/sweep_job.rb +12 -0
- data/lib/active_durable/sweeper.rb +22 -0
- data/lib/active_durable/testing.rb +118 -0
- data/lib/active_durable/version.rb +5 -0
- data/lib/active_durable.rb +145 -0
- data/lib/generators/active_durable/install/install_generator.rb +27 -0
- data/lib/generators/active_durable/install/templates/create_active_durable_tables.rb.tt +60 -0
- data/lib/tasks/active_durable.rake +24 -0
- data/sig/active_durable.rbs +4 -0
- metadata +134 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 593d546eb6e8e46a70c03be3945934ed0c8a189937a5a27256478783cd345df0
|
|
4
|
+
data.tar.gz: 3226b77ada034c6bf49830dfdb30457904e14104b430b4cfb0a9def3d3de4124
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f0f0adcff14966f0b8cf7710218a6a6df9b27152593ea4d0d29c90f1968967817b467c33b9803dac0b7aaec6ff105c291a50ecf1335f15882b1969c4d7f7d2bd
|
|
7
|
+
data.tar.gz: 1ecba4e399e4f9a247ea9717e9727a50c86d7389aa41a4e53fe3aa9817a100e04a91ecfdc7a2dc51333b24ae9b94a666f1a3c2d5e1987132a48949970a210592
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/). Before 1.0 the database schema may change between minor versions:
|
|
6
|
+
regenerate the migration when upgrading.
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- README: the quick start recipe reads top to bottom, with one-line undos and the Stripe calls in a `Payments`
|
|
13
|
+
module where charging and refunding sit side by side. A new section, "In a Rails app", sets up a Rails app step by
|
|
14
|
+
step: install, job backend, sweeper, the initializer with every setting, routes, where each piece of code goes
|
|
15
|
+
(recipe, service, controller, model, view), how the job is managed when the gem owns it, tests, and a checklist
|
|
16
|
+
before going to production. The settings moved there from "Observability".
|
|
17
|
+
- Specs cover undos without arguments (`-> { ... }`), a `Method` as an undo, and `flow.abort!` inside a step, which
|
|
18
|
+
skips the step's remaining retries.
|
|
19
|
+
|
|
20
|
+
## [0.5.0] - 2026-10-06
|
|
21
|
+
|
|
22
|
+
More Ruby and Rails versions, and a README in two languages.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Supports Ruby 3.1+ and Rails 6.1+ (was Ruby 3.3+ and Rails 7.2+), with every feature on every version. The
|
|
27
|
+
notebook no longer relies on `ActiveRecord.after_all_transactions_commit`: `flow.transaction` steps and their
|
|
28
|
+
undos run inside `Notebook#transaction`, which remembers their writes only once the transaction commits.
|
|
29
|
+
- CI covers Ruby 3.1, 3.2, 3.3, 3.4 and 4.0 against Rails 6.1, 7.0, 7.1, 7.2, 8.0 and 8.1 and the three
|
|
30
|
+
databases (84 jobs). MySQL runs on mysql2 for Rails 6.1 and 7.0, and on trilogy from 7.1. Each job resolves its
|
|
31
|
+
own gems from `gemfiles/rails-X.Y.gemfile`; per-Rails lockfiles are no longer committed, so they can never fall
|
|
32
|
+
behind the gem version (which broke the 0.4.0 CI run).
|
|
33
|
+
- The README is rewritten, with animated explanations (`docs/assets/*.svg`, built by `docs/assets/generate.rb`),
|
|
34
|
+
dashboard screenshots, a state diagram and a compatibility table.
|
|
35
|
+
- The README also exists in Spanish (`README.es.md`, with its own animations). `CONTRIBUTING.md` and `CLAUDE.md`
|
|
36
|
+
ask to update both, and `spec/readme_spec.rb` fails when they drift apart.
|
|
37
|
+
- Dashboard: long step names wrap at underscores, and notebook results get room to breathe.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- Dashboard: on Rails 6.1 and 7.0, `Rails.env.local?` silently answered false, which would have closed the
|
|
42
|
+
dashboard in development too. It now checks for development and test explicitly.
|
|
43
|
+
- Migration: datetime columns are created with microsecond precision on every Rails version.
|
|
44
|
+
- The packaged gem no longer includes `gemfiles/`.
|
|
45
|
+
|
|
46
|
+
## [0.4.0] - 2026-10-05
|
|
47
|
+
|
|
48
|
+
The dashboard, redrawn.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- The dashboard is redrawn full screen: a rail with statuses and recipes, and every saga shown as a row of blocks.
|
|
53
|
+
Each block's animation tells its state (running beats, a waiting step pings like a radar, a sleeping one fills
|
|
54
|
+
a ring until it wakes, a failed one shakes, undone ones are striped and wired backwards), with a visible point
|
|
55
|
+
of no return, live countdowns, and a live mode that refreshes the list and flashes the rows that changed.
|
|
56
|
+
Animations stop when the system asks for reduced motion.
|
|
57
|
+
- The gemspec links to the GitHub repository (homepage, source, changelog and issues).
|
|
58
|
+
|
|
59
|
+
## [0.3.0] - 2026-10-05
|
|
60
|
+
|
|
61
|
+
Third version: everything the design called "later", except the Rust gem.
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
|
|
65
|
+
- `flow.parallel`: branches that run in threads, each checkpointed with its own ticket and retries. Unfinished
|
|
66
|
+
branches resume after a crash; completed ones are undone in the order they finished. Branch threads run inside
|
|
67
|
+
the Rails executor and keep OpenTelemetry context.
|
|
68
|
+
- Recipe versions: `Durable.define(name, version:)`, executions keep the version they started with,
|
|
69
|
+
`ActiveDurable.versions_in_use` and `rake active_durable:versions`.
|
|
70
|
+
- `ActiveDurable::OpenTelemetry.install!`: nested spans for executions, steps, compensations and undos.
|
|
71
|
+
- `ActiveDurable.branch_wrappers` to carry other thread-local context into parallel branches.
|
|
72
|
+
|
|
73
|
+
### Fixed
|
|
74
|
+
|
|
75
|
+
- The dashboard was open in every environment except production (staging included). Without
|
|
76
|
+
`config.dashboard_authorize` it now opens only in development and test.
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
|
|
80
|
+
- MySQL 8+ and SQLite 3 are supported and run the full suite, like PostgreSQL. Tested on Rails 7.2, 8.0 and 8.1.
|
|
81
|
+
- The notebook is safe to write from several threads, and only remembers writes whose transaction committed.
|
|
82
|
+
- The registry looks the recipe constant up on every use, so an edited recipe is picked up after a code reload
|
|
83
|
+
in development.
|
|
84
|
+
- One Gemfile per Rails version (`gemfiles/`) with lockfiles for Linux, used by the CI matrix.
|
|
85
|
+
|
|
86
|
+
## [0.2.0] - 2026-10-05
|
|
87
|
+
|
|
88
|
+
Second version: see it and operate it.
|
|
89
|
+
|
|
90
|
+
### Added
|
|
91
|
+
|
|
92
|
+
- `ActiveDurable.retry`, `ActiveDurable.compensate` and `ActiveDurable.rerun` (see `ActiveDurable::Operations`).
|
|
93
|
+
They refuse executions a worker holds and rotate the lease token.
|
|
94
|
+
- Reruns: a new execution (`<id>~rerun-N`, `forked_from`) that reuses the completed steps before a chosen step.
|
|
95
|
+
A blocked original becomes `superseded`.
|
|
96
|
+
- The dashboard engine (`mount ActiveDurable::Engine => "/durable"`): executions by status and recipe, notebooks
|
|
97
|
+
with tickets, undos and signals, and the three operations. It works in API-only apps with its own cookie
|
|
98
|
+
session and CSRF protection, and is closed in production until `config.dashboard_authorize` is set.
|
|
99
|
+
- Events: `completed`, `compensated`, `blocked`, `retried`, `compensation_requested` and `rerun`
|
|
100
|
+
(`*.active_durable`).
|
|
101
|
+
- `bin/demo` to browse the dashboard with sample sagas.
|
|
102
|
+
|
|
103
|
+
### Changed
|
|
104
|
+
|
|
105
|
+
- Requires Ruby 3.3+ (3.2 is end of life) and Rails 7.2+.
|
|
106
|
+
- A compensation that reaches a completed `flow.pivot` blocks instead of undoing past the point of no return.
|
|
107
|
+
- Schema: `durable_executions.forked_from` (regenerate the migration).
|
|
108
|
+
|
|
109
|
+
## [0.1.0] - 2026-10-05
|
|
110
|
+
|
|
111
|
+
First version: nothing gets lost.
|
|
112
|
+
|
|
113
|
+
### Added
|
|
114
|
+
|
|
115
|
+
- `Durable.define` and `Durable.start`: named recipes and executions stored in `durable_executions`. The execution
|
|
116
|
+
row is the outbox: the job is enqueued after commit.
|
|
117
|
+
- The notebook (`durable_steps`): steps are checkpointed and skipped on replay.
|
|
118
|
+
- `flow.step` with a stable ticket per step for idempotency keys, and retries with configurable backoff.
|
|
119
|
+
- `flow.transaction`: a database-only step committed together with its checkpoint (exactly once).
|
|
120
|
+
- `flow.pivot`: the point of no return. Before it failures compensate; after it steps are retried, then blocked.
|
|
121
|
+
- Compensation in reverse order, checkpointed per undo and resumable after a crash. `undo_on_failure:` for steps
|
|
122
|
+
whose failure may hide a success.
|
|
123
|
+
- `flow.sleep`, `flow.wait_for` and `Durable.signal` (`durable_signals`), without holding a worker.
|
|
124
|
+
- A lease with a fencing token: one worker per execution, and a worker that lost its lease cannot write.
|
|
125
|
+
- The recipe-changed alarm (`ActiveDurable::RecipeChanged`) and checks for duplicated step names and non-JSON
|
|
126
|
+
results.
|
|
127
|
+
- `ActiveDurable::Sweeper` / `SweepJob` / `rake active_durable:sweep` for lost jobs and expired leases.
|
|
128
|
+
- `ActiveDurable::Testing.crash_everywhere` and `ActiveDurable::Testing.drain`.
|
|
129
|
+
- `rails generate active_durable:install`.
|
|
130
|
+
- `ActiveSupport::Notifications` events: `execution.active_durable`, `step.active_durable`,
|
|
131
|
+
`compensation.active_durable` and `undo.active_durable`.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 William Romero
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|