From 3d685352143275fe7c7159c8c20193f77c8293c7 Mon Sep 17 00:00:00 2001 From: Lucas Carlson Date: Sun, 9 Aug 2026 21:25:43 -0700 Subject: [PATCH 1/2] docs: record the PostgreSQL wake-up adapter Milestone 2 shipped without the roadmap being updated, so it still described PostgreSQL notifications as unimplemented and the cross-process polling delay as unaddressed. Record the adapter, its measured latency, why it is opt-in rather than automatic, and that MySQL has no notification primitive. Milestone 2 now covers only the remaining Redis adapter. --- docs/roadmap.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/roadmap.md b/docs/roadmap.md index 0d7e925..4e6bded 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -32,6 +32,8 @@ graceful caller shutdown, committed state snapshots, and an opt-in Minitest helper - SQLite, PostgreSQL, and MySQL integration suites +- Opt-in cross-process wake-up on PostgreSQL through `WakeUpAdapters.for`, with + a listening connection per waiting thread and release on supervisor shutdown - Inline RBS generation/validation, Steep, Standard Ruby, Solid Queue's exact RuboCop policy, and a warning-free Brakeman scan - A JavaScript suite covering the state payload and batched refresh browser @@ -42,12 +44,16 @@ - Supervisor: starts and drains thread roles, but does not replace a crashed role or run periodic maintenance automatically. -- Wake-up strategy: in-process signaling plus durable polling and injection are - implemented; PostgreSQL `LISTEN/NOTIFY` and optional Redis adapters are not. - Signaling cannot cross process boundaries, so a commit in a web process does - not wake a broadcast executor in a worker process; that delivery waits up to - `polling_interval`, 100 ms by default. This is the largest remaining term in - reactive update latency, and neither batching nor state payloads reduce it. +- Wake-up strategy: in-process signaling, durable polling, injection, and an + opt-in PostgreSQL notification adapter are implemented; a Redis adapter is + not. In-process signaling cannot cross process boundaries, so without the + adapter a commit in a web process does not wake a broadcast executor in a + worker process and that delivery waits up to `polling_interval`, 100 ms by + default. `WakeUpAdapters.for` removes that delay on PostgreSQL, measured at + 103.7 ms to 2.9 ms at p50. It is opt-in rather than automatic: it opens a + connection per waiting thread outside the pool, and `LISTEN` does not survive + a transaction-pooling proxy such as PgBouncer. MySQL has no notification + primitive, so MySQL applications keep polling. - Realtime: scalar and dependency-driven keyed ERB component replacement or morphing, personalized refresh authorization, revision fencing, coalescing, reconnect convergence, batched refreshes, and personalized state payloads are @@ -68,9 +74,9 @@ ## Next milestones 1. Add automatic supervisor role replacement and periodic dead-process cleanup. -2. Add PostgreSQL notification and optional Redis wake-up adapters with latency - benchmarks and polling-race tests, removing the cross-process polling delay - rather than shrinking it with a smaller `polling_interval`. +2. Add an optional Redis wake-up adapter, which is the remaining cross-process + option for MySQL. The PostgreSQL notification adapter, its latency + benchmark, and its concurrency tests are implemented. 3. Add result lookup by request ID and broader deadlock retry classification. 4. Add scheduled retention and stale-process maintenance. 5. Add database/server-version checks and MySQL InnoDB verification at boot. From 6ee836426db0745ce6abb5dd4fa8b4d82a06ca18 Mon Sep 17 00:00:00 2001 From: Lucas Carlson Date: Sun, 9 Aug 2026 21:27:25 -0700 Subject: [PATCH 2/2] docs: require roadmap updates alongside features Two releases shipped milestones without the roadmap following, leaving it claiming that implemented capabilities were missing. Make the update part of the pull request that changes what the project claims about itself, and say plainly that correcting a stale entry matters more than appending a new one. --- AGENTS.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 5f444b9..4dbcac2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,6 +28,16 @@ Write Minitest files as `test/**/*_test.rb`. Start behavioral changes with a foc Use concise imperative subjects, preferably under 50 characters; use prefixes such as `fix:`, `ci:`, or `chore:`. Pull requests should explain API, correctness, security, migration, and compatibility effects; list exact validation commands; link issues; and include screenshots for UI or reactive ERB changes. Never bypass hooks or add AI attribution. +Update `docs/roadmap.md` in the same pull request whenever the change alters +what the project claims about itself. That includes completing or advancing a +numbered milestone, moving an entry between "Implemented and tested" and +"Partially implemented", and discovering a limitation worth recording, such as a +capability that turns out to be opt-in, adapter-specific, or measured rather +than assumed. Prefer correcting a stale entry over only appending a new one: an +inaccurate claim misleads more than a missing one. State what was measured and +what was not, so a reader can tell evidence from intent. A change that only +fixes a defect, adjusts tooling, or edits prose does not need a roadmap edit. + ## Release Workflow Update the version, `CHANGELOG.md`, and `Gemfile.lock`; run `bundle exec rake`; then commit and push `main`. Publish by pushing an annotated version tag: