feat: warm contract (warm/warmOnOpen/provider warm hook), configurable transact budget floor, backend-neutral vector index op names
Three pieces addressing the cold-restart-write incident where a production deployment's first writes after every restart (33-35s each on a cold page cache) blew the op-count-scaled transact budget mid-batch: every write is itself a multi-op transaction, so one cold operation consumed the whole budget, the gate before the next operation tripped, and the write rolled back atomically - refused, retried, and refused again until the page cache warmed passively. - The budget's start-gating contract is now explicit and pinned: it gates STARTING the next operation, never rolling back completed work for elapsed time (the shipped schedule since 8.7.0, now stated in contract JSDoc, guarded by code for operation 0, and enforced by regression tests). The 30s floor is configurable via transactionBudgetFloorMs for stores whose cold operations legitimately run long. - New brain.warm() eagerly loads the vector index, metadata index, and graph adjacency so first operations after a cold restart run at steady-state cost. Returns a WarmReport with an honest per-surface outcome (warmed / probed / unavailable) - never reports a probe as a warm. warmOnOpen: true runs it during init(). New optional provider hook warm() on the vector and graph plugin contracts. - Vector-index transaction op classes renamed from the backend-specific AddToHNSWOperation / RemoveFromHNSWOperation to backend-neutral AddToVectorIndexOperation / RemoveFromVectorIndexOperation, stamping the active backend into the emitted op-name string (AddToVectorIndex(js-hnsw) vs a native provider's own identity) so journals never misdirect an operator toward an index that isn't running.
This commit is contained in:
parent
d08679fc84
commit
55b867c998
13 changed files with 1099 additions and 57 deletions
|
|
@ -1651,6 +1651,25 @@ export interface BrainyConfig {
|
|||
*/
|
||||
disableAutoRebuild?: boolean
|
||||
|
||||
/**
|
||||
* The floor (ms) of the apply-phase transaction budget's scaling formula:
|
||||
* `max(transactionBudgetFloorMs, opCount × 2 000)`. The budget governs
|
||||
* whether a `transact()` / single-op write's NEXT internal operation may
|
||||
* **start** — never whether already-completed work gets rolled back after
|
||||
* the fact (a single-op write can never time out post-hoc: it either runs
|
||||
* or it commits). A trip mid-batch still rolls back every applied operation
|
||||
* atomically and throws a retryable `TransactionTimeoutError`; only the
|
||||
* floor of the formula is configurable here.
|
||||
*
|
||||
* Raise this when a cold store's first writes after a restart legitimately
|
||||
* take longer than 30s per operation (e.g. page-cache-cold canonical writes
|
||||
* on a large brain) so a bulk `transact()` batch gets a proportionally
|
||||
* larger runway instead of tripping mid-batch. Lower it to fail faster on a
|
||||
* latency-sensitive write path. Default: `30000` (30 s) — unchanged from
|
||||
* pre-8.9 behavior.
|
||||
*/
|
||||
transactionBudgetFloorMs?: number
|
||||
|
||||
/**
|
||||
* How long (ms) an operation **waits** on the coordinated 7.x → 8.0 migration
|
||||
* before throwing a retryable `MigrationInProgressError`.
|
||||
|
|
@ -1806,6 +1825,23 @@ export interface BrainyConfig {
|
|||
*/
|
||||
eagerEmbeddings?: boolean
|
||||
|
||||
/**
|
||||
* When `true`, `init()` **awaits `warm()`** (see {@link Brainy.warm}) before
|
||||
* it resolves — blocking startup until the vector index, metadata index,
|
||||
* and graph adjacency have all faulted their backing storage in. This is a
|
||||
* deliberate operator opt-in trade: startup takes longer, but the FIRST
|
||||
* request after a cold restart runs at steady-state cost instead of paying
|
||||
* page-cache-miss / demand-load latency on the critical path.
|
||||
*
|
||||
* Runs AFTER `init()`'s own sequence completes (index construction, crash
|
||||
* recovery, migrations, VFS bootstrap) — never in place of any of it — so
|
||||
* `warm()` always operates on a fully-initialized brain.
|
||||
*
|
||||
* Default: `false` (lazy — the pre-8.9 behavior: indexes demand-load on
|
||||
* first access).
|
||||
*/
|
||||
warmOnOpen?: boolean
|
||||
|
||||
// Plugin configuration
|
||||
// Controls which plugins are loaded during init().
|
||||
// - undefined (default): guarded auto-detection of the first-party
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue