Skip to content

Message byte estimation and batching on @fedify/cfworkers#960

Merged
dahlia merged 3 commits into
fedify-dev:2.0-maintenancefrom
SJang1:patch-2
Jul 19, 2026
Merged

Message byte estimation and batching on @fedify/cfworkers#960
dahlia merged 3 commits into
fedify-dev:2.0-maintenancefrom
SJang1:patch-2

Conversation

@SJang1

@SJang1 SJang1 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixed WorkersMessageQueue.enqueueMany() failing when the given messages exceeded Cloudflare Queues' batch limits of 100 messages or 256 KB per batch.

Assisted-by: chatgpt codex-5.6-sol

Changes

  • estimates the serialized size of each message
  • splits the messages into multiple sendBatch() calls

Added message byte estimation and batching logic to handle message limits.

Assisted-By: codex-5.6-sol
Copilot AI review requested due to automatic review settings July 19, 2026 06:37
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 468d7561-3542-4592-8172-475ff2ea8501

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements batching logic in WorkersMessageQueue.enqueueMany to comply with Cloudflare Queue limits (maximum of 100 messages or 240 KB per batch). It estimates message sizes using JSON.stringify and TextEncoder and flushes batches accordingly. The review feedback points out that the check for serialized === undefined is redundant and can be removed because JSON.stringify on a plain object will never return undefined.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +352 to +356
const serialized = JSON.stringify(body);

if (serialized === undefined) {
throw new TypeError("Queue message must be JSON-serializable.");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since body is a plain object literal, JSON.stringify(body) will never return undefined (it would only return undefined if the top-level value itself was undefined, a function, or a symbol). Therefore, the check for serialized === undefined is unreachable dead code and can be safely removed.

Suggested change
const serialized = JSON.stringify(body);
if (serialized === undefined) {
throw new TypeError("Queue message must be JSON-serializable.");
}
const serialized = JSON.stringify(body);

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes WorkersMessageQueue.enqueueMany() in @fedify/cfworkers so it no longer fails Cloudflare Queues’ sendBatch() limits by estimating message sizes and splitting large fan-out operations into multiple batches.

Changes:

  • Added batch limit constants and a UTF-8 byte-size estimator for JSON-serialized messages.
  • Implemented incremental batching with flush() to issue multiple sendBatch() calls based on message count and estimated total bytes.

Comment on lines +387 to +393
const messageBytes = estimateMessageBytes(body);
const exceedsBatchLimit = batch.length >= MAX_BATCH_MESSAGES ||
estimatedBatchBytes + messageBytes > MAX_ESTIMATED_BATCH_BYTES;

if (batch.length > 0 && exceedsBatchLimit) {
await flush();
}
Comment on lines +376 to +379
for (const message of messages) {
const body = {
__fedify_ordering_key__: options?.orderingKey,
__fedify_payload__: msg,
} satisfies WrappedMessage,
contentType: "json",
}));
await this.#queue.sendBatch(requests, {
delaySeconds: options?.delay?.total("seconds") ?? 0,
});
__fedify_payload__: message,
@codecov

codecov Bot commented Jul 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.
see 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b7322dc5d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +388 to +389
const exceedsBatchLimit = batch.length >= MAX_BATCH_MESSAGES ||
estimatedBatchBytes + messageBytes > MAX_ESTIMATED_BATCH_BYTES;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject messages over Cloudflare's item limit

When one serialized wrapped message is over Cloudflare's 128 KB per-item limit but under this 240 KB batch threshold, exceedsBatchLimit is false for an empty batch, so enqueueMany() still sends an invalid item; if this occurs after a previous size-triggered flush, earlier messages have already been enqueued before the method rejects, so retrying can duplicate deliveries. Cloudflare documents that each sendBatch item is limited to 128 KB (https://developers.cloudflare.com/queues/configuration/javascript-apis/#queue), so these items should be preflighted/rejected before any flush or send.

Useful? React with 👍 / 👎.

Comment on lines 346 to 347
messages: readonly any[],
options?: MessageQueueEnqueueOptions,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include required bugfix artifacts

This commit is explicitly a bug fix for #958, but the patch only changes the implementation; the root AGENTS.md “Bugfix process” requires both a regression test demonstrating the bug and a CHANGES.md entry. Without tests covering the >100-message and >256 KB split cases, this batching fix can regress silently, and the required release note for the user-facing Cloudflare Queues failure is missing.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5fa3eb9a28

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +391 to +395
if (batch.length > 0 && exceedsBatchLimit) {
await flush();
}

batch.push(request);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject oversized Queue items before flushing

Fresh evidence: this version still only flushes when batch.length > 0 and then unconditionally pushes the current request, so a single wrapped activity over Cloudflare Queues' documented 128 KB per-item limit can be sent when it starts a batch or immediately after a prior flush (https://developers.cloudflare.com/queues/configuration/javascript-apis/). In the after-flush case, earlier batches have already been written before this deterministic rejection, so retrying the whole enqueueMany() call can duplicate those deliveries; preflight each message against the item limit before any flush/send.

Useful? React with 👍 / 👎.

@dahlia
dahlia merged commit 4c57bb7 into fedify-dev:2.0-maintenance Jul 19, 2026
16 of 17 checks passed
@dahlia dahlia self-assigned this Jul 19, 2026
@dahlia dahlia added the runtime/cfworkers Cloudflare Workers runtime related label Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

runtime/cfworkers Cloudflare Workers runtime related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cfworkers: WorkersMessageQueue.enqueueMany() exceeds Cloudflare Queues batch size limit

3 participants