Uh oh!
There was an error while loading. Please reload this page.
test(app-shell): pin the console sys_user_preference request budget per mount - #5593
Merged
Merged
Conversation
…er mount objectui#5544 reported `/api/v1/data/sys_user_preference` ×3 on prod and ×6 on staging in one cold load, grouped by URL pathname. Grouping by pathname is the trap: `ConsoleShell`'s `UserStateBridge` attaches three adapters — `ui.favorites`, `ui.recent`, `ui.flow.palette.recents` — which are three distinct rows that differ only in the `key` predicate riding in the query string. Three reads is the correct budget, not a duplicate. The card proposes dedup at the request layer. That already exists: `ObjectStackAdapter.find()` coalesces on `resource + serialized params`. The hazard is a future fix widening that key to the ENDPOINT, which would collapse the three reads into one, starve two of the three consumers, and still look perfect to a pathname-level count. So this pins both directions across one mount: exactly one read per distinct preference key, and every consumer still receives its own row. Tests only — no runtime code changes. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012u2pRjcqAYtoEjgr3wwhnK
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-sales
marked this pull request as ready for review
August 21, 2026 16:38
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #5544
What was measured, before any fix was chosen
The card's prod/staging numbers are the card's measurement, taken in a browser against a deployed build. They are not reproduced here and are not claimed as mine. Everything below was measured against
origin/main(cad512fe1) with a stubbed transport.Caller census —
sys_user_preferenceConsoleShell'sUserStateBridgecreates three adapters on a console boot, one per slot:keyui.favoritesFavoritesProviderui.recentRecentItemsProviderui.flow.palette.recentsFlowPaletteRecentsProvidercreateObjectStackUserStateAdapterbinds one adapter to one(user, key)pair, andload()issuesfind('sys_user_preference', { $filter: { user_id, key }, $top: 1 }). Three different rows, differing only in thekeypredicate — which rides in the query string.The classification
The card's reproduce snippet groups by
new URL(r.name).pathname, which discards the query string. So three distinct KV reads collapse into one pathname and read as "×3 duplicates". The prod ×3 is the expected budget, not a defect.Measured on
main, one mount: 3 calls, 3 distinct keys, zero repeats. Under a StrictMode double-mount: still 3 —ObjectStackAdapter.find()already coalesces in-flight reads onresource + serialized params, so the second wave never reaches the transport.The other endpoints on the card
meta/object×2 /meta/view×2 — already fixed onmainunder objectui#4042 (MetadataProvider's preview-mode effect skips its mount run) and already pinned byMetadataProvider.requestBudget.test.tsx, which is green. Nothing left to do here.auth/get-session×2 — two call sites by design:preflightAuthprobes with the Bearer only (credentials: 'omit') to detect a stale token, thenAuthProviderasks who the user is. Deduping them would break stale-Bearer detection. Not a duplicate to remove.runtime/config×2 /auth/me/localization×2 — one boot call site each in this repo (initRuntimeConfig,languageSeed) plus the React provider for localization. The measured host is a cloud deployment, so a secondruntime/configcaller is not visible from this repo.MetadataProvider key={language}remount would, but the language is deliberately committed before React mounts and never flips late (languageSeed.tsdocuments exactly this). Not reproducible from this repo'smain.Why this PR ships a test and no source change
There is no measured duplicate on
mainto remove. The narrowest useful change is therefore a regression pin — and it guards against a specific, live hazard: the remedy the card proposes.The card suggests "dedup at the request layer (in-flight requests sharing a Promise per key)". Read as endpoint-level dedup, that collapses the three distinct reads into one and starves two of the three consumers — while making a pathname-level count look perfect. So the test pins both directions together:
Reverse-verification (ablation)
Mutated
ObjectStackAdapter.find()'s coalescing key fromresource + paramstoresourcealone — the card's proposed remedy read literally.1 -> 0, mutant anchor0 -> 1,git diff --stat=1 file changed, 1 insertion(+), 1 deletion(-)vitest.config.mtsaliases@object-ui/data-objectstacktopackages/data-objectstack/src, so the test loads the mutated source directlyexpected [] to have a length of 1 but got +0forui.recentandui.flow.palette.recents— three reads collapsed to one. Consumer test:expected [] to deeply equal [ 'object:contact' ]— consumers starved. The identical-reads case stayed green, correctly.trap ... EXIT INT TERM;git status --porcelainempty, original anchor back at count 1, all 3 green again.Gates — all at
a615125e5, exit codes captured before any pipevitest(new file)Tests 3 passed (3)vitestconsole + context + providersTest Files 73 passed (73)/Tests 516 passed (516)vitestpackages/data-objectstack/Test Files 41 passed (41)/Tests 558 passed (558)@object-ui/app-shelltype-check^...closure@object-ui/app-shelllint2510 problems (0 errors, 2510 warnings)— all pre-existing; eslint on the new file alone emits nothingcheck-control-bytescheck-control-bytes: OK (scanned 4647 tracked text file(s); skipped 85 binary).check-changeset-presencecheck-changeset-no-majorNo changeset declares a major bump.check-changeset-fixedAll workspace packages are in the changeset fixed group.Declared narrowing: the full
packages/app-shell/suite (482 test files) exceeds this container's foreground limit, so it was run asconsole/+context/+providers/— the directories this test imports from. This cannot hide a failure: the diff is 2 files, 0 runtime source (one new test, one changeset), so no existing test's subject changed; and thedomproject runsisolate: true, so a new file cannot leak module state into another. CI runs the whole farm regardless.Residual items for triage (not addressed here)
meta×2 is already gone and the card's remaining numbers should be re-taken.main; it likely needs a measurement from the cloud deployment (cloud#1521).runtime/config×2 may have a second caller in the cloud repo, outside this repo's reach.Generated by Claude Code