Skip to content

fix(openclaw): make queued retains idempotent - #3143

Open
r266-tech wants to merge 3 commits into
vectorize-io:mainfrom
r266-tech:r266/openclaw-retain-idempotency
Open

fix(openclaw): make queued retains idempotent#3143
r266-tech wants to merge 3 commits into
vectorize-io:mainfrom
r266-tech:r266/openclaw-retain-idempotency

Conversation

@r266-tech

@r266-tech r266-tech commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #3114.

What changed

  • assign one UUID to each logical async retain before its first send
  • preserve that UUID in RetainQueue JSONL rows and pass it through the typed client as operationId on every supported replay
  • probe /version before sends and flushes so old servers omit the wire field, while an unknown capability queues instead of risking a non-idempotent request
  • atomically upgrade legacy queue rows with an ID before their first supported replay
  • bind retain work to a service generation and abort signal so a stopped instance cannot resume against a restarted client
  • checkpoint each acknowledged queue item before awaiting the next send

This keeps compatibility with pre-0.8.6 servers and legacy queue rows while preventing a lost acknowledgement from creating duplicate durable memories and provider work.

Validation

  • npm test — 11 files, 294 tests passed
  • npm run build
  • Prettier check for all six changed files
  • generated OpenAPI skill reference is byte-for-byte identical to its canonical file (the PR base currently contains mirror drift, which failed verify-generated-files)
  • ./scripts/hooks/lint.sh — all runnable tasks passed; the unrelated control-plane ESLint task could not load @eslint/js from its local workspace installation

The regression coverage includes lost acknowledgements, restart replay, capability downgrade/upgrade, legacy rows, timer-driven flushes, stop during a version probe, stale hooks across restart, and per-item checkpointing after a partial batch acknowledgement.

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.

hindsight-openclaw: RetainQueue retries are not idempotent — plugin never sends operation_id (API supports it since 0.8.6)

1 participant