From fab956759dd91f555fd6735fbb4017a24874cc1f Mon Sep 17 00:00:00 2001 From: Jack Zhuang Date: Sat, 22 Aug 2026 09:30:54 +0800 Subject: [PATCH 1/2] perf(console): share one in-flight GET instead of racing duplicates on boot Fixes objectstack-ai/objectui#5544 Co-Authored-By: Claude Opus 5 --- .changeset/console-boot-request-dedup-5544.md | 42 ++++ apps/console/index.html | 60 ++++- .../console/src/LocalizationFetchProvider.tsx | 14 +- .../__tests__/localizationBootDedup.test.tsx | 139 +++++++++++ .../__tests__/runtimeConfigBootDedup.test.ts | 158 +++++++++++++ apps/console/src/languageSeed.ts | 18 +- packages/app-shell/src/runtime-config.ts | 23 +- .../types/src/__tests__/http-inflight.test.ts | 217 ++++++++++++++++++ packages/types/src/http-inflight.ts | 202 ++++++++++++++++ packages/types/src/index.ts | 12 + 10 files changed, 858 insertions(+), 27 deletions(-) create mode 100644 .changeset/console-boot-request-dedup-5544.md create mode 100644 apps/console/src/__tests__/localizationBootDedup.test.tsx create mode 100644 apps/console/src/__tests__/runtimeConfigBootDedup.test.ts create mode 100644 packages/types/src/__tests__/http-inflight.test.ts create mode 100644 packages/types/src/http-inflight.ts diff --git a/.changeset/console-boot-request-dedup-5544.md b/.changeset/console-boot-request-dedup-5544.md new file mode 100644 index 0000000000..e9de03abb1 --- /dev/null +++ b/.changeset/console-boot-request-dedup-5544.md @@ -0,0 +1,42 @@ +--- +'@object-ui/types': patch +'@object-ui/app-shell': patch +--- + +The console's cold load no longer asks `/api/v1/runtime/config` or +`/auth/me/localization` twice (objectui#5544). + +Two pairs of boot callers were racing each other for the same URL, with no shared +provider between them, so no guard inside either component could see the other: + +- `GET /api/v1/runtime/config` — the pre-React branding script inlined in + `apps/console/index.html` (it runs during HTML parse so the tab title and + favicon are the operator's before the bundle is fetched) and + `initRuntimeConfig()`. Measured ×2 on prod and on staging. This is the + expensive one: the console `await`s `initRuntimeConfig()` before + `createRoot().render()`, so the duplicate sat on the critical path to first + paint, and at the control plane's ~0.5–1.4 s for this endpoint it also pushed + boot concurrency further past the server's pool knee. +- `GET /api/v1/auth/me/localization` — `seedTenantLanguage()` on a device's true + first visit and `LocalizationFetchProvider` on every boot. The seed keeps + running past its 500 ms race by design and the provider mounts the moment that + race resolves, so on a first visit the two overlap. Measured ×2 on staging. + +`@object-ui/types` gains `sharedGetJson()`: callers that ask for the same GET +while one is already in flight join that request instead of starting another. It +shares the in-flight promise and nothing else — the entry is deleted the instant +the request settles, so there is no cache, no TTL and no stale window, and a +caller arriving after settle fetches fresh exactly as before. Rejections fan out +to every sharer with the status intact (`LocalizationFetchProvider`'s retry +policy still sees its own 503), each caller receives its own copy of the parsed +body, and only GETs are eligible — a non-GET is refused rather than quietly +rewritten. + +Requests that differ in credentials mode or headers keep separate identities, so +the console's two deliberate `auth/get-session` calls — one Bearer-only with the +cookie omitted to detect a stale token, then one through the cookie — stay two +requests. Collapsing those would have destroyed the signal the first one exists +to read. + +No component receives anything different: same payloads, same errors, one fewer +round trip. diff --git a/apps/console/index.html b/apps/console/index.html index 4337b6796a..35b8de9058 100644 --- a/apps/console/index.html +++ b/apps/console/index.html @@ -15,19 +15,59 @@ +