Files

41 lines
1.7 KiB
TypeScript

// The status a page reads: the module flag, the search service's readiness (separate from the
// indexing indicator, which is the per-document rows), and the document counts by progress state.
import { type DocumentStatus, documents } from "../contract/index.js"
import { type KnowledgeDeps, type KnowledgeScope, knowledgeEnabled } from "./ports.js"
const PAGE = 200
export interface KnowledgeStatus {
enabled: boolean
service: { state: "registered" | "indexing" | "ready" | "degraded" | "disabled" | "unavailable"; reasons: string[] }
documents: Record<DocumentStatus, number>
}
export async function knowledgeStatusOf(deps: KnowledgeDeps, scope: KnowledgeScope): Promise<KnowledgeStatus> {
const counts: Record<DocumentStatus, number> = { queued: 0, indexing: 0, indexed: 0, failed: 0, cancelled: 0 }
let cursor: string | undefined
for (;;) {
const page = await deps.data
.forScope(scope)
.of(documents)
.list({ limit: PAGE, ...(cursor === undefined ? {} : { cursor }) })
for (const row of page.items) counts[row.status as DocumentStatus] += 1
if (!page.hasMore) break
cursor = page.cursor
}
const enabled = await knowledgeEnabled(deps, scope)
const readiness =
deps.search === undefined
? { state: "unavailable" as const, reasons: ["the knowledge search service is not bound in this process"] }
: await deps.search.readiness(scope).catch((error: unknown) => ({
state: "unavailable" as const,
reasons: [
error instanceof Error
? (error.message.split("\n")[0] ?? error.message)
: "the search service did not answer",
],
}))
return { enabled, service: readiness, documents: counts }
}