Fix and clarify Cloudflare Workers documentation#669
Conversation
Update the Cloudflare Workers README snippet to use the current federation API. The example now imports createFederation, calls federation.fetch(), and passes context data and a Message value to processQueuedTask(). AI-assisted with Codex for drafting and editing the documentation changes; reviewed in the workspace. Co-Authored-By: OpenAI Codex <noreply@openai.com>
Correct the Cloudflare Workers deployment example to match the processQueuedTask() signature and repair the broken InProcessMessageQueue anchor in the same guide. AI-assisted with Codex for drafting and editing the documentation changes; reviewed in the workspace. Co-Authored-By: OpenAI Codex <noreply@openai.com>
Explain the extra queue consumer step needed for ordering keys on Cloudflare Workers. The manual, deployment guide, and package README now point users to orderingKv and WorkersMessageQueue.processMessage(). AI-assisted with Codex for drafting and editing the documentation changes; reviewed in the workspace. Co-Authored-By: OpenAI Codex <noreply@openai.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughDocumentation updates for Cloudflare Workers message queue handling, including corrected documentation links, reordered function arguments in examples, and new guidance on using Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces support for best-effort message ordering on Cloudflare Workers by allowing the use of an ordering KV namespace with WorkersMessageQueue. It updates the documentation to explain the new process of calling WorkersMessageQueue.processMessage() before Federation.processQueuedTask(), and includes minor refactors to the Cloudflare Workers example code to improve consistency and correctness. I have no feedback to provide as the changes are well-documented and follow the established patterns.
There was a problem hiding this comment.
Pull request overview
This PR updates Cloudflare Workers-related documentation to match the current Fedify APIs, correcting outdated examples and adding guidance for queue ordering keys when using WorkersMessageQueue.
Changes:
- Update Cloudflare Workers examples to use
createFederation(),federation.fetch(), and the currentFederation.processQueuedTask(contextData, message)signature. - Fix a broken
InProcessMessageQueueanchor in the deployment manual. - Add documentation about
orderingKv/WorkersMessageQueue.processMessage()for best-effort ordering-key handling, and link to the detailed guidance.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| packages/cfworkers/README.md | Updates Workers example code and adds an ordering-key note for WorkersMessageQueue. |
| docs/manual/mq.md | Documents ordering-key consumption flow with WorkersMessageQueue.processMessage() and orderingKv. |
| docs/manual/deploy.md | Fixes anchor + updates processQueuedTask() usage and adds a link to ordering-key guidance. |
| await federation.processQueuedTask( | ||
| env, | ||
| message.body as unknown as Message, |
There was a problem hiding this comment.
WorkersMessageQueue.enqueue() wraps queued bodies in a { __fedify_payload__: ... } envelope (and optionally __fedify_ordering_key__). Passing message.body directly to Federation.processQueuedTask() will therefore hand it the wrapper object (missing type, id, traceContext, etc.) and can fail at runtime. Unwrap first via WorkersMessageQueue.processMessage(message.body) and pass result.message to processQueuedTask() (even when not using ordering keys).
| await federation.processQueuedTask( | |
| env, | |
| message.body as unknown as Message, | |
| const result = WorkersMessageQueue.processMessage(message.body); | |
| await federation.processQueuedTask( | |
| env, | |
| result.message, |
| > `Federation.processQueuedTask()`. This acquires and releases the best-effort | ||
| > ordering lock for that key. You can also customize the lock behavior with | ||
| > the `orderingKeyPrefix` and `orderingLockTtl` options. |
There was a problem hiding this comment.
This note says processMessage() “acquires and releases” the ordering lock, but processMessage() only acquires and returns a release callback; callers must invoke result.release?.() (typically in a finally) to actually release the lock. Consider updating the wording to avoid implying the lock is released automatically.
| > `Federation.processQueuedTask()`. This acquires and releases the best-effort | |
| > ordering lock for that key. You can also customize the lock behavior with | |
| > the `orderingKeyPrefix` and `orderingLockTtl` options. | |
| > `Federation.processQueuedTask()`. This acquires the best-effort ordering | |
| > lock for that key and returns a `release` callback; call | |
| > `result.release?.()` after processing the message, typically in a `finally` | |
| > block. You can also customize the lock behavior with the | |
| > `orderingKeyPrefix` and `orderingLockTtl` options. |
| > `Federation.processQueuedTask()`. Otherwise, the ordering key is embedded in | ||
| > the message, but not enforced when the worker consumes it. |
There was a problem hiding this comment.
This note implies processMessage() will enforce ordering by itself, but it only returns a release callback for the acquired lock; the consumer must call result.release?.() after processing to release it. Consider explicitly mentioning the required release call so readers don’t accidentally leak locks until TTL expiration.
| > `Federation.processQueuedTask()`. Otherwise, the ordering key is embedded in | |
| > the message, but not enforced when the worker consumes it. | |
| > `Federation.processQueuedTask()`. `processMessage()` does not enforce | |
| > ordering by itself; it returns a result that includes a `release` callback | |
| > for the acquired ordering lock, and you must call `result.release?.()` | |
| > after processing the message (preferably in a `finally` block). Otherwise, | |
| > the ordering key is embedded in the message, but not enforced correctly | |
| > when the worker consumes it, and the lock may remain held until its TTL | |
| > expires. |
| for (const message of batch.messages) { | ||
| try { | ||
| await federation.processQueuedTask( | ||
| message.body as unknown as Message, | ||
| env, | ||
| message.body as unknown as Message, | ||
| ); |
There was a problem hiding this comment.
The manual queue() example passes message.body directly into Federation.processQueuedTask(), but WorkersMessageQueue wraps outgoing bodies in a { __fedify_payload__: ... } envelope (and possibly __fedify_ordering_key__). Without unwrapping via WorkersMessageQueue.processMessage(message.body), processQueuedTask() will receive the wrapper object and can fail at runtime.
| If you use queue ordering keys on Cloudflare Workers, instantiate | ||
| `WorkersMessageQueue` with an `orderingKv` namespace and call | ||
| `WorkersMessageQueue.processMessage()` before | ||
| `Federation.processQueuedTask()`. See the | ||
| [*`WorkersMessageQueue`* section](./mq.md#workersmessagequeue-cloudflare-workers-only) | ||
| for a complete example and caveats about best-effort ordering. |
There was a problem hiding this comment.
This paragraph suggests WorkersMessageQueue.processMessage() is only needed when using ordering keys, but processMessage() is also what unwraps the { __fedify_payload__: ... } envelope used for queue messages. As written, readers may skip processMessage() and pass the wrapped body to processQueuedTask(), leading to runtime errors. Consider rephrasing to recommend processMessage() for all consumed messages, with orderingKv being the extra requirement to enforce ordering locks.
| > If you use `~MessageQueueEnqueueOptions.orderingKey` with | ||
| > `WorkersMessageQueue`, you also need to provide a KV namespace for ordering | ||
| > locks and pass each raw queue message through | ||
| > `~WorkersMessageQueue.processMessage()` before calling | ||
| > `Federation.processQueuedTask()`. Otherwise, the ordering key is embedded in | ||
| > the message, but not enforced when the worker consumes it. |
There was a problem hiding this comment.
This note frames WorkersMessageQueue.processMessage() as only necessary when orderingKey is used, but processMessage() is also what unwraps the { __fedify_payload__: ... } envelope used for queued messages. If readers skip processMessage() for non-ordered messages, they may pass the wrapped body into Federation.processQueuedTask() and hit runtime errors. Update the wording to recommend processMessage() for all consumed messages, and mention orderingKv as the additional requirement to enforce ordering locks.
| > If you use `~MessageQueueEnqueueOptions.orderingKey` with | |
| > `WorkersMessageQueue`, you also need to provide a KV namespace for ordering | |
| > locks and pass each raw queue message through | |
| > `~WorkersMessageQueue.processMessage()` before calling | |
| > `Federation.processQueuedTask()`. Otherwise, the ordering key is embedded in | |
| > the message, but not enforced when the worker consumes it. | |
| > When consuming messages from `WorkersMessageQueue`, always pass each raw | |
| > queue message through `~WorkersMessageQueue.processMessage()` before | |
| > calling `Federation.processQueuedTask()`. This unwraps the queued payload | |
| > format and, when present, applies ordering metadata. If you use | |
| > `~MessageQueueEnqueueOptions.orderingKey` with `WorkersMessageQueue`, you | |
| > also need to provide a KV namespace for ordering locks; otherwise, the | |
| > ordering key is embedded in the message, but not enforced when the worker | |
| > consumes it. |
Codecov Report✅ All modified and coverable lines are covered by tests. 🚀 New features to boost your workflow:
|
Summary
This PR fixes a few immediate mismatches in the Cloudflare Workers documentation.
packages/cfworkers/README.md still showed outdated API usage, and docs/manual/deploy.md had a
processQueuedTask()example that no longer matched the current signature. While updating those examples, this PR also documents the extra consumer-side step required whenWorkersMessageQueueis used withorderingKey.Changes
createFederation(),federation.fetch(), and the currentprocessQueuedTask(contextData, message)signatureprocessQueuedTask()mismatch in docs/manual/deploy.mdInProcessMessageQueueanchor in docs/manual/deploy.mdorderingKvandWorkersMessageQueue.processMessage()in docs/manual/mq.md, and link back to that guidance from docs/manual/deploy.md and packages/cfworkers/README.mdWhy
These examples are easy to copy into real projects, so small mismatches matter. The old
federation.handle()call and the staleprocessQueuedTask()example can send readers to APIs that no longer exist or no longer accept those arguments. The ordering-key note closes a separate gap between the published docs and the currentWorkersMessageQueueimplementation.Verification
This is a docs-only change. I cross-checked the updated examples against the current implementations in packages/fedify/src/federation/federation.ts and packages/cfworkers/src/mod.ts.