Repository navigation
App: the Executive summary opens with 8 queries rather than 18 (cut 1, the landing diet) - #155
Merged
Keith McGrane (Keithland89) merged 1 commit intoOct 21, 2026
Conversation
Keith McGrane (Keithland89)
force-pushed
the
keithmcgrane-microsoft-cut-1-landing-diet
branch
2 times, most recently
from
October 20, 2026 21:52
f1caa46 to
004d98d
Compare
…, the landing diet) Cut 1 of the 20k cut list. The landing now sends 8 foreground queries at open, the hours range's among them, or 9 with org-scoped access, so its own queries wait behind fewer others in the app's four-slot queue. - Load status and the org columns load in a background lane; the org columns move on screen when a filter menu other than the dates opens or a breakdown by org mounts. - The org values and Consumption Central's org attributes load when such a menu first opens (and the attributes once an org filter is set). The org menu lists values only once the org columns have settled the column. - One probe checks the optional sources; each is asked on its own if it fails for any reason but a busy model. - The two credits queries become one; they still wait for the dates. - The trend starts with the first queries when no date filter is set, and, like the summary and its hours range, at the model's own task times. - `__me` is asked only when the app's config says org-scoped access is on. On Azure, /app.config.json now passes rlsOrgAttribute on, as the installer meant. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keith McGrane (Keithland89)
force-pushed
the
keithmcgrane-microsoft-cut-1-landing-diet
branch
from
October 21, 2026 06:20
004d98d to
695b727
Compare
This was referenced Oct 21, 2026
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.
For 0.6.8 if it's ready in time, else 0.6.9. Keith decides the merge.
Summary
Cut 1 of the 20k cut list, the landing diet. The Executive summary now opens with 8 foreground queries rather than 18, or 9 with org-scoped access. Both counts include the summary's hours range, which #154 (cut 2) asks on its own. The app runs at most four queries at a time, so the page's own queries wait behind fewer others. Nothing on the first view changes. What users lose: the org menu's first open waits about a second for its values, or up to about three seconds if it opens before the org columns have loaded in the background (deviation 2).
These are the cut list's figures, from 0.6.8-rc.1 (465de3b) on an F64 trial with 20,000 people, as it marks them: (m) measured with the executeQueries API, est. estimated from its model of the app's 4-slot query queue. None were re-measured for this PR, which made no Power BI calls.
The landing's queries, numbered as in the cut list, with Consumption Central and every optional module installed, as on the trial:
__me: whose data the viewer seesSo these go on screen at open: c00, c02, the probe, the trend, c13, the credits, c16 and its hours range, plus
__mewith org-scoped access. c01 and then c11 load in the background. A copy of the new whole-app test, run against main (fd6a42d), counts 18 on screen and none in the background, with org-scoped access off or on: main asks__meeither way. Before #154 (3b843e3), it counted 17.What changed:
useSemanticModelQuerytakesbackground, which asks in the scheduler's low-priority lane, as the Prefetcher's queries do.useLoadStatus).__meonly with org-scoped access.useAccessScopeasksACCESS_SCOPE_QUERYonly when the app's config namesaccess.rlsOrgAttribute.publicAccessininstaller/src/steps/access.js), for both hosts. On Fabric, it offers to redeploy the app when access changes./app.config.jsondropped it: its ownpublicAccess(azure/web/src/server.js) passed on only the group and who to ask. It now passesrlsOrgAttributetoo, so__meis still asked there.offat once. Main readofffrom the model's missingAccess Scopetable.mergedSourceProbecounts every source in oneROW, one column per source, with the five probes' own expressions (SOURCE_COUNTS). It covers only the sources whose module wasn't left off.readMergedSourceStatereads each column as each probe's row was read: a count above 0 is present, else missing.useSourceProbes:FilterMenucallsonOpenas its popover opens.FilterBarpassesrequestFilterChoicesasonOpenfrom the org, agent type, agent name and Group by menus. The dates' menu doesn't call it: its presets and fields come with the filter options.FilterProviderthen asks for the org values (c06) and Consumption Central's org attributes (c05).lib/filter-profiles.ts:219reads it only to rule out an attribute Consumption Central lacks.useOrgAttribute(true), except on a page fetched ahead.FilterProviderasks for the org values (c06) only once c11 has answered or failed.useSpeculativeQuery, beside c11. The column seldom changes, so the real ask then joins that query or reads its answer, and c06 is sent once. If it does change, that answer is wasted.executiveRecentMonths(): the same months query, held to the six months to the last day of activity.CALCULATE(MAX('Chat + Agent Interactions (Audit Logs)'[ActivityDate]), REMOVEFILTERS()). That's the last date the filter options give the page.leadandspeculate, like the summary and its hours range. With a date filter, it still waits for the dates.executiveCreditPartsasks the credits query twice in aUNION: once for the trend's months and once for the date range.reportingDateFilter), and tagged with a"Part"column.useConsumptionTableParts, onuseTablePartsQueryandsplitQueryParts, splits the answer back into the two tables the page read before.wrapEvaluateBodieswraps eachEVALUATEbody, leavingDEFINEandORDER BYin place;applyDaxFiltersnow uses it.evaluateBodyreturns the first body.docs/ARCHITECTURE.mdgains "How the app opens", andapp/README.mda bullet on it.azure/web/README.mdsays what/app.config.json'saccesscarries. CHANGELOG.md: an entry at the end of## Unreleased.Deviations from the cut list
Keith accepted both.
1. The credits still wait for the filter options (c02). The cut list starts the trend and the credits with the first query. The trend does, but the credits can't, because both their windows come from c02's first and last dates:
useExecutiveRange).The credits are asked of Consumption Central, which can't read the ValueLens audit log's dates, so they can't find their own window as the trend does. Starting them early would mean asking at guessed dates and again when those differ, or showing credits for other dates.
Cost (est., from the cut list's queue model):
2. The org columns (c11) load in the background, not when a menu opens. The cut list defers c11 to the filter menu, since "They only fill that menu". But c11 also picks the org column app-wide:
useOrgAttributegives the org filter its name, and every breakdown by org its grouping;Organizationcolumn is empty, it falls back to the first column worth grouping by.So c11 now loads in the background at open. It moves on screen, still sent once, when a filter menu other than the dates opens or a breakdown by org mounts.
Because c11 picks the column, the org menu lists values only once c11 has answered (see "What changed"). So the org menu, first opened before c11 has loaded, waits for c11 as well as its values (c06): up to about 3 s, as c11 took 3.01 s in #118's waterfall (m). On main (fd6a42d), with no task times saved, c11 loads in the background from about 3.3–3.6 s to 6.35–6.60 s after the first query (est.), or from 3.7–3.9 s to 6.7–6.9 s before #154. Opened after that, the menu waits about 1 s, the cut list's figure. Opened while the landing's own queries still run, it also waits for a slot, as c06 did on main. The alternative is to list the values of the column in use at once, and clear any ticked if c11 then changes the column. The column seldom changes, but a ticked value could then vanish.
No breakdown on the landing groups by org: the Executive summary's two by-org stages, "Where it is landing" and "What needs attention", aren't on its first tab. So the landing stays at 8 queries, or 9 with org-scoped access.
Group by lists c11's columns, and shows once they've loaded and there's more than one. When it appears, in seconds from the first query (est.):
Under the cut list's plan, Group by wouldn't show until another menu opened, and then about 3 s later: c11 took 3.01 s (m) in #118's waterfall. Here, opening any other menu first moves c11 on screen.
It also delays the Prefetcher, which waits until nothing at all is loading (see the notes below).
Saved task times
The trend is asked with
speculate: true, as the summary is: from the first query at the model's own task times, then again at the saved times if they differ. The early answer is never shown.speculate's doc comment inuse-filtered-query.tsis unchanged. #154 reworded it to a rule the trend fits: "Only for queries a page's first view waits on, where an early answer is worth a wasted one when times are saved."Since #154, three landing queries speculate: the summary, its hours range and the trend. Landing's queries and C, in seconds from the first query (est.). The model has the summary at 2.87–3.10 s, and saved task times known at 1.2 s:
cl_sim.py), with each change here added: durations from App: the Executive summary opens sooner #118's waterfall, the probe at 0.70 s (m), the credits at 0.60 s (est.), and App: ask the hours range on its own, so the Executive summary's figures don't wait for it #154's split from its pair medians (m).Other notes and limitations
IDLE_MS). It now also waits for c01 and then c11 in the background lane. So it starts at 7.85–8.10 s rather than main's 6.12–6.26 s (est.), or, before App: ask the hours range on its own, so the Executive summary's figures don't wait for it #154, at 8.16–8.39 s rather than 6.02 s. Under the cut list's plan, with only c01 in the background, it would have started at 5.12–5.35 s before App: ask the hours range on its own, so the Executive summary's figures don't wait for it #154 (est.). What it fetches is unchanged, but each page is fetched about 2 s later, so one opened in that time loads on screen rather than from what was fetched ahead.Organizationcolumn is empty: the org filter takes the name of the column it falls back to once c11 loads, which is now later.__me. The header wouldn't say whose data shows, and a viewer with no scope would see empty pages rather than the no-scope notice. The model's row-level security still filters every query, so no one sees more.share-panel.tsxshows it on Azure only when the app's config namesrlsOrgAttribute, which/app.config.jsondropped until this PR. The web host has served it all along, on the same condition (DelegationService.enabled), and the release notes say it ships ("scoped delegation from the Share panel (Azure)"). The panel asks/api/delegationsand shows nothing unless the host says it's on.Scope
Parts affected (installer / app / Fabric notebooks and pipeline / Azure infra, jobs or web / core / Power BI models):
The app: the filter bar, menus and provider, the source probes, the access scope, load status, the semantic model query hook, and the Executive page's data hook and queries. And the Azure web host's
/app.config.json, which now passes onaccess.rlsOrgAttribute.app/src/lib/runtime-config.tspicks the host), so both get it. The Azure web image's next build carries it, with the config change.Source contracts, optional inputs, install record or deployed item names changed:
None. The app reads
access.rlsOrgAttributefrom its config, which the installer already writes for both hosts. On Azure,/app.config.jsonnow passes it on rather than dropping it.Validation
python -B -m pytest tests -qand recorded results below.npm test(andnpm run typecheckfor the installer) in each changed Node project..pbitfiles changed, documented the rebuild method and Desktop refresh / visual checks.Results, skipped checks and limitations:
The branch is rebased onto main 087209b, which has #148, #151, #152, #153, #154 and #158.
use-executive-data.tsandexecutive-lead-queries.spec.tsx. Both cuts' behaviour is kept: the page asks the summary, then its hours range, then the trend, and App: ask the hours range on its own, so the Executive summary's figures don't wait for it #154's lead-queries tests now have the trend third. The landing's counts here, in the docs and in the CHANGELOG are now 8, or 9 with org-scoped access, as the whole-app test counts./app.config.json, without conflict. Neither it nor Azure: fit 20,000 seats in the run job, and carry an unfinished reload over #148, App: Leaderboards' share card shows the top 1%, 5% and 25% without the curve #151 or Power BI model and app: sync ValueLens #202 and #203, and split the Adoption summary (0.6.8 cut 3) #153 changes what the landing asks: they changed comments only in the Executive summary's DAX andqueries/shared.ts, and the rest is on other pages or in the host.CHANGELOG.md. This PR's entry is the last under## Unreleased, after Azure web: reuse each user's Power BI and Graph tokens, and compress responses (0.6.8 cut 5) #152's.CHANGELOG.md: this PR's entry is last under## Unreleased, after App: on Azure, a ranked chart whose query has no rows shows its empty state, not the error screen #158's. App: on Azure, a ranked chart whose query has no rows shows its empty state, not the error screen #158's stages render without aFilterProvider. The filter context's new fields are optional, so those stages behave as before.On the original head, before the replay,
004d98d3539846c3a3b3c1dade318452c17b2156, treef1e8761d7e89159fa514ad8a494b02211c1d3fea, on Windows with Node 24.19.0, npm 11.17.0 and Python 3.12.10:app/, afternpx --no-install fabric-app-data generate -o src/fabric.generated.ts:npm test: 155 test files, 3624 tests, all passed. A first run, under load from other work on the machine, timed out one test this PR doesn't touch (report-export.spec.ts, building a PowerPoint file, at its 5 s limit). It passed alone and in the full rerun.npm run lint: 0 errors, and 2 warnings that main has too (react-refresh/only-export-componentsinvega-visual.tsxandroot.tsx, which this PR doesn't touch).npx --no-install tsc -b: passed.npm run build:fabric: passed.azure/web/,npm test: 81 passed.python -u -B -m pytest tests -q -ra -p no:cacheprovider: 1222 passed, 5 skipped and 12176 subtests passed. The five skips need Spark and Java, which aren't installed here. CI'spytestjob passed on this head too.tests(pytest, app, installer, valuelens-web and arm-drift),azure-images(Build valuelens-web and Build valuelens-jobs),CodeQL(actions, javascript-typescript and python) and license/cla. Code scanning's summary check is neutral, "1 configuration not found", as on the previous head.New and changed tests:
landing-queries.spec.tsx(new): the whole app on the real SDK and scheduler, with both models and the Prefetcher left out. The landing's queries:filter-provider.spec.tsx(new), 8 tests:filter-bar.spec.tsx(new):optional-sources.spec.tsanduse-source-probes.spec.tsx:executive-queries.spec.ts:query-parts.spec.ts(new, 5) anduse-table-query.spec.tsx(new, 3): each part reads as its own query did, a part with no rows is an empty table, and the parts load and fail together.executive-lead-queries.spec.tsx, on App: ask the hours range on its own, so the Executive summary's figures don't wait for it #154's tests for the hours range:speculate: true: it asks the trend at the model's own task times while the app's are still loading;use-semantic-model-query.sdk.spec.tsx, the background lane: it waits while a query on screen loads; it moves on screen, sent once; a query already sent is read, not sent again; and a page fetched ahead stays in the background.dax-filters.spec.ts:wrapEvaluateBodiesandevaluateBody.use-load-status.spec.tsx: load status asks in the background lane.azure/web/test/access.test.js: the app config says when org-scoped access is on, with the org attribute it filters on.Compatibility
Repair or change: nothing to migrate. The app ships whole.
.daxfile changes. The existing months and credits queries are unchanged; the trend's and the credits' new queries wrap them.