Merge branch 'release/8.10.1'
# Conflicts: # .forgejo/workflows/ci.yml
This commit is contained in:
commit
fc9f0d7222
17 changed files with 681 additions and 105 deletions
112
src/brainy.ts
112
src/brainy.ts
|
|
@ -65,7 +65,8 @@ import type {
|
|||
OpaqueIdSet,
|
||||
AtGenerationVectors,
|
||||
VectorIndexProvider,
|
||||
GraphIndexProvider
|
||||
GraphIndexProvider,
|
||||
ProviderMaintenanceDebt
|
||||
} from './plugin.js'
|
||||
import type {
|
||||
BrainyPlugin,
|
||||
|
|
@ -424,6 +425,30 @@ export interface WarmReport {
|
|||
totalDurationMs: number
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Result of {@link Brainy.maintenanceDebt}: one outcome per
|
||||
* index surface, mirroring {@link WarmReport}'s shape.
|
||||
* - `'reported'` — the active provider for this surface implements
|
||||
* `maintenanceDebt?()` and its {@link ProviderMaintenanceDebt} payload is
|
||||
* attached verbatim under `debt`.
|
||||
* - `'unavailable'` — the active provider does not implement the hook, so
|
||||
* nothing is known; brainy never estimates or infers a payload on its
|
||||
* behalf.
|
||||
*/
|
||||
export type MaintenanceDebtOutcome = 'reported' | 'unavailable'
|
||||
|
||||
/**
|
||||
* @description Per-surface result of {@link Brainy.maintenanceDebt}. Brainy
|
||||
* performs no thresholding, polling, or estimation over this data — it is a
|
||||
* pure passthrough of each active provider's own self-report (the provider
|
||||
* owns the numbers; the operator owns the policy).
|
||||
*/
|
||||
export interface MaintenanceDebtReport {
|
||||
vector: { outcome: MaintenanceDebtOutcome; debt?: ProviderMaintenanceDebt }
|
||||
metadata: { outcome: MaintenanceDebtOutcome; debt?: ProviderMaintenanceDebt }
|
||||
graph: { outcome: MaintenanceDebtOutcome; debt?: ProviderMaintenanceDebt }
|
||||
}
|
||||
|
||||
/**
|
||||
* How long a failed aggregation-backfill walk suppresses fresh walk attempts.
|
||||
* Within the window, queries rethrow the recorded failure instantly (loud,
|
||||
|
|
@ -14352,9 +14377,16 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
* *some* backing storage as a side effect but is reported honestly as
|
||||
* `'probed'`, never `'warmed'`. An empty index or unknown dimension has
|
||||
* nothing to probe (`'unavailable'`).
|
||||
* - **Metadata**: full hydration — every persisted field's sparse index is
|
||||
* loaded from storage (`MetadataIndexManager.hydrateAll()`), not just the
|
||||
* heuristic common-fields subset `init()` warms.
|
||||
* - **Metadata**: calls the provider's own `warm?()` when the active
|
||||
* `'metadataIndex'` provider implements it (`'warmed'`) — the seam a
|
||||
* native metadata provider lights up so it is not duck-typed against the
|
||||
* JS manager's method. Otherwise falls back to full hydration on the
|
||||
* built-in JS manager — every persisted field's sparse index is loaded
|
||||
* from storage (`MetadataIndexManager.hydrateAll()`), not just the
|
||||
* heuristic common-fields subset `init()` warms — and reports `'warmed'`.
|
||||
* Neither seam present → `'unavailable'` (honest: `init()` is never used
|
||||
* as a substitute here, since a native provider's `init()` may be a
|
||||
* cheap verify rather than a real warm).
|
||||
* - **Graph**: calls the provider's own `warm?()` when the active graph
|
||||
* provider implements it; otherwise re-runs its existing eager cold-load
|
||||
* `init()` seam (idempotent — the JS adjacency index's `init()` already
|
||||
|
|
@ -14410,12 +14442,23 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
// --- Metadata --------------------------------------------------------
|
||||
const metadataStart = Date.now()
|
||||
let metadataOutcome: WarmOutcome
|
||||
const metadataProvider = this.metadataIndex as unknown as MetadataIndexProvider
|
||||
const metadataWithHydrate = this.metadataIndex as unknown as { hydrateAll?: () => Promise<void> }
|
||||
if (typeof metadataWithHydrate.hydrateAll === 'function') {
|
||||
if (typeof metadataProvider.warm === 'function') {
|
||||
// Active provider (e.g. a native metadata index) declares its own warm
|
||||
// seam — route through it FIRST so a native provider's warmth is
|
||||
// reported honestly instead of being duck-typed against the JS
|
||||
// manager's hydrateAll(), which a native provider does not implement.
|
||||
await metadataProvider.warm()
|
||||
metadataOutcome = 'warmed'
|
||||
} else if (typeof metadataWithHydrate.hydrateAll === 'function') {
|
||||
// Built-in JS manager path — full sparse-index hydration.
|
||||
await metadataWithHydrate.hydrateAll()
|
||||
metadataOutcome = 'warmed'
|
||||
} else {
|
||||
// No hydration seam on this metadata provider — nothing to run.
|
||||
// No hydration seam on this metadata provider — nothing to run. (No
|
||||
// init() fallback here: init() on a native provider may be a cheap
|
||||
// verify, and reporting that as warmth would lie.)
|
||||
metadataOutcome = 'unavailable'
|
||||
}
|
||||
const metadataDurationMs = Date.now() - metadataStart
|
||||
|
|
@ -14449,6 +14492,63 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read each index surface's self-reported outstanding maintenance work —
|
||||
* the observability seam so an operator sees a grind coming (rising
|
||||
* pending bytes/items, a stalled background pass) instead of discovering
|
||||
* it as a CPU storm or a transaction blowing its budget mid-flight (see
|
||||
* {@link TransactionTimeoutError}).
|
||||
*
|
||||
* PURE PASSTHROUGH: for each of vector/metadata/graph, this calls ONLY the
|
||||
* ACTIVE provider's own `maintenanceDebt?()` hook (the same per-surface
|
||||
* provider resolution {@link Brainy.warm} uses) and reports its
|
||||
* {@link ProviderMaintenanceDebt} payload verbatim. There is no JS-side
|
||||
* fallback computation, no threshold evaluation, and no polling — brainy
|
||||
* surfaces the truth the provider measured; the provider owns the numbers
|
||||
* and the operator owns the policy (what threshold matters, what action to
|
||||
* take). A surface whose active provider does not implement the hook
|
||||
* reports `'unavailable'` — never a guessed or zeroed payload.
|
||||
*
|
||||
* @returns A {@link MaintenanceDebtReport}: per-surface outcome + payload.
|
||||
* @example
|
||||
* ```typescript
|
||||
* const debt = await brain.maintenanceDebt()
|
||||
* if (debt.metadata.outcome === 'reported' && debt.metadata.debt?.pendingBytes) {
|
||||
* console.log('metadata pending bytes:', debt.metadata.debt.pendingBytes)
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
async maintenanceDebt(): Promise<MaintenanceDebtReport> {
|
||||
await this.ensureInitialized({ needs: ['vector', 'metadata', 'graph'] })
|
||||
|
||||
// --- Vector ---------------------------------------------------------
|
||||
const vectorProvider = this.index as VectorIndexProvider & {
|
||||
maintenanceDebt?: () => Promise<ProviderMaintenanceDebt>
|
||||
}
|
||||
const vector =
|
||||
typeof vectorProvider.maintenanceDebt === 'function'
|
||||
? { outcome: 'reported' as const, debt: await vectorProvider.maintenanceDebt() }
|
||||
: { outcome: 'unavailable' as const }
|
||||
|
||||
// --- Metadata --------------------------------------------------------
|
||||
const metadataProvider = this.metadataIndex as unknown as MetadataIndexProvider
|
||||
const metadata =
|
||||
typeof metadataProvider.maintenanceDebt === 'function'
|
||||
? { outcome: 'reported' as const, debt: await metadataProvider.maintenanceDebt() }
|
||||
: { outcome: 'unavailable' as const }
|
||||
|
||||
// --- Graph -------------------------------------------------------------
|
||||
const graphProvider = this.graphIndex as GraphIndexProvider & {
|
||||
maintenanceDebt?: () => Promise<ProviderMaintenanceDebt>
|
||||
}
|
||||
const graph =
|
||||
typeof graphProvider.maintenanceDebt === 'function'
|
||||
? { outcome: 'reported' as const, debt: await graphProvider.maintenanceDebt() }
|
||||
: { outcome: 'unavailable' as const }
|
||||
|
||||
return { vector, metadata, graph }
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly warm up the embedding engine
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue