Skip to content

Bound storefront config polling while unbound or connecting - #1518

Open
sbolinger-godaddy wants to merge 5 commits into
mainfrom
fix/storefront-bounded-config-polling
Open

sbolinger-godaddy wants to merge 5 commits into
mainfrom
fix/storefront-bounded-config-polling

Conversation

@sbolinger-godaddy

@sbolinger-godaddy sbolinger-godaddy commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

CommerceProvider polled GET /api/commerce/config every 5 seconds whenever the last response was unbound or connecting. Failed refreshes kept the last unbound data, so they didn't stop the interval either. In production, every open tab of a site with no store kept polling indefinitely.

Why this approach

A user may select a template that has no store bound. They may never connect a store, or they may connect one minutes, hours or days later. So the goal isn't to wait until a store connects. It's to make sure we never poll indefinitely in production.

To do that, polling ends on a fixed schedule, and a page refresh starts it again. Polling is frequent right after a refresh, when the user is most likely to be connecting a store, then backs off over 30 minutes. A request cap or a more complex backoff was not needed, so the schedule is deliberately simple.

Change

refetchInterval is now timed from when the provider mounts, which is when the page loads:

  • 0–5 min: every 5 s
  • 5–30 min: every 60 s
  • after 30 min: stop

Reloading the page starts polling again. Focus and retryConnection() still refresh once. These are unchanged: samples, the connecting failure grace, stale data never granting readiness, and no polling in background tabs. Failures don't extend the window.

A page still connecting when polling stops shows the connection error with "Retry connection" instead of "Connecting to the store…" indefinitely. Only a host's readConnectionState() can report connecting, so catalog API outages can't cause this.

Tests

  • Polling backs off after 5 minutes and stops at 30, including after failed refreshes, with no requests over the next day.
  • A store connected while backed off (20 minutes in) is picked up.
  • A remount after polling stops starts polling again.
  • A page still connecting at 30 minutes offers a retry, and retrying picks up ready.

The stopping test fails against the previous refetchInterval (expected 121 to be 66). The other two pass on both versions, as expected. lint, typecheck, build and all 127 package tests pass.

🤖 Generated with Claude Code

A site with no connected store reports `unbound` until it is republished,
so every visible tab requested /config every five seconds indefinitely,
and failed refreshes kept the interval running. Poll every five seconds
for two minutes, then every 30 seconds, and stop after fifteen minutes.
`connecting` should end soon, so it polls fast for five minutes and stops
after 30. Each limit counts from when the page first saw that state.
Mount and visibility refetches still recover, and visibility starts a new
polling period.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 35c1cde

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

This PR includes changesets to release 1 package
Name Type
@godaddy/gd-commerce-storefront Minor

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

@sbolinger-godaddy
sbolinger-godaddy requested a review from a team as a code owner October 23, 2026 17:31
sbolinger-godaddy and others added 2 commits October 23, 2026 10:39
Stop polling after a fixed number of /config results, failures included,
counted by React Query: 180 (about fifteen minutes) unbound and 360
(about thirty) connecting. This bounds polling with a much smaller change
than the backoff schedule and visibility tracking it replaces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A site can stay unbound for days, so a request cap or focus-based restart
does not fit. Time polling from page load instead: every five seconds for
five minutes, then every minute, and stop at thirty minutes. Reloading the
page starts it again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@wcole1-godaddy wcole1-godaddy 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.

Reviewed the polling implementation, surrounding connection handling, documentation, and regression tests. No blocking findings. The mount-relative deadline bounds repeated configuration requests even when refreshes fail, without resetting the budget on retry/focus or changing readiness eligibility. The tradeoff that a store connected after the window needs a focus refresh, explicit retry, or remount/reload is intentional and reasonable for this fix.

Validated locally at 4e2d798: package build, all 126 tests, typecheck, and lint pass.

Optional follow-ups: (1) describe timing as relative to provider mount rather than page load, since an SPA can mount/remount it without a reload; (2) strengthen the polling test with an expected request count at the 30-minute boundary (the existing long-idle assertion proves it stops by then, not that it continues until then), plus connecting-state and post-cutoff focus/retry cases. These are non-blocking.

sbolinger-godaddy and others added 2 commits October 23, 2026 10:53
A page still connecting at thirty minutes shows the connecting message
until focus or reload. Once polls are a minute apart, the 60-second
connecting grace has already passed at the next failure, so the error
shows at once. Rewrap the edited paragraphs to the surrounding width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Once polling stops, nothing refreshes a page that is still connecting, so
it showed "Connecting to the store…" with no way forward. Report it as a
connection error with "Retry connection".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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