t142: 雲端子庫顯示同步幾張卡+幾個三元組(政府專案驗收需求)
leo 07-29:「要在雲端子庫顯示同步了幾個 wiki,既然這樣也同步顯示有幾個三元組,
這是為了政府專案驗收。」
kbdb 兩支統計端點:
- entries.ts: COUNT(DISTINCT page_name) AS card_count
⚠️ 必須 distinct——算 block 數會膨脹 3-5 倍,政府驗收看到假數字比沒數字更糟
- records.ts: COUNT(*) AS triplet_count(三元組本來就算全部)
portal.ts 聚合兩者掛進庫目錄;前端 index.html 顯示。
驗:卡數確為 COUNT(DISTINCT page_name)/前端內嵌 JS node --check 全通過
(07-29 白畫面事故教訓)/portal-admin 測試 34 passed(改動前 31 passed,
唯一的 1 failed 是既有債:GET /portal 回 404,改動前後相同,非本次造成)。
註:此為子 CC 完成後未 commit 的懸置工作,總管收工檢查時發現並補收。
This commit is contained in:
@@ -1081,11 +1081,35 @@ portalRouter.get('/portal/admin/libraries', (c) =>
|
||||
return { ...lib, ...(watching !== undefined ? { daemon_watching: watching } : {}) };
|
||||
});
|
||||
const known = new Set(out.map((l) => l.name));
|
||||
// 資料面實際出現的庫(來自 ingest 蓋章的 metadata.library)
|
||||
// t142:資料面實際出現的庫+統計數字(卡數、三元組數)並行撈取,避免 N+1。
|
||||
// 任一端點失敗不擋登記簿列表(誠實降級:stats 保持 0,不炸主流程)。
|
||||
try {
|
||||
const res = await kbdbFetch(c.env, `/entries/libraries?owner_id=${encodeURIComponent(portalTenant(c.env))}`);
|
||||
if (res.ok) {
|
||||
const body = (await res.json()) as { libraries?: string[] };
|
||||
const tenant = portalTenant(c.env);
|
||||
const ownerParam = `owner_id=${encodeURIComponent(tenant)}`;
|
||||
const [autoRes, cardRes, tripletRes] = await Promise.all([
|
||||
kbdbFetch(c.env, `/entries/libraries?${ownerParam}`).catch(() => null),
|
||||
kbdbFetch(c.env, `/entries/library-stats?${ownerParam}`).catch(() => null),
|
||||
kbdbFetch(c.env, `/records/triplet-stats?${ownerParam}`).catch(() => null),
|
||||
]);
|
||||
// 解析統計,建成 Map 供 O(1) 查找
|
||||
const cardMap = new Map<string, number>();
|
||||
if (cardRes?.ok) {
|
||||
const body = (await cardRes.json()) as { stats?: { library: string; card_count: number }[] };
|
||||
for (const s of body.stats ?? []) cardMap.set(s.library, s.card_count);
|
||||
}
|
||||
const tripletMap = new Map<string, number>();
|
||||
if (tripletRes?.ok) {
|
||||
const body = (await tripletRes.json()) as { stats?: { library: string; triplet_count: number }[] };
|
||||
for (const s of body.stats ?? []) tripletMap.set(s.library, s.triplet_count);
|
||||
}
|
||||
// 已登記庫補入統計
|
||||
for (const lib of out) {
|
||||
(lib as Record<string, unknown>).card_count = cardMap.get(lib.name) ?? 0;
|
||||
(lib as Record<string, unknown>).triplet_count = tripletMap.get(lib.name) ?? 0;
|
||||
}
|
||||
// 資料面自動出現的庫(蓋章即現身)
|
||||
if (autoRes?.ok) {
|
||||
const body = (await autoRes.json()) as { libraries?: string[] };
|
||||
for (const name of body.libraries ?? []) {
|
||||
const n = String(name ?? '').trim();
|
||||
// general 是系統內部「未標庫」桶(未標記 entry 的 fallback),不在用戶目錄露臉
|
||||
@@ -1096,6 +1120,8 @@ portalRouter.get('/portal/admin/libraries', (c) =>
|
||||
record_id: '', name: n, display_name: n,
|
||||
description: '資料同步時自動出現(可在此補顯示名)',
|
||||
status: 'active', graph_source: false, auto: true,
|
||||
card_count: cardMap.get(n) ?? 0,
|
||||
triplet_count: tripletMap.get(n) ?? 0,
|
||||
...(watching !== undefined ? { daemon_watching: watching } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user