Skip to content

afterCommit follow-ups: end on uninstall, revoke or lost read; drop stale proposals - #1934

Closed
michielbdejong wants to merge 2 commits into
claude/durable-after-commitfrom
claude/after-commit-followups
Closed

michielbdejong wants to merge 2 commits into
claude/durable-after-commitfrom
claude/after-commit-followups

Conversation

@michielbdejong

Copy link
Copy Markdown
Contributor

Related Issues

Part of #1907 (the server-side items). Stacked on #1906: the base is its branch, so the diff shows only these commits. Everything is behind --plugin-after-commit, like #1906.

What changes

  • Uninstall and revoke. Destroying the app or its Installation, or revoking the Installation, ends the subscription (ended_via: "uninstalled" / "revoked"). Its markers, delivery, waiting proposal and own-write records are deleted. A paused Installation still only waits.
    • The subscription record is kept, marked ended, the same way a removed View is handled, so the Installation page can say why it stopped. The design table said "deleted"; the planning doc now describes this instead.
  • Ending promptly. The delivery worker listens to the store's change events. When a subscription's table, one of the table's ancestors (read rights are inherited), its View, app or Installation changes, the next tick (1 s) re-checks those subscriptions and ends the ones that can never deliver again. That includes an activator who lost read access.
    • A lagging broadcast re-checks every subscription.
    • The 10-minute sweep re-checks everything too, as a backstop for rights that change elsewhere, such as a group's members.
    • Row edits don't trigger the check.
  • Stale proposals. A proposal records the source hash that made it. If the app's source changes while it waits, the proposal is discarded (its journal is abandoned, with the reason) and the same page is delivered again as a new delivery to the new source. Answering a stale proposal is refused with that explanation.
  • The race. "A person's edit just before the hook's write" is tested through the review window, the widest one: both writes survive (Loro merges per property), and the person's edit is delivered next rather than dropped as the hook's echo. The existing rule, that an own write is recorded only when the row was still at the version the hook saw, already covers this; the test proves it.

Refactor: eligibility's end checks moved into row_class_or_end / end_reason, which the event path and the sweep share. end_finished takes the delivery lock, so a delivery in progress never saves over an ended subscription.

Not in this PR: the Playwright spec from #1907.

Checklist

  • Add changelog entry linking to issue, describe API changes: not added; Durable afterCommit for user-installed plugins, behind --plugin-after-commit (#1851) #1906 (unreleased, behind a flag) has none yet either.
  • Add or update tests if needed: 7 new tests in server/src/plugins/after_commit_test.rs:
    • revoke ends the subscription on the next tick and drops its proposal;
    • pause does not end it;
    • uninstall ends it at the sweep;
    • lost read ends it when the table's rights change, and a row edit doesn't end it;
    • a stale proposal is refused on review, and the page reruns on the new release;
    • the worker discards a stale proposal by itself;
    • the race test above.
    • Run: cargo test -p atomic-server --lib -- after_commit (29 passed), cargo clippy -p atomic-server --all-targets -- -D warnings, cargo fmt --check.
  • Update docs if needed: docs/src/plugins/creating-plugins.md (when a subscription ends; a release change drops a waiting proposal), planning/durable-after-commit.md and TESTING_COVERAGE.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_011KbrNpTmoDhqsVVrSxb64R


Generated by Claude Code

… proposals (#1907)

WIP: not yet compiled or tested.

- Uninstalling the app or its Installation, or revoking the Installation,
  ends the subscription (`uninstalled` / `revoked`) and drops its markers,
  delivery, waiting proposal and own-write records. Pausing still waits.
- The worker listens to the store's change events: a change to a
  subscription's table, one of its ancestors, View, app or Installation
  re-checks it on the next tick, so losing read access ends it promptly. A
  lagging broadcast and the 10-minute sweep re-check everything.
- A proposal records the source hash that made it; if the app's source
  changes while it waits, it is discarded (journal abandoned with the
  reason) and the same page is delivered again to the new source. Answering
  a stale one is refused.
- Tests for each, and for a person's edit landing while a proposal waits.
- Docs, planning notes and TESTING_COVERAGE updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011KbrNpTmoDhqsVVrSxb64R
Tested: cargo test -p atomic-server --lib -- after_commit (29 passed, 7
of them new), clippy --all-targets -D warnings, cargo fmt --check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011KbrNpTmoDhqsVVrSxb64R
@michielbdejong

Copy link
Copy Markdown
Contributor Author

Closing as part of the plugin-host stack cleanup (Q-101): not needed by atomic-plugins now. See the inventory at #1726 (comment). The branch is kept, and pin candidates are unaffected. Closed by Claude (VPS coordinator) on behalf of Michiel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants