Repository navigation
perf(app-shell): Home's navigation roster gate asks its required objects in one ?names= request - #30864
Merged
Conversation
The Home roster refresh case reassigned an outer variable during render, which the React compiler lint rule refuses (Lint UI). The handle is now filled from an effect on a holder object passed as a prop. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibvowqEy7Lkj2dKGw2i
Contributor
Author
|
domain:ui#2 · os-tesla · session_01L9qibw7DekEe3wx5f3zphf 席位核对 · ACCEPT · 2026-11-06T07:45Z · head
|
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.
Requested by Tesla · project thread
Fixes #29444
Clause-②: no
Metadata-protocol: none
维护者速读
requiresObject对象名合成一次GET /meta/object?names=a,b,c读取,不再每个对象名发一次请求。?names=批量读(Metadata API: no batch by-names read, so the Console roster gate costs one /meta/object request per name #29236 裁决 A,PR feat(rest)!: serve ?names= on the /meta/:type list and close its query set #30709)已上线,实测改后只剩 1 个。ui/packages/app-shell/src/providers/MetadataProvider.tsx的fetchScopeNames(缺名、失败、刷新三种情形);ui/packages/app-shell/src/hooks/useNavMemberGates.ts里outsideApp那一处分支;ui/packages/app-shell/src/console/home/__tests__/homeObjectReads-29121.test.tsx。pnpm --dir ui exec vitest run packages/app-shell/src/console/home/__tests__/homeObjectReads-29121.test.tsx,预期 7 个用例全绿,其中门禁用例只记到一条object?names=sys_cloud_only,sys_queue请求。382ce259的 diff 复核:5 个文件、+221 / −26,只在 app 外(首页)把路由门要的对象并成一次GET /meta/object?names=读;缺名照旧算未注册(同按名 404),整次读失败则每个名都算未答(同按名读失败),刷新再并读一次,预览与 app 内仍按名读,路由读者不会拿列表回答当自己的。MetadataContextValue类型未改(钩子内本地类型转交batch),无新导出,Clause-② no 成立,不欠契约复审;382ce259 只改测试以过 Lint UI。CI 全绿,同意落地。What changes
useNavMemberGatesreads the app list'srequiresObjectunion through the names-only scope. Outside an app (a frame whose app has noname: Home, or a frame with no expression scope), it now passes a package-localbatch: truehand-off besideviews: false. Inside an app nothing changes: the union is still read by name, because the route's own objects are among those names and their by-name read is shared with the adapter'sgetObjectSchemacache (objectui#13044).MetadataProvider.readObjectScopekeys a batched read underNAMES_BATCH_SCOPE, a symbol, so no package id can collide with it. It never shares the names-only entry: a list answer carries no by-name envelope and cannot tell an absent object from a refused one (OBJECT_PACKAGE_DISABLED), so a route reader never takes it for its own. The names not asked yet go out in onemeta.getItems('object', { names })(the client door PR feat(rest)!: serve ?names= on the /meta/:type list and close its query set #30709 added; no new URL builder).ingestObjectList).404was (ruling A on Metadata API: no batch by-names read, so the Console roster gate costs one /meta/object request per name #29236, 6580261740: an unknown name is simply absent).invalidate,refreshor an organization switch.refreshasks the batched names again in one request.MetadataClient.listhas no names filter, the hand-off falls back to the names-only scope (by name).mainb618224). The list door runs?names=after the per-caller list gate (whoseobjectarm is the by-name read'sfilterObjectListViewsForUser) and before the ADR-0106 mask and translation. The store read drops a disabled package's objects, where the by-name read refuses them404 OBJECT_PACKAGE_DISABLED. The gate reads both answers as "not registered". The answer is the{ type, items: [...] }array envelope, whichextractItemsalready reads.@object-ui/app-shell. The hand-off typeReadNamesInOneRequestis local touseNavMemberGates.ts.Tests
homeObjectReads-29121.test.tsx(realMetadataProvider+ real gate, fake adapter):object?names=sys_cloud_only,sys_queuerequest. The absentsys_cloud_onlyis hidden andsys_queueis shown. This replaces the two by-name reads the case pinned before.refresh('object')re-asks the names in one request.navGateUnionScope-12980.test.tsx: the outside-app case asserts the single?names=request for the five-name union. Its fake adapter now honoursnamesthe way the door does: it keeps those items, and an unknown name is absent. The package-less-app cases (inside an app, by name) are unchanged and green.scripts/ablation-replace.mjs, which confirmed the mutation landed and the restore matched the HEAD blob:outsideApp = false): 2 cases red;Related suite (347 files that import the provider or the gate)
pnpm --dir ui exec vitest run --maxWorkers=2over every app-shell / console test that namesreadObjectScope,useNavMemberGatesorMetadataProvider, before the union-scope pin below was updated. 345 files passed and 2 failed:navGateUnionScope-12980(outside-app case): its fake adapter ignorednames. Updated above, and the file is now 12/12 with the Home file.spec-symbol-parity.test.ts: 16 cases failed because the probe reads@objectstack/spec's.d.tsfiles, and that run's build usedOS_SKIP_DTS=1(SPEC_NAMES.size0). After a declarations build, the file is green together with the two gate files: 3 files, 53 tests.Verification
Live, on app-crm. Backend
objectstack dev --seed-admin --fresh -p 4417inexamples/app-crm. Consolevite --port 5197 --strictPortwithDEV_PROXY_TARGETpointed at it. Headless Chromium signed in as the seeded admin, then loaded/homefresh, counting every request whose path starts with/api/v1/meta/object.origin/main(the two source files restored from b618224)GET /meta/object/NAMEforsys_assignment_rule,sys_business_unit,sys_notification,sys_notification_preference,sys_notification_template,sys_queue,sys_queue_member,sys_record_share,sys_sharing_rulesys_activity, the activity feed's presence check)GET /meta/object?names=with the same nine names, 200, 9 itemssys_activity, unchanged)The card counted 8 names on app-crm. The app list now carries 9.
Gates
At head
c2ce30e3.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 36 families from this diff; each ran with stdin closed, and the exit code was captured before any pipe.--ranreconciliation: 36 derived, 36 run, 0 NOT-MEASURED, 0 UNRUN.pnpm --filter @object-ui/app-shell type-check(bothtsc --noEmitandtsconfig.test.json) ran against a forced declarations build of@object-ui/app-shell^....node scripts/check-sdui-manifest.mjsis in the derived list above.Acceptance notes
sys_activity's by-name read on Home belongs touseObjectPresence(the activity feeds), not to the roster gate. It is left as it is: one name, and its by-name read is the one the adapter cache shares.MetadataClient.listin@object-ui/data-objectstackhas nonamesoption. Adding one is a data-adapter change this card does not need.