Skip to content

Reduce redundant inbox network requests#169

Open
mikemilla wants to merge 2 commits intomainfrom
perf/batch-open-requests
Open

Reduce redundant inbox network requests#169
mikemilla wants to merge 2 commits intomainfrom
perf/batch-open-requests

Conversation

@mikemilla
Copy link
Copy Markdown
Collaborator

@mikemilla mikemilla commented Apr 8, 2026

Summary

  • Batch open requests: Add InboxClient.batchOpen(messageIds) that combines multiple opened() mutations into a single aliased GraphQL request. Replace the per-message server call in CourierInboxDatastore.openMessage with a debounced batch queue (100ms window) — optimistic UI updates remain immediate. No existing public APIs change.
  • Eliminate duplicate inbox loads on mount: Pass feeds as an HTML attribute on <courier-inbox> and <courier-inbox-popup-menu> so the web component has the correct feeds before initializeInboxData runs. This removes the redundant setFeeds()refresh() cycle from the React wrapper's useEffect, cutting inbox requests on mount from 4 to 2 per component.

Changes

Batch open (courier-js, courier-ui-inbox)

  • New InboxClient.batchOpen(messageIds) method — single aliased GraphQL mutation
  • CourierInboxDatastore.openMessage now queues opens and flushes via a 100ms debounced batch
  • Already-opened messages short-circuit without scheduling a server call

Feeds as attribute (courier-ui-inbox, courier-react-components)

  • CourierInbox: added feeds to observedAttributes; attributeChangedCallback stores feeds before init or calls setFeeds after init
  • CourierInboxPopupMenu: same treatment — stores feeds from attribute before creating the inner CourierInbox, passes them before DOM append
  • CourierInboxComponent (React): passes feeds as a memoized JSON attribute, removed setFeeds useEffect
  • CourierInboxPopupMenuComponent (React): same changes

Test plan

  • All existing datastore tests pass
  • New test: single open flushes after the batch window with batchOpen([id])
  • New test: multiple opens within the window produce a single batchOpen call
  • New test: opens arriving after a flush produce separate batchOpen calls
  • New test: error during flush notifies error listeners
  • Existing test: already-opened messages short-circuit without scheduling a server call
  • Integration test for InboxClient.batchOpen added
  • Verified designer inbox tab loads with 2 requests instead of 4
  • Verified designer popup menu tab loads with 2 requests instead of 4
  • Verified dynamic feed changes via React props still trigger setFeedsrefresh correctly
  • No TypeScript or linter errors

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
courier-web-designer Ready Ready Preview, Comment Apr 10, 2026 1:36am

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 8, 2026

🦋 Changeset detected

Latest commit: 30d858b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@trycourier/courier-js Patch
@trycourier/courier-ui-inbox Patch
@trycourier/courier-react-components Patch
@trycourier/courier-ui-toast Patch
@trycourier/courier-react Patch
@trycourier/courier-react-17 Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

* Add batch size limit of 50 to open requests

Introduces OPEN_BATCH_MAX_SIZE = 50 to cap the number of message IDs
sent in a single batchOpen GraphQL mutation. When more than 50 messages
are queued, flushBatchOpen splits them into chunks and sends them as
parallel requests via Promise.all.

This prevents oversized GraphQL payloads from hitting server-side limits
when many messages become visible at once (e.g. rapid scrolling).

Co-authored-by: Mike Miller <mike@mikemiller.design>

* Add boundary test for batch size just over the limit (51)

Adds a test verifying 51 messages produce 2 chunks (50 + 1), and an
explicit assertion that no single batchOpen call ever exceeds 50 IDs.

Co-authored-by: Mike Miller <mike@mikemiller.design>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant