@lunora/do 1.0.0-alpha.61 → 1.0.0-alpha.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SchemaLike, DatabaseWriterLike, CdcChange, FilterClause, ExportRow, MigrationDirection, ReactiveCache, ReactiveCacheOptions, ShardSocketLike, LifecycleDispatchInfo, MigrationRunResult, TableIndexInfo, ColumnMeta, AdvisoryFinding, AdvisorProcedure, RlsPoliciesResult, MaskPoliciesResult, StorageRulesResult, StudioFeaturesResult, FlagsResult, SubscriptionIdentity, QueuesResult, WorkflowsResult, ImportShardResult, ShardRankPageResult, SubscriptionQuery, ShapeSubscriptionQuery, MutationDelta, KeyRange, ResolvedShape, ShapeRow, TtlSweepSpec, TransactionLimits,
|
|
1
|
+
import { SchemaLike, DatabaseWriterLike, CdcChange, FilterClause, ExportRow, MigrationDirection, ReactiveCache, ReactiveCacheOptions, ShardSocketLike, TransactionHeadroomTracker, LifecycleDispatchInfo, MigrationRunResult, TableIndexInfo, ColumnMeta, AdvisoryFinding, AdvisorProcedure, RlsPoliciesResult, MaskPoliciesResult, StorageRulesResult, StudioFeaturesResult, FlagsResult, SubscriptionIdentity, QueuesResult, WorkflowsResult, ImportShardResult, ShardRankPageResult, SubscriptionQuery, ShapeSubscriptionQuery, MutationDelta, KeyRange, ResolvedShape, ShapeRow, TtlSweepSpec, TransactionLimits, IndexKeyEntry, SqlExec } from '@lunora/shard-engine';
|
|
2
2
|
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, AGGREGATE_SQL_FUNCTION, type AdvisorProcedure, type AdvisorProceduresResult, type AdvisoriesResult, type AdvisoryFinding, type AggregateIndexDefinitionLike, type AggregateOp, type AggregateOptions, type AggregateResult, type AggregateTally, type ApplyOnDeleteOptions, type AuditEntry, type AuditLogResult, type BroadcastDelta, CDC_LOG_TABLE, type CacheEntry, type CapturedMailRow, type CdcChange, type Clock, type ColumnMeta, type ColumnMetaLike, ConflictError, type CountArgs, CountRlsUnsupportedError, type CtxDbOptions, DATA_MIGRATION_STATE_TABLE, DEFAULT_MAX_RELATION_KEYS, type DataMigrationDocument, type DataMigrationLike, type DataMigrationTransform, type DatabaseWriterLike, type DependencyTracker, type DeployInfo, type ExportRow, type ExportShardAdminArgs, type ExportShardArgs, type ExternalSourceDiffResult, type ExternalSourceLike, FLAGS_FUNCTION_PREFIX, type FacetColumnOptions, type FacetColumnResult, type FacetValue, type FieldOperators, type FlagEvaluation, type FlagsResult, type FunctionCallStat, type FunctionStatsResult, GEO_DEFAULT_PRECISION, type GeoBoundingBox, type GeoFilterBuilderLike, type GeoIndexDefinitionLike, type GeoPoint, type GroupByEntry, type GroupByOptions, type IdGenerator, type ImportError, type ImportShardAdminArgs, type ImportShardArgs, type ImportShardResult, type IncrementalMaterializeResult, type IndexDefinitionLike, type IndexKeyEntry, type IndexRangeBuilderLike, type KeyRange, MAIL_RETENTION, MAIL_TABLE, MAX_SQL_ROWS, type MaskColumnMetadata, type MaskPoliciesResult, type MaterializeResult, type MigrationDirection, type MigrationRunResult, type MigrationStatus, type MigrationStatusRow, type MutationDelta, type NestedWith, NotFoundError, NotUniqueError, type OnDeleteActionLike, type OrderByInput, type OrderKey, type PaginationOptions, type PitrBookmarkResult, type PitrRestoreArgs, type PitrRestoreResult, type PitrStorage, type QueryArgs, type QueryPage, type QueueMetadata, type QueuesResult, RANK_TIEBREAK, RELATION_FUNCTION_PREFIX, RLS_UNWRAP_SYMBOL, type RankDirection, type RankIndexDefinitionLike, type RankOptions, type RankPage, type RankPageOptions, type RankPageRow, type RankPageRowKey, type RankResult, type RankSortKeyLike, ReactiveCache, type ReactiveCacheOptions, type ReadHook, type ReadTablePageOptions, type RecordMailInput, type RelationDefinitionLike, type RenderedSql, type ResolveRelationPredicatesOptions, type ResolveWithOptions, type RestrictableQueryOptions, type RlsPoliciesResult, type RlsPolicyMetadata, RlsRequiredError, type RlsRoleMetadata, type RpcRequest, type RunDataMigrationOptions, type RunTriggersOptions, SCAN_DEP, type SchedulableWorkflowReferenceLike, type ScheduledFunctionDoc, type SchedulerLike, type SchemaLike, type SearchFilterBuilderLike, type SearchIndexDefinitionLike, type SelectMatchingIdsOptions, type ServerDefaultContextLike, type SettingEntry, type SettingKind, type SettingsResult, type ShapeSubscriptionQuery, type ShardRankPageResult, type SocketAttachment, type SortDirection, type SourceClientLike, type SourceCursorLike, type SourceRefresh, type SqlConsoleResult, type SqlCursor, type SqlEngine, type SqlExec, type StorageRuleMetadata, type StorageRulesResult, type StudioFeaturesResult, type SubscriptionEnvelope, type SubscriptionQuery, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemReaderOptions, type SystemReaderSchedulerLike, type SystemReaderStorageLike, type SystemTableName, type TableColumnsResult, type TableDefinitionLike, type TableIndexInfo, type TableIndexesResult, type TableInfo, type TablePage, type TableReaderLike, type TablesColumnsResult, type TransactionHeadroomTracker, type TransactionSqlLike, type TriggerContextLike, type TriggerDefinitionLike, type TriggerEventLike, type TriggerOpLike, type TriggerTimingLike, type TtlSweepSpec, type ValidatorLike, type WhereInput, type WhereSqlStrategy, type WithInput, type WorkflowMetadata, type WorkflowsResult, type WriteEvent, type WriteHook, aggregateSqlFunction, aggregateTableName, applyCdcChanges, applyOnDelete, applySelect, armRestore, assertFlatPredicate, assertReadonly, assertShapeShardable, assertValidClientId, backfillAggregateIndexes, backfillRankIndexes, backfillSearchIndexes, boundingBoxCenter, boundingBoxGeohashes, buildSeekWhere, clearCapturedMail, coerceAggregateNumber, compileWhereSql, containsRelationPredicate, coveringGeohashes, createDependencyTracker, createReadFootprint, createShardCtxDb, createSystemReader, decodeCursor, depKey, diffExternalSource, encodeAggregateKey, encodeCursor, encodeGeohash, encodePartitionKey, ensureMailTable, exportShardRows, exportShardTable, facetColumn, fanOutScalarCounts, foldAggregateTally, guardWriter, hasTrigger, haversineMeters, importShardRows, isRelationPredicate, isSoftDeleted, isSourceDue, liftSourceId, listTables, matchesRankStaticWhere, matchesStaticWhere, materializeExternalRows, materializeExternalRowsIncremental, mergeWhere, normalizeCountArgument, normalizeIdStructurally, normalizeOrderKeys, parseExportShardArgs, parseImportShardArgs, planAggregateLookup, pointInBoundingBox, pullExternalSourceIncrementalTick, pullExternalSourceTick, rankTableName, reactiveCacheKey, readAggregateValue, readBookmark, readCapturedMail, readCdcChanges, readExternalSourceBaseline, readMigrationStatus, readTablePage, recordCapturedMail, renderSql, resolveRankPartition, resolveRelationPredicates, resolveWith, runDataMigration, runExternalSourceTick, runReadonlySql, runRowValidators, runShardMigrations, runTriggers, selectExpiredIds, selectExportTables, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy, selectMatchingIds, softDeleteScope, sortColumnName, stableStringify, stableWireKey, subscriptionListDeltas, throwingScheduler, trimCdcChanges, validateImportRow } from '@lunora/shard-engine';
|
|
3
3
|
import { DatabaseInstrumentation, MetricHistoryOptions, LogEventInput, ContextLogLevel, TraceAnchor, ContextTracer, ContextFetch, ContextMetrics } from '@lunora/observability';
|
|
4
4
|
import { DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite';
|
|
@@ -1131,6 +1131,13 @@ declare abstract class ShardDO {
|
|
|
1131
1131
|
* RPC. In-memory only — they reset when the DO hibernates or restarts, which
|
|
1132
1132
|
* is the right granularity for a "since this instance woke" health readout
|
|
1133
1133
|
* (durable aggregation would be a separate, heavier feature).
|
|
1134
|
+
*
|
|
1135
|
+
* `subscriptionRefreshErrors` (DO-01) rides along the same lifetime/in-memory
|
|
1136
|
+
* shape: incremented, alongside a structured log, wherever a live-query
|
|
1137
|
+
* refresh or shape poke swallows a per-subscription/per-socket error so its
|
|
1138
|
+
* siblings can keep flushing (`refreshSubscriptions`, `pokeShapeSubscribers`
|
|
1139
|
+
* via `recordSubscriptionRefreshError`). It IS on the `getMetrics` wire
|
|
1140
|
+
* response (`collectMetrics`); a studio panel charting it is a follow-up.
|
|
1134
1141
|
*/
|
|
1135
1142
|
private readonly metrics;
|
|
1136
1143
|
/**
|
|
@@ -1208,6 +1215,16 @@ declare abstract class ShardDO {
|
|
|
1208
1215
|
* call so a leaked tracker can never bleed into a sibling RPC.
|
|
1209
1216
|
*/
|
|
1210
1217
|
private currentTracker;
|
|
1218
|
+
/**
|
|
1219
|
+
* In-flight range footprint (the `onReadRange` channel) for the
|
|
1220
|
+
* currently-executing cached query. Set by `runCachedQuery` alongside
|
|
1221
|
+
* `currentTracker` so `getCtxDbReadRangeHook` — and the range-marking half
|
|
1222
|
+
* of `getCtxDbReadHook` — can stamp it without threading it explicitly
|
|
1223
|
+
* through every generated handler signature. `ReactiveCache.run`'s ranges
|
|
1224
|
+
* thunk reads it lazily, AFTER the handler resolves, so it always sees the
|
|
1225
|
+
* footprint's final state. Cleared in the same `finally` as `currentTracker`.
|
|
1226
|
+
*/
|
|
1227
|
+
private currentReadFootprint;
|
|
1211
1228
|
/**
|
|
1212
1229
|
* Tables the in-flight dispatch full-scanned (read via `SCAN_DEP`, no index
|
|
1213
1230
|
* / point lookup). Allocated at the top of each `/rpc` dispatch and drained
|
|
@@ -1248,19 +1265,38 @@ declare abstract class ShardDO {
|
|
|
1248
1265
|
*/
|
|
1249
1266
|
private currentRequestReadTables;
|
|
1250
1267
|
/**
|
|
1251
|
-
* Per-statement SQL samples collected during the current `/rpc`
|
|
1252
|
-
* the instrumented `sql` getter
|
|
1253
|
-
* `__lunora_metrics_queries` table after the
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1256
|
-
* never leak into the
|
|
1257
|
-
*
|
|
1258
|
-
*
|
|
1259
|
-
*
|
|
1268
|
+
* Per-DISTINCT-statement SQL samples collected during the current `/rpc`
|
|
1269
|
+
* dispatch by the instrumented `sql` getter, keyed by the raw query text.
|
|
1270
|
+
* Drained into the durable `__lunora_metrics_queries` table after the
|
|
1271
|
+
* handler returns (same pattern as `currentScannedTables` /
|
|
1272
|
+
* `currentIndexHits`). `undefined` when no dispatch is in flight; allocated
|
|
1273
|
+
* fresh per dispatch so a previous request's samples never leak into the
|
|
1274
|
+
* next one.
|
|
1275
|
+
*
|
|
1276
|
+
* Keyed by the raw query string rather than a growing array: a handler
|
|
1277
|
+
* that queries in a loop reuses the SAME prepared-statement text on every
|
|
1278
|
+
* iteration (bind parameters travel separately via `...params`, never
|
|
1279
|
+
* inlined into `query`), so folding each call into its entry as it lands
|
|
1280
|
+
* collapses the loop to one entry — {@link ShardDO.flushStmtSamples} then
|
|
1281
|
+
* pays one upsert per DISTINCT statement instead of one per raw execution.
|
|
1282
|
+
* Bounded at {@link MAX_STMT_SAMPLES_PER_DISPATCH} distinct entries; past
|
|
1283
|
+
* that, a brand-new statement shape (ad-hoc SQL built per iteration) is
|
|
1284
|
+
* dropped and `currentStmtSamplesTruncated` is set — already-tracked
|
|
1285
|
+
* statements keep folding regardless.
|
|
1286
|
+
*
|
|
1287
|
+
* `rowsWritten` is always 0 here — the ctx-db adapter doesn't expose a
|
|
1260
1288
|
* `changes()` count through the structural `SqlExec` surface, so we
|
|
1261
1289
|
* attribute only SELECT result sizes as `rowsRead`.
|
|
1262
1290
|
*/
|
|
1263
1291
|
private currentStmtSamples;
|
|
1292
|
+
/**
|
|
1293
|
+
* Set when `currentStmtSamples` hit {@link MAX_STMT_SAMPLES_PER_DISPATCH}
|
|
1294
|
+
* distinct statements and a brand-new shape was dropped this dispatch.
|
|
1295
|
+
* Folded onto the dispatch's wide event as `db.stmt_samples_truncated`
|
|
1296
|
+
* (mirrors `database-telemetry.ts`'s `db.spans_truncated`) so a truncated
|
|
1297
|
+
* leaderboard contribution reads as partial rather than complete.
|
|
1298
|
+
*/
|
|
1299
|
+
private currentStmtSamplesTruncated;
|
|
1264
1300
|
/** Whether the current dispatch's cached query was served from cache; `undefined` until `runCachedQuery` resolves one. */
|
|
1265
1301
|
private currentRequestCacheHit;
|
|
1266
1302
|
constructor(state: ShardDOState, env: unknown, options?: ShardDOOptions);
|
|
@@ -1315,8 +1351,22 @@ declare abstract class ShardDO {
|
|
|
1315
1351
|
* this stays dormant there.
|
|
1316
1352
|
*/
|
|
1317
1353
|
alarm(): Promise<void>;
|
|
1318
|
-
/**
|
|
1319
|
-
|
|
1354
|
+
/**
|
|
1355
|
+
* Subclasses implement function dispatch.
|
|
1356
|
+
*
|
|
1357
|
+
* `headroom` is an optional BY-VALUE override, mirroring
|
|
1358
|
+
* {@link ShardDO.deleteRowThroughWriter}'s pattern: the main `/rpc` dispatch
|
|
1359
|
+
* (`handleFetchCloudflare`) captures its freshly-minted tracker in a LOCAL and
|
|
1360
|
+
* passes it here explicitly, so the ctx this dispatch builds never depends on
|
|
1361
|
+
* `this.currentTransactionHeadroom` still holding the right value by the time
|
|
1362
|
+
* the (possibly `await`-interleaved) handler runs — a concurrent dispatch's
|
|
1363
|
+
* `finally` clearing that shared field could otherwise leave this one
|
|
1364
|
+
* unmetered mid-flight. Callers that dispatch through here without minting
|
|
1365
|
+
* their own tracker (`dispatchLifecycle`, `handleRunAs`) omit it and the
|
|
1366
|
+
* codegen subclass falls back to `this.transactionHeadroom()`, unchanged from
|
|
1367
|
+
* before this parameter existed.
|
|
1368
|
+
*/
|
|
1369
|
+
abstract handleRpc(functionPath: string, args: Record<string, unknown>, headroom?: TransactionHeadroomTracker): Promise<unknown>;
|
|
1320
1370
|
/**
|
|
1321
1371
|
* The registered function paths to dispatch when a socket connects/disconnects.
|
|
1322
1372
|
* Base default is empty; the codegen subclass overrides it to return the
|
|
@@ -1353,7 +1403,7 @@ declare abstract class ShardDO {
|
|
|
1353
1403
|
protected runRelationFanoutRead(_functionPath: string, _args: Record<string, unknown>): Promise<unknown>;
|
|
1354
1404
|
/**
|
|
1355
1405
|
* Instrumented SQL handle. Wraps `state.storage.sql` so that every `exec`
|
|
1356
|
-
* call during a user RPC dispatch is timed and its result size
|
|
1406
|
+
* call during a user RPC dispatch is timed and its result size folded into
|
|
1357
1407
|
* `currentStmtSamples`. The samples are flushed to the durable
|
|
1358
1408
|
* `__lunora_metrics_queries` table after the handler returns (same lifecycle
|
|
1359
1409
|
* as `currentScannedTables`/`currentIndexHits`).
|
|
@@ -1669,8 +1719,14 @@ declare abstract class ShardDO {
|
|
|
1669
1719
|
* The base class can't build a writer without the user's `schema.ts`, so it
|
|
1670
1720
|
* reports the table as unknown; the codegen-generated subclass overrides
|
|
1671
1721
|
* this to call `writer.delete(id)` on a live `createShardCtxDb(...)` writer.
|
|
1722
|
+
*
|
|
1723
|
+
* `headroom` is an optional BY-VALUE override: {@link ShardDO.runShardBulkDelete}
|
|
1724
|
+
* (a normal `/rpc` dispatch) omits it, so the override falls back to
|
|
1725
|
+
* `this.transactionHeadroom()` — the per-dispatch meter every other write
|
|
1726
|
+
* already uses. {@link ShardDO.pollTtlSweeps} (an alarm work item, no dispatch
|
|
1727
|
+
* in flight) passes its own fresh tracker explicitly instead.
|
|
1672
1728
|
*/
|
|
1673
|
-
protected deleteRowThroughWriter(_table: string, _id: string): Promise<void>;
|
|
1729
|
+
protected deleteRowThroughWriter(_table: string, _id: string, _headroom?: TransactionHeadroomTracker): Promise<void>;
|
|
1674
1730
|
/**
|
|
1675
1731
|
* Bulk-delete the rows of `table` matching the active `filters`/`search`
|
|
1676
1732
|
* (or every row, for `clearTable`), bounded to {@link SHARD_BULK_DELETE_CAP}
|
|
@@ -2042,6 +2098,17 @@ declare abstract class ShardDO {
|
|
|
2042
2098
|
* cadence, so freshly-written rows expire within a bounded window) while any
|
|
2043
2099
|
* TTL table exists, or `undefined` when there are none — so a DO with no TTL
|
|
2044
2100
|
* table never arms this tier.
|
|
2101
|
+
*
|
|
2102
|
+
* One {@link ShardDO.alarmHeadroom} tracker covers the WHOLE sweep pass (every
|
|
2103
|
+
* spec, every batch) — not per-row or per-spec — because the ceiling exists to
|
|
2104
|
+
* bound one alarm tick's total isolate cost, not any single table's. A
|
|
2105
|
+
* `TRANSACTION_LIMIT_EXCEEDED` mid-batch is "batch full", not a genuine
|
|
2106
|
+
* failure: `selectExpiredIds` never re-selects an already-deleted row, so
|
|
2107
|
+
* deletion IS the resumable checkpoint here — no separate cursor is needed.
|
|
2108
|
+
* The sweep stops immediately, logs a `warn` (not `recordShapeError`, which
|
|
2109
|
+
* would surface as a genuine failure), and returns `Date.now()` so the shared
|
|
2110
|
+
* alarm re-arms promptly via `nextPollAlarmTarget`'s existing due-now floor,
|
|
2111
|
+
* rather than waiting out the full `TTL_SWEEP_INTERVAL_MS` cadence.
|
|
2045
2112
|
*/
|
|
2046
2113
|
protected pollTtlSweeps(): Promise<number | undefined>;
|
|
2047
2114
|
/**
|
|
@@ -2084,6 +2151,24 @@ declare abstract class ShardDO {
|
|
|
2084
2151
|
* with empty dep sets, so writes never invalidate them and stale
|
|
2085
2152
|
* results stick around — the {@link ReactiveCache} class is contract-
|
|
2086
2153
|
* neutral about who fills `deps`.
|
|
2154
|
+
*
|
|
2155
|
+
* Also allocates a fresh {@link ReadFootprint} alongside the tracker,
|
|
2156
|
+
* stored on `this.currentReadFootprint` so `getCtxDbReadRangeHook()` —
|
|
2157
|
+
* and the range-marking half of `getCtxDbReadHook()` — can stamp it. Its
|
|
2158
|
+
* `ranges()` is handed to `reactiveCache.run` as a LAZY 4th argument (a
|
|
2159
|
+
* thunk, evaluated only after `run()` resolves), the same deferral
|
|
2160
|
+
* `deps` already relies on: the footprint is only complete once the
|
|
2161
|
+
* handler has actually run. Subclasses that also want range-precise
|
|
2162
|
+
* invalidation should pass `getCtxDbReadRangeHook()` as `onReadRange` on
|
|
2163
|
+
* the same `createShardCtxDb(...)` call — mirroring `onRead` above. A
|
|
2164
|
+
* subclass that only wires `onRead` still works: `ranges()` degrades to
|
|
2165
|
+
* `undefined` and every read is treated as a whole-table dependency, per
|
|
2166
|
+
* `ReactiveCache.run`'s own default. When `onReadRange` IS wired, a table
|
|
2167
|
+
* `footprint.ranges()` could not narrow (any by-id/scan read, or a
|
|
2168
|
+
* provable range mixed with one) still falls back to a whole-table
|
|
2169
|
+
* `SCAN_DEP`, stamped after `run()` resolves — see the fallback in this
|
|
2170
|
+
* method's body. Only a table read EXCLUSIVELY through provable ranges
|
|
2171
|
+
* gets range-precise invalidation instead.
|
|
2087
2172
|
*/
|
|
2088
2173
|
protected runCachedQuery<R>(functionPath: string, args: Record<string, unknown>, run: () => Promise<R>): Promise<R>;
|
|
2089
2174
|
/**
|
|
@@ -2099,8 +2184,30 @@ declare abstract class ShardDO {
|
|
|
2099
2184
|
* full-scan attribution — and unlike the tracker, it's collected even when
|
|
2100
2185
|
* the reactive cache is off, since the causal signal is independent of
|
|
2101
2186
|
* caching.
|
|
2187
|
+
*
|
|
2188
|
+
* It ALSO marks the table unnarrowable on {@link currentReadFootprint},
|
|
2189
|
+
* mirroring `executeSubscription`'s wiring (which hands a single
|
|
2190
|
+
* `ReadFootprint`'s `onRead`/`onReadRange` pair straight to `buildCtx`).
|
|
2191
|
+
* `ctx-db.ts`'s reader calls this `onRead` and `onReadRange` mutually
|
|
2192
|
+
* exclusively per read — a provable index slice fires ONLY `onReadRange`,
|
|
2193
|
+
* everything else (by-id, scan, an unprovable slice) fires ONLY this
|
|
2194
|
+
* `onRead` — so folding the footprint's `onRead` in here is exactly the
|
|
2195
|
+
* "read this table outside a range" signal {@link ReadFootprint.ranges}
|
|
2196
|
+
* needs to drop that table from the narrowed set.
|
|
2102
2197
|
*/
|
|
2103
2198
|
protected getCtxDbReadHook(): (table: string, idOrScan?: string) => void;
|
|
2199
|
+
/**
|
|
2200
|
+
* Returns an `onReadRange` callback suitable to hand to
|
|
2201
|
+
* `createShardCtxDb`'s `onReadRange` option, alongside `getCtxDbReadHook()`
|
|
2202
|
+
* as `onRead` on the same call — the pairing `executeSubscription` already
|
|
2203
|
+
* uses via `ReadFootprint`. Stamps the in-flight footprint (set by
|
|
2204
|
+
* `runCachedQuery`) when one exists and is a no-op otherwise, so subclasses
|
|
2205
|
+
* can wire this hook unconditionally regardless of whether the cache is
|
|
2206
|
+
* enabled. Without this wiring `runCachedQuery`'s ranges thunk always
|
|
2207
|
+
* observes an empty footprint and every cached query degrades to the prior
|
|
2208
|
+
* whole-table dependency — safe, just not range-precise.
|
|
2209
|
+
*/
|
|
2210
|
+
protected getCtxDbReadRangeHook(): (range: KeyRange) => void;
|
|
2104
2211
|
/**
|
|
2105
2212
|
* Read hook recording which declared indexes a query actually exercises.
|
|
2106
2213
|
* Two destinations, both stamped here so a single hook serves the live and
|
|
@@ -2143,6 +2250,20 @@ declare abstract class ShardDO {
|
|
|
2143
2250
|
* drain would take the refresh branch and lose its own ceiling entirely.
|
|
2144
2251
|
*/
|
|
2145
2252
|
protected subscriptionHeadroom(): TransactionHeadroomTracker;
|
|
2253
|
+
/**
|
|
2254
|
+
* A fresh budget for one alarm-driven work item — one external-source
|
|
2255
|
+
* table's tick, or one TTL sweep pass.
|
|
2256
|
+
*
|
|
2257
|
+
* Alarm work runs with no client waiting and no `/rpc` dispatch in flight,
|
|
2258
|
+
* so `transactionHeadroom()`'s per-dispatch tracker is `undefined` there —
|
|
2259
|
+
* leaving external-source ingest and TTL sweeps completely unmetered, the
|
|
2260
|
+
* exact isolate-exhaustion class the meter exists to bound. Handed to the
|
|
2261
|
+
* writer BY VALUE, the same pattern as `subscriptionHeadroom()` and for the
|
|
2262
|
+
* same reason: an ambient instance-field flag would race a concurrently
|
|
2263
|
+
* in-flight `/rpc` dispatch, or a sibling alarm work item, clearing or
|
|
2264
|
+
* substituting the wrong tracker mid-flight.
|
|
2265
|
+
*/
|
|
2266
|
+
protected alarmHeadroom(): TransactionHeadroomTracker;
|
|
2146
2267
|
/**
|
|
2147
2268
|
* Record that `table` was written during the current RPC. Wired into the
|
|
2148
2269
|
* db adapter's `broadcast` callback by the generated subclass so that
|
|
@@ -2440,12 +2561,25 @@ declare abstract class ShardDO {
|
|
|
2440
2561
|
* fields. `indexHits` is shaped exactly as the advisor's `AdvisorIndexHit`
|
|
2441
2562
|
* (`{ table, index, reads }`), so the studio passes it straight to
|
|
2442
2563
|
* `runLints({ ..., indexHits })` after summing the per-shard arrays.
|
|
2564
|
+
*
|
|
2565
|
+
* `subscriptionRefreshErrors` (DO-01) rides along the same way: an
|
|
2566
|
+
* in-memory-only lifetime count (no durable table, unlike `requests`/
|
|
2567
|
+
* `errors`), incremented by `recordSubscriptionRefreshError` whenever a live
|
|
2568
|
+
* query refresh or shape poke swallows a per-subscription error to protect
|
|
2569
|
+
* its siblings. The field is on the wire so it is queryable/testable now;
|
|
2570
|
+
* charting it in the studio's metrics panel is a follow-up.
|
|
2443
2571
|
*/
|
|
2444
2572
|
private collectMetrics;
|
|
2445
2573
|
/**
|
|
2446
2574
|
* Fold one dispatch into the per-function counters keyed by `functionPath`,
|
|
2447
2575
|
* creating the entry on first sight. `errorMessage` is supplied only when
|
|
2448
|
-
* the handler threw, in which case the failure counters advance too.
|
|
2576
|
+
* the handler threw, in which case the failure counters advance too. The
|
|
2577
|
+
* caller is expected to have already redacted `errorMessage` (via
|
|
2578
|
+
* `redactArgs`, the same `standardRules` treatment the request-log sinks
|
|
2579
|
+
* use) — this method persists/caches it verbatim into BOTH the durable
|
|
2580
|
+
* `__lunora_metrics.last_error_message` column and the in-memory
|
|
2581
|
+
* `functionStats.lastErrorMessage` served by `getFunctionStats`, so an
|
|
2582
|
+
* un-redacted message reaching here leaks into the Studio.
|
|
2449
2583
|
* `scannedTables` carries the tables the dispatch full-scanned (collected by
|
|
2450
2584
|
* `getCtxDbReadHook`), which advance the causal scan attribution.
|
|
2451
2585
|
* `indexHits` carries the declared indexes it exercised (collected by
|
|
@@ -2464,9 +2598,16 @@ declare abstract class ShardDO {
|
|
|
2464
2598
|
*/
|
|
2465
2599
|
private recordFunctionCall;
|
|
2466
2600
|
/**
|
|
2467
|
-
* Flush per-statement SQL samples accumulated during the
|
|
2468
|
-
* into the durable `__lunora_metrics_queries` table.
|
|
2469
|
-
* `recordFunctionCall` on both the success and error paths.
|
|
2601
|
+
* Flush the per-DISTINCT-statement SQL samples accumulated during the
|
|
2602
|
+
* current dispatch into the durable `__lunora_metrics_queries` table.
|
|
2603
|
+
* Called after `recordFunctionCall` on both the success and error paths.
|
|
2604
|
+
*
|
|
2605
|
+
* Already folded by the instrumented `sql` getter (see
|
|
2606
|
+
* `currentStmtSamples`), so this pays exactly one `recordQueryMetric` call
|
|
2607
|
+
* — one accumulator upsert plus one bucket upsert — per distinct statement
|
|
2608
|
+
* the dispatch ran, however many times it actually ran. `count` carries the
|
|
2609
|
+
* real execution count through so the durable `exec_count`/`total_duration_ms`
|
|
2610
|
+
* still reflect every execution, not just one.
|
|
2470
2611
|
*
|
|
2471
2612
|
* Best-effort: a SQL failure (e.g. a test double without a usable `sql`
|
|
2472
2613
|
* handle) must never fail the response, so every call is swallowed.
|
|
@@ -2492,8 +2633,8 @@ declare abstract class ShardDO {
|
|
|
2492
2633
|
/**
|
|
2493
2634
|
* Per-function coarse time-series served additively by the metrics RPC, so
|
|
2494
2635
|
* the studio can chart call/error history. Reads the durable
|
|
2495
|
-
* `__lunora_metrics_buckets` table; returns
|
|
2496
|
-
* unavailable so the response stays well-formed.
|
|
2636
|
+
* `__lunora_metrics_buckets` table; returns an empty, non-truncated result
|
|
2637
|
+
* when persistence is unavailable so the response stays well-formed.
|
|
2497
2638
|
*/
|
|
2498
2639
|
private collectFunctionMetricBuckets;
|
|
2499
2640
|
private maybeWarnRootSize;
|
|
@@ -2914,15 +3055,26 @@ declare abstract class ShardDO {
|
|
|
2914
3055
|
* @returns the result and table-dependency set for a read op, or `null` for a write/migration op
|
|
2915
3056
|
*/
|
|
2916
3057
|
private readAdminOp;
|
|
3058
|
+
/**
|
|
3059
|
+
* Shared shape behind `describeTables` and `listTablesIndexes`: read the
|
|
3060
|
+
* `tables` arg, run `lookup` (a cheap, synchronous, schema-sourced `this.*()`
|
|
3061
|
+
* hook) over each, and report the requested set as the read's table
|
|
3062
|
+
* dependency (or the {@link ADMIN_WILDCARD} sentinel when none were named).
|
|
3063
|
+
* Factored out so `readAdminTableSignal` states each batched RPC as one line
|
|
3064
|
+
* rather than duplicating the array-filter/fan-out shape per sibling.
|
|
3065
|
+
*/
|
|
3066
|
+
private batchedTableLookup;
|
|
2917
3067
|
/**
|
|
2918
3068
|
* Resolve the table-scoped introspection reads whose payload is a single
|
|
2919
3069
|
* `this.*()` lookup keyed by an optional `table` arg — `listTableIndexes`
|
|
2920
3070
|
* (declared indexes), `describeTable` (declared columns) and `migrationStatus`
|
|
2921
|
-
* (the migration ledger)
|
|
2922
|
-
* {@link
|
|
2923
|
-
*
|
|
2924
|
-
*
|
|
2925
|
-
*
|
|
3071
|
+
* (the migration ledger); plus their batched siblings `describeTables` and
|
|
3072
|
+
* `listTablesIndexes` (one RPC for N tables via {@link batchedTableLookup}).
|
|
3073
|
+
* The single-table pair carries its `table` (or the {@link ADMIN_WILDCARD}
|
|
3074
|
+
* sentinel when unscoped); `migrationStatus` is deployment-wide, so it always
|
|
3075
|
+
* carries the wildcard. Returns `undefined` for any other path so
|
|
3076
|
+
* {@link readAdminOp} falls through; folded into one helper to keep that
|
|
3077
|
+
* dispatcher under its complexity budget.
|
|
2926
3078
|
* @returns the read result and its table-dependency set, or `undefined` when the path is not owned by this resolver
|
|
2927
3079
|
*/
|
|
2928
3080
|
private readAdminTableSignal;
|
|
@@ -3220,6 +3372,32 @@ declare abstract class ShardDO {
|
|
|
3220
3372
|
* high-fanout shards rather than bolt a second, semantically-divergent dedup
|
|
3221
3373
|
* into this loop.
|
|
3222
3374
|
*/
|
|
3375
|
+
/**
|
|
3376
|
+
* Count and log a subscription-delivery error that its caller is about to
|
|
3377
|
+
* swallow (DO-01) — `refreshSubscriptions`' per-`(socket, sub)` catch and
|
|
3378
|
+
* `pokeShapeSubscribers`' per-socket catch both call this instead of a bare
|
|
3379
|
+
* `catch { continue; }`, so a live query or shape poke that throws
|
|
3380
|
+
* DETERMINISTICALLY on every flush is counted on `metrics.subscriptionRefreshErrors`
|
|
3381
|
+
* and shows up in the studio's Live Logs, rather than repeating silently for
|
|
3382
|
+
* the life of the socket. Factored out because both call sites need the
|
|
3383
|
+
* identical counter-then-best-effort-log shape, and duplicating it inline
|
|
3384
|
+
* pushed each closure over the file's cognitive-complexity budget.
|
|
3385
|
+
*
|
|
3386
|
+
* `lastTelemetrySink` (not a threaded `sink`) because both flush workers run
|
|
3387
|
+
* with no `ctx` — the same stand-in `flushTelemetry` uses.
|
|
3388
|
+
*
|
|
3389
|
+
* `error` is a caught INTERNAL failure surfaced from a background
|
|
3390
|
+
* refresh/poke pass, not a value a developer chose to log via `ctx.log` —
|
|
3391
|
+
* so `recordUserLog`'s "args are not redacted" contract (see its
|
|
3392
|
+
* docstring) does not apply here: a thrown value can carry an arbitrary
|
|
3393
|
+
* `cause`, stack, or custom own property (a handler can `throw
|
|
3394
|
+
* Object.assign(new Error(...), { row })`), and `args` rides raw into any
|
|
3395
|
+
* `sink.onLog` an operator has configured. Route it through the same
|
|
3396
|
+
* `toErrorBody` envelope every other error-crossing boundary in this file
|
|
3397
|
+
* uses (see `errorToResponse`, the shape-seed catches above) so only a
|
|
3398
|
+
* bounded `{ code, message }` — not the raw error — reaches the sink.
|
|
3399
|
+
*/
|
|
3400
|
+
private recordSubscriptionRefreshError;
|
|
3223
3401
|
private refreshSubscriptions;
|
|
3224
3402
|
/**
|
|
3225
3403
|
* Seed a freshly-registered subscription with its first value. Runs the
|
|
@@ -3309,9 +3487,10 @@ declare abstract class ShardDO {
|
|
|
3309
3487
|
* the results into the poke parts to send and the per-shape memo advances. A
|
|
3310
3488
|
* `.global()` shape (driven by the alarm poll loop, not this flush) and a shape
|
|
3311
3489
|
* whose table didn't change are skipped; a shape whose resolve/diff throws is
|
|
3312
|
-
*
|
|
3313
|
-
*
|
|
3314
|
-
*
|
|
3490
|
+
* counted and logged via `recordSubscriptionRefreshError` (DO-01) and skipped
|
|
3491
|
+
* with its memo unadvanced so a later flush retries. Empty diffs advance
|
|
3492
|
+
* unconditionally; part-bearing shapes advance only once the caller confirms
|
|
3493
|
+
* the poke was delivered.
|
|
3315
3494
|
*/
|
|
3316
3495
|
private collectShapePokeParts;
|
|
3317
3496
|
/**
|
|
@@ -3404,6 +3583,16 @@ declare abstract class ShardDO {
|
|
|
3404
3583
|
* default, since neither knows a more precise due time yet.
|
|
3405
3584
|
*/
|
|
3406
3585
|
private scheduleGlobalPoll;
|
|
3586
|
+
/**
|
|
3587
|
+
* Delete one expired row through {@link ShardDO.deleteRowThroughWriter},
|
|
3588
|
+
* absorbing a `TRANSACTION_LIMIT_EXCEEDED` as "batch full" rather than
|
|
3589
|
+
* letting it propagate — split out of {@link ShardDO.pollTtlSweeps} to keep
|
|
3590
|
+
* that method's own complexity down. Returns `true` when the limit was hit
|
|
3591
|
+
* (the caller must stop the sweep pass) and logs a `warn` recording it; `false`
|
|
3592
|
+
* on an ordinary successful delete. Any OTHER thrown error still propagates —
|
|
3593
|
+
* only the meter's own signal is contained here.
|
|
3594
|
+
*/
|
|
3595
|
+
private deleteExpiredTtlRow;
|
|
3407
3596
|
/**
|
|
3408
3597
|
* Record a contained shape-tier error (poll / poke / seed) into the DO's log
|
|
3409
3598
|
* ring without aborting the rest of the pass. The shape pipeline is a
|
|
@@ -3478,6 +3667,14 @@ declare abstract class ShardDO {
|
|
|
3478
3667
|
* persist its resume position and replay it as `sinceSeq` on reconnect
|
|
3479
3668
|
* (Pillar 1b). Omitted on shards without CDC, keeping the wire byte-identical
|
|
3480
3669
|
* to the pre-cursor format.
|
|
3670
|
+
*
|
|
3671
|
+
* `clientWatermark` is this socket's `socketClientWatermark(ws)` — read
|
|
3672
|
+
* ONCE by the caller and passed in, not recomputed here. A single
|
|
3673
|
+
* write-flush can call this method many times for the same socket (once
|
|
3674
|
+
* per affected subscription — see `refreshOne`), and the watermark
|
|
3675
|
+
* depends only on `ws`, never on `subId`/`outcome`, so recomputing it per
|
|
3676
|
+
* subscription was a redundant `SELECT … FROM __client_watermark` per
|
|
3677
|
+
* subscription per socket per flush.
|
|
3481
3678
|
*/
|
|
3482
3679
|
private pushSubscriptionData;
|
|
3483
3680
|
/**
|
|
@@ -3559,13 +3756,17 @@ declare abstract class ShardDO {
|
|
|
3559
3756
|
* harness double) or a pre-CDC shard, so callers degrade to the no-CDC path.
|
|
3560
3757
|
*/
|
|
3561
3758
|
private cdcEnabled;
|
|
3562
|
-
/**
|
|
3759
|
+
/**
|
|
3760
|
+
* Whether `ws` carries a credential whose expiry (stamped at upgrade) is
|
|
3761
|
+
* now past. Delegates to the shared boundary check `@lunora/agent`'s
|
|
3762
|
+
* voice DO uses for the same decision, so the two DOs can never disagree
|
|
3763
|
+
* about it.
|
|
3764
|
+
*/
|
|
3563
3765
|
private isSocketExpired;
|
|
3564
3766
|
/**
|
|
3565
|
-
*
|
|
3566
|
-
*
|
|
3567
|
-
*
|
|
3568
|
-
* gone) is swallowed — this must never escape the hibernation handlers.
|
|
3767
|
+
* Drop an expired-credential socket via the shared `TOKEN_EXPIRED`/`4001`
|
|
3768
|
+
* helper `@lunora/agent`'s voice DO also calls, so both DOs send the
|
|
3769
|
+
* client-facing wire shape from one place.
|
|
3569
3770
|
*/
|
|
3570
3771
|
private dropExpiredSocket;
|
|
3571
3772
|
/**
|