feat(appkit-ui): share in-flight useAnalyticsQuery requests - #524
Draft
MarioCadenas wants to merge 1 commit into
Draft
feat(appkit-ui): share in-flight useAnalyticsQuery requests#524MarioCadenas wants to merge 1 commit into
MarioCadenas wants to merge 1 commit into
Conversation
Identical analytics requests (same query key, parameters, format, and dev mode) now share a single in-flight network request instead of one per hook instance. A module-singleton request store (mirroring the ResourceStatusStore idiom) owns the transport; useAnalyticsQuery becomes a useSyncExternalStore subscriber. Late subscribers read the current snapshot; the request is torn down a tick after the last subscriber unmounts, so a StrictMode unmount->remount reuses it rather than aborting. useChartData and all charts inherit the dedup for free. Dedup-only, no result cache. UseAnalyticsQueryResult is unchanged (non-breaking). Adds a /query-dedup playground route that counts analytics fetches in-page to make the behavior observable. Closes #496 Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Contributor
📦 Bundle size reportCompared against
|
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 855 KB | 298 KB |
| Type declarations | 314 KB | 108 KB |
| Source maps | 1.7 MB | 557 KB |
| Other | 11 KB | 3.7 KB |
| Total | 2.8 MB | 967 KB |
Per-entry composition (own code — deps external (as shipped))
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
. |
87 KB | 2.5 KB | 90 KB | external | 285 KB |
./beta |
48 KB | 459 B | 48 KB | external | 140 KB |
./type-generator |
20 KB | 0 B | 20 KB | external | 57 KB |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
. |
index.js |
initial | 83 KB |
. |
utils.js |
initial | 4.0 KB |
. |
remote-tunnel-manager.js |
lazy | 2.5 KB |
./beta |
beta.js |
initial | 32 KB |
./beta |
stream-manager.js |
initial | 5.8 KB |
./beta |
wide-event-emitter.js |
initial | 3.2 KB |
./beta |
databricks.js |
initial | 3.0 KB |
./beta |
configuration.js |
initial | 2.1 KB |
./beta |
service-context.js |
initial | 1.3 KB |
./beta |
client.js |
initial | 431 B |
./beta |
client-options.js |
initial | 220 B |
./beta |
supervisor-api.js |
lazy | 194 B |
./beta |
databricks.js |
lazy | 142 B |
./beta |
index.js |
lazy | 123 B |
./type-generator |
index.js |
initial | 20 KB |
@databricks/appkit-ui
npm tarball (packed): 314 KB (+5.2 KB) — gzipped download (dist + bin; excludes release-only docs/NOTICE).
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 366 KB (+3.9 KB) | 122 KB (+1.8 KB) |
| Type declarations | 209 KB (+341 B) | 76 KB (+152 B) |
| Source maps | 700 KB (+7.4 KB) | 230 KB (+3.2 KB) |
| CSS | 16 KB | 3.3 KB |
| Total | 1.3 MB (+12 KB) | 432 KB (+5.1 KB) |
Per-entry composition (consumer bundle — deps bundled, peerDeps external)
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
./js |
4.3 KB | 49 KB | 54 KB | 208 KB | 12 KB |
./js/beta |
20 B | 0 B | 20 B | 0 B | 0 B |
./react |
429 KB (+229 B) | 49 KB | 478 KB (+229 B) | 1.3 MB (+16 B) | 169 KB (+743 B) |
./react/beta |
1.0 KB | 0 B | 1.0 KB | 0 B | 1.9 KB |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
./js |
index.js |
initial | 4.2 KB |
./js |
chunk |
initial | 120 B |
./js |
apache-arrow |
lazy | 49 KB |
./js/beta |
beta.js |
initial | 20 B |
./react |
index.js |
initial | 427 KB |
./react |
tslib |
initial | 2.1 KB |
./react |
apache-arrow |
lazy | 49 KB |
./react/beta |
beta.js |
initial | 1.0 KB |
Contributor
🤖 AppKit PR bot🔬 Run evalsStart an eval for this PR from the evals-monitor app: Go to Evals Monitor → 📦 Try this PR's app templateScaffolds a new app from this PR's SDK build. Run it in any folder (requires the GitHub CLI — gh run download 31167158174 -R databricks/appkit -n appkit-template-0.55.1-pr.7e39751-in-flight-requests-524 -D appkit-pr-524 \
&& unzip -o "appkit-pr-524/appkit-template-0.55.1-pr.7e39751-in-flight-requests-524.zip" -d "appkit-pr-524" \
&& databricks apps init --template "appkit-pr-524"The template pins |
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 free
to 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.
What
useAnalyticsQuerydeduplicates identical in-flight requests. When multiple components call the hook with the same query key, parameters, format, and dev mode, they now share a single network request instead of each firing its own.Closes #496.
How
analytics-request-store.ts— a module-singleton request store mirroring the existingResourceStatusStoreidiom (keyedMap+ subscribe/notify + immutable snapshot viauseSyncExternalStore). It owns the transport lifecycle (SSE forJSON_ARRAY, direct Arrow fetch forARROW_STREAM) and fans both the final result and mid-flightwarehouse_statusupdates out to every subscriber.use-analytics-query.tsbecomes a thinuseSyncExternalStoresubscriber. Cache key =urlSuffix + serialized({parameters, format}). Warehouse-status mirroring intoResourceStatusProvidermoved from the transport into a hook effect.useChartDataand all charts route throughuseAnalyticsQuery, so they inherit dedup for free.UseAnalyticsQueryResultis unchanged — non-breaking.Showcase
New
/query-dedupplayground route (Data → "Query Dedup"). It wrapswindow.fetchwhile mounted to count analytics POSTs in-page, so you can watch "N components mounted → 1 network request fired" without the DevTools Network tab. Buttons mount more panels (count stays 1) and give the last panel a different key (count ticks to 2, proving distinct keys still fan out).Testing
appkit-uisuite: 371 passed / 18 files, including new dedup + store-lifecycle tests and the warehouse-status integration tests (both test files reset the singleton store between cases).appkit-uitypecheck: clean. dev-playground clienttsc --noEmit: clean.biome checkandknip: clean.Not yet run end-to-end against a live warehouse (no creds in this environment); the dedup counter is exercised by the request-store tests regardless of query success.