@minnowdb/core 0.10.0 → 0.10.2
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/engine/auto-store.d.ts +15 -3
- package/dist/engine/auto-store.js +48 -6
- package/dist/engine/client.js +23 -7
- package/dist/engine/database.js +347 -862
- package/dist/engine/index-terms.js +627 -0
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.js +2 -1
- package/dist/engine/live-maintenance.js +220 -0
- package/dist/engine/schema.js +2 -1
- package/dist/engine/sql-functions.js +3 -2
- package/dist/engine/sql-quote.js +6 -0
- package/dist/engine/vector.js +1 -3
- package/dist/engine/worker-host.js +2 -0
- package/dist/engine/worker-server.js +4 -5
- package/dist/engine/worker-store-auto.js +2 -2
- package/dist/engine/write-coordinator.js +21 -1
- package/dist/storage/indexeddb.d.ts +18 -0
- package/dist/storage/indexeddb.js +293 -211
- package/dist/storage/opfs/coordination-helpers.js +54 -0
- package/dist/storage/opfs/index.d.ts +1 -1
- package/dist/storage/opfs/index.js +3 -2
- package/dist/storage/opfs/leader.js +44 -5
- package/dist/storage/opfs/rpc.js +3 -1
- package/dist/storage/opfs/store.d.ts +12 -0
- package/dist/storage/opfs/store.js +59 -12
- package/dist/storage/toolkit/wal.js +16 -0
- package/dist/storage/toolkit/wire.js +3 -3
- package/dist/storage/types.d.ts +35 -4
- package/dist/storage/types.js +17 -4
- package/dist/testing/block-store-conformance.js +40 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +9 -0
- package/dist/testing/interaction-simulator.d.ts +319 -0
- package/dist/testing/interaction-simulator.js +1631 -0
- package/dist/transactions/index.d.ts +7 -0
- package/dist/transactions/index.js +17 -3
- package/package.json +4 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CompactionJobConflictError, assertCompactionOutputProvenance, compactionOutputSegmentIds, CompactionBacklogError, createManifest, createGarbageCollectionJobRecord, storeNames, advanceGarbageCollectionJobRecord as advanceGarbageCollectionJobRecordUnchecked, BlockReadBatchTooLargeError, activePostingStorageColumnIds, assertTempRunPageBatchLimits, assertStorageBulkReadItems, assertTransactionArtifactBatchLimits, boundedMaintenanceBatchItems, canonicalManifestChangedTableIds, catalogRecordRetainedBytes, manifestRecordRetainedReservationBytes, segmentRecordRetainedBytes, collectFtsPostings, ftsPostingQueryMatches, invalidateUncoveredFtsColumns, invalidateUncoveredSecondaryIndexes, GarbageCollectionJobConflictError, LeaseConflictError, LeaseExpiredError, LeaseOwnerConflictError, MAX_FTS_CANDIDATE_ROW_IDS, MAX_ACTIVE_UNIQUE_KEY_BUILDS, MAX_UNIQUE_KEY_BUILD_STAGED_BYTES, MAX_UNIQUE_KEY_BUILD_STAGED_BYTES_TOTAL, MAX_UNIQUE_KEY_BUILD_CHUNK_BYTES, MAX_UNIQUE_KEY_BUILD_TOKENS_PER_CHUNK, MAX_UNIQUE_KEY_BUILD_TTL_MS, MAX_FTS_BASE_CHUNKS, MAX_FTS_DELTA_CHUNKS, MAX_FTS_POSTINGS_PER_CHUNK, MAX_FTS_POSTING_ROW_IDS_PER_CHUNK, MAX_FTS_POSTING_TERM_CHARACTERS, MAX_FTS_TOKENS_PER_DOCUMENT, MAX_FTS_ORDERED_READ_BYTES, MAX_MANIFEST_BLOCK_PRESENCE_IDS, MAX_MANIFEST_RECORDS, MAX_MANIFEST_RETAINED_BYTES, MAX_BLOCK_READ_BATCH_BYTES, MAX_STORAGE_ID_CHARACTERS, MAX_LEASE_TTL_MS, MAX_ACTIVE_LEASES, MAX_ACTIVE_TRANSACTIONS, MAX_GLOBAL_STAGED_ARTIFACT_BYTES, MAX_GLOBAL_STAGED_BLOCKS, MAX_GLOBAL_STAGED_SEGMENTS, MAX_RETIRED_HISTORY_BYTES, MAX_PINNED_MANIFEST_VERSION_LAG, MAX_PINNED_RETIRED_BLOCKS, MAX_PINNED_RETIRED_BYTES, MAX_TERMINAL_TRANSACTION_RECORDS, MAX_ACTIVE_COMPACTION_JOBS, MAX_ACTIVE_GARBAGE_COLLECTION_JOBS, MAX_TERMINAL_COMPACTION_JOB_RECORDS, MAX_COMPLETED_GARBAGE_COLLECTION_JOB_RECORDS, MAX_CATALOG_RECORDS, MAX_CATALOG_RETAINED_BYTES, MAX_SEGMENT_RECORDS, MAX_SEGMENT_RETAINED_BYTES, MAX_ACTIVE_FTS_BASE_BUILDS, MAX_ACTIVE_SECONDARY_INDEX_BUILDS, MAX_ACCELERATOR_BUILD_STAGED_BYTES_TOTAL, MAX_ACCELERATOR_BUILD_STAGED_ENTRIES_TOTAL, MAX_POSTING_BUILD_TTL_MS, MAX_SNAPSHOT_SESSION_TTL_MS, MAX_SNAPSHOT_FRAME_BATCH_BYTES, MAX_SNAPSHOT_FRAME_BATCH_ITEMS, MAX_SNAPSHOT_METADATA_BATCH_BYTES, MAX_SNAPSHOT_METADATA_FRAME_BYTES, SNAPSHOT_FRAME_KINDS, MAX_LEVEL_ZERO_SEGMENTS, MAX_AUTO_INCREMENT_EXCLUSIVE_END, MAX_ROW_ID, MAX_ROW_ID_EXCLUSIVE_END, StorageCorruptionError, StorageFormatVersionError, IndexedDbSchemaUpgradeBlockedError, StorageResourceLimitError, SnapshotManifestMissingError, SnapshotImportConflictError, PostingBuildConflictError, validateTableForeignKey, TableInUseError, TableRecordConflictError, TempOwnerConflictError, MAX_TEMP_OWNER_TTL_MS, MAX_ACTIVE_TEMP_OWNERS, MAX_TEMP_RUNS_PER_OWNER, MAX_TEMP_PAGES_PER_OWNER, MAX_TEMP_RUNS_TOTAL, MAX_TEMP_PAGES_TOTAL, MAX_TEMP_BYTES_PER_OWNER, MAX_TEMP_BYTES_TOTAL, TransactionRecordConflictError, UniqueKeyConflictError, UniqueKeyBuildConflictError, UniqueIndexCoverageError, SchemaConflictError, normalizeCompactionJobRecord, normalizeGarbageCollectionJobRecord, normalizeSegmentRecord, updateCompactionJobRecord as updateCompactionJobRecordUnchecked, updateGarbageCollectionPlanningRecord, updateTransactionRecord as updateTransactionRecordUnchecked, validateColumnDefault, validateCatalogName, validateCanonicalManifestChangedTableIds, validateEnumValues, validateFtsCandidateLimit, validateFtsOrderedReadLimits, validateFtsReadVersion, validateFtsPostingQueries, validateStorageId, validateStorageDatabaseName, validateTableColumns, validateSecondaryIndexes, validateTableRecordBounds, secondaryIndexColumnIds, secondaryIndexWriteContractChanged, secondaryUniqueKeyNamespace, transactionCommitDeltaRetainedBytes, uniqueKeyBuildChunkRetainedBytes, WriteConflictError } from "./types.js";
|
|
1
|
+
import { CompactionJobConflictError, assertCompactionOutputProvenance, compactionOutputSegmentIds, CompactionBacklogError, createManifest, createGarbageCollectionJobRecord, storeNames, advanceGarbageCollectionJobRecord as advanceGarbageCollectionJobRecordUnchecked, BlockReadBatchTooLargeError, activePostingStorageColumnIds, assertTempRunPageBatchLimits, assertStorageBulkReadItems, assertTransactionArtifactBatchLimits, boundedMaintenanceBatchItems, canonicalManifestChangedTableIds, catalogRecordRetainedBytes, manifestRecordRetainedReservationBytes, segmentRecordRetainedBytes, collectFtsPostings, ftsPostingQueryMatches, invalidateUncoveredFtsColumns, invalidateUncoveredSecondaryIndexes, GarbageCollectionJobConflictError, LeaseConflictError, LeaseExpiredError, LeaseOwnerConflictError, MAX_FTS_CANDIDATE_ROW_IDS, MAX_ACTIVE_UNIQUE_KEY_BUILDS, MAX_UNIQUE_KEY_BUILD_STAGED_BYTES, MAX_UNIQUE_KEY_BUILD_STAGED_BYTES_TOTAL, MAX_UNIQUE_KEY_BUILD_CHUNK_BYTES, MAX_UNIQUE_KEY_BUILD_TOKENS_PER_CHUNK, MAX_UNIQUE_KEY_BUILD_TTL_MS, MAX_FTS_BASE_CHUNKS, MAX_FTS_DELTA_CHUNKS, MAX_FTS_POSTINGS_PER_CHUNK, MAX_FTS_POSTING_ROW_IDS_PER_CHUNK, MAX_FTS_POSTING_TERM_CHARACTERS, MAX_FTS_TOKENS_PER_DOCUMENT, MAX_FTS_ORDERED_READ_BYTES, MAX_MANIFEST_BLOCK_PRESENCE_IDS, MAX_MANIFEST_RECORDS, MAX_MANIFEST_RETAINED_BYTES, MAX_BLOCK_READ_BATCH_BYTES, MAX_STORAGE_ID_CHARACTERS, MAX_LEASE_TTL_MS, MAX_ACTIVE_LEASES, MAX_ACTIVE_TRANSACTIONS, MAX_GLOBAL_STAGED_ARTIFACT_BYTES, MAX_GLOBAL_STAGED_BLOCKS, MAX_GLOBAL_STAGED_SEGMENTS, MAX_RETIRED_HISTORY_BYTES, MAX_PINNED_MANIFEST_VERSION_LAG, MAX_PINNED_RETIRED_BLOCKS, MAX_PINNED_RETIRED_BYTES, MAX_TERMINAL_TRANSACTION_RECORDS, MAX_ACTIVE_COMPACTION_JOBS, MAX_ACTIVE_GARBAGE_COLLECTION_JOBS, MAX_TERMINAL_COMPACTION_JOB_RECORDS, MAX_COMPLETED_GARBAGE_COLLECTION_JOB_RECORDS, MAX_CATALOG_RECORDS, MAX_CATALOG_RETAINED_BYTES, MAX_SEGMENT_RECORDS, MAX_SEGMENT_RETAINED_BYTES, MAX_ACTIVE_FTS_BASE_BUILDS, MAX_ACTIVE_SECONDARY_INDEX_BUILDS, MAX_ACCELERATOR_BUILD_STAGED_BYTES_TOTAL, MAX_ACCELERATOR_BUILD_STAGED_ENTRIES_TOTAL, MAX_POSTING_BUILD_TTL_MS, MAX_SNAPSHOT_SESSION_TTL_MS, MAX_SNAPSHOT_FRAME_BATCH_BYTES, MAX_SNAPSHOT_FRAME_BATCH_ITEMS, MAX_SNAPSHOT_METADATA_BATCH_BYTES, MAX_SNAPSHOT_METADATA_FRAME_BYTES, SNAPSHOT_FRAME_KINDS, MAX_LEVEL_ZERO_SEGMENTS, MAX_AUTO_INCREMENT_EXCLUSIVE_END, MAX_ROW_ID, MAX_ROW_ID_EXCLUSIVE_END, StorageCorruptionError, StorageFormatVersionError, StorageUnresponsiveError, IndexedDbSchemaUpgradeBlockedError, StorageResourceLimitError, SnapshotManifestMissingError, SnapshotImportConflictError, PostingBuildConflictError, validateTableForeignKey, TableInUseError, TableRecordConflictError, TempOwnerConflictError, MAX_TEMP_OWNER_TTL_MS, MAX_ACTIVE_TEMP_OWNERS, MAX_TEMP_RUNS_PER_OWNER, MAX_TEMP_PAGES_PER_OWNER, MAX_TEMP_RUNS_TOTAL, MAX_TEMP_PAGES_TOTAL, MAX_TEMP_BYTES_PER_OWNER, MAX_TEMP_BYTES_TOTAL, TransactionRecordConflictError, UniqueKeyConflictError, UniqueKeyBuildConflictError, UniqueIndexCoverageError, SchemaConflictError, normalizeCompactionJobRecord, normalizeGarbageCollectionJobRecord, normalizeSegmentRecord, updateCompactionJobRecord as updateCompactionJobRecordUnchecked, updateGarbageCollectionPlanningRecord, updateTransactionRecord as updateTransactionRecordUnchecked, validateColumnDefault, validateCatalogName, validateCanonicalManifestChangedTableIds, validateEnumValues, validateFtsCandidateLimit, validateFtsOrderedReadLimits, validateFtsReadVersion, validateFtsPostingQueries, validateStorageId, validateStorageDatabaseName, validateTableColumns, validateSecondaryIndexes, validateTableRecordBounds, secondaryIndexColumnIds, secondaryIndexWriteContractChanged, secondaryUniqueKeyNamespace, transactionCommitDeltaRetainedBytes, uniqueKeyBuildChunkRetainedBytes, WriteConflictError } from "./types.js";
|
|
2
2
|
import { crc32, verifyStoredBlock } from "../block-format/index.js";
|
|
3
3
|
import { dateIsoString } from "../date-value.js";
|
|
4
4
|
import { decodeSnapshotMetadataItems, encodeSnapshotMetadataPage, extendSnapshotFrameStreamChecksum, prepareSnapshotFrameStreamHeader, snapshotFrameEnvelopeParts, snapshotFrameStreamHeaderIdentity } from "./snapshot-stream.js";
|
|
@@ -129,11 +129,18 @@ class IndexedDbBlockStore {
|
|
|
129
129
|
#snapshotPeakRetainedItems = 0;
|
|
130
130
|
#snapshotPeakRetainedBytes = 0;
|
|
131
131
|
#closed = false;
|
|
132
|
-
|
|
132
|
+
#unresponsive;
|
|
133
|
+
#stallGuard;
|
|
134
|
+
constructor(db, durability, uniqueKeyCacheBytes, unresponsiveAfterMs) {
|
|
133
135
|
this.#db = db;
|
|
134
136
|
this.liveQueryChannelName = `minnowdb-live:indexeddb:${db.name}`;
|
|
135
137
|
this.#durability = durability;
|
|
136
138
|
this.#uniqueKeyCacheBytes = uniqueKeyCacheBytes;
|
|
139
|
+
this.#stallGuard = new ConnectionStallGuard(db.name, unresponsiveAfterMs, (error) => {
|
|
140
|
+
this.#unresponsive = error;
|
|
141
|
+
this.close();
|
|
142
|
+
});
|
|
143
|
+
stallGuards.set(db, this.#stallGuard);
|
|
137
144
|
db.addEventListener("versionchange", () => {
|
|
138
145
|
this.close();
|
|
139
146
|
});
|
|
@@ -144,6 +151,10 @@ class IndexedDbBlockStore {
|
|
|
144
151
|
if (!Number.isSafeInteger(uniqueKeyCacheBytes) || uniqueKeyCacheBytes < 0) {
|
|
145
152
|
throw new RangeError("Unique-key cache bytes must be a non-negative whole number");
|
|
146
153
|
}
|
|
154
|
+
const unresponsiveAfterMs = options.unresponsiveAfterMs ?? INDEXEDDB_UNRESPONSIVE_AFTER_MS;
|
|
155
|
+
if (!Number.isSafeInteger(unresponsiveAfterMs) || unresponsiveAfterMs <= 0) {
|
|
156
|
+
throw new RangeError("The unresponsive deadline must be a positive whole number of ms");
|
|
157
|
+
}
|
|
147
158
|
const factory = options.indexedDB ?? getGlobalIndexedDb();
|
|
148
159
|
if (factory === void 0)
|
|
149
160
|
throw new Error("IndexedDB is unavailable");
|
|
@@ -177,7 +188,7 @@ class IndexedDbBlockStore {
|
|
|
177
188
|
db = await openDatabaseRequest(request, (event) => {
|
|
178
189
|
abandoned = true;
|
|
179
190
|
return new IndexedDbSchemaUpgradeBlockedError(options.name, event.oldVersion, event.newVersion ?? SCHEMA_VERSION);
|
|
180
|
-
});
|
|
191
|
+
}, options.name, unresponsiveAfterMs);
|
|
181
192
|
} catch (error) {
|
|
182
193
|
if (upgradeError !== void 0)
|
|
183
194
|
throw upgradeError;
|
|
@@ -187,7 +198,7 @@ class IndexedDbBlockStore {
|
|
|
187
198
|
}
|
|
188
199
|
throw error;
|
|
189
200
|
}
|
|
190
|
-
const store = new IndexedDbBlockStore(db, options.durability ?? "strict", uniqueKeyCacheBytes);
|
|
201
|
+
const store = new IndexedDbBlockStore(db, options.durability ?? "strict", uniqueKeyCacheBytes, unresponsiveAfterMs);
|
|
191
202
|
try {
|
|
192
203
|
await validateCurrentIndexedDbSchema(db);
|
|
193
204
|
await store.#validateCatalogResourceLedger();
|
|
@@ -253,8 +264,7 @@ class IndexedDbBlockStore {
|
|
|
253
264
|
return result;
|
|
254
265
|
} catch (error) {
|
|
255
266
|
abortIfActive(transaction);
|
|
256
|
-
await
|
|
257
|
-
throw error;
|
|
267
|
+
throw await refusalBehindAbort(transaction, error);
|
|
258
268
|
}
|
|
259
269
|
}
|
|
260
270
|
async readManifestBlock(version, id) {
|
|
@@ -288,8 +298,7 @@ class IndexedDbBlockStore {
|
|
|
288
298
|
return bytes;
|
|
289
299
|
} catch (error) {
|
|
290
300
|
abortIfActive(transaction);
|
|
291
|
-
await
|
|
292
|
-
throw error;
|
|
301
|
+
throw await refusalBehindAbort(transaction, error);
|
|
293
302
|
}
|
|
294
303
|
}
|
|
295
304
|
async hasManifestBlocks(version, ids) {
|
|
@@ -314,8 +323,7 @@ class IndexedDbBlockStore {
|
|
|
314
323
|
return result;
|
|
315
324
|
} catch (error) {
|
|
316
325
|
abortIfActive(transaction);
|
|
317
|
-
await
|
|
318
|
-
throw error;
|
|
326
|
+
throw await refusalBehindAbort(transaction, error);
|
|
319
327
|
}
|
|
320
328
|
}
|
|
321
329
|
async listManifestBlockPage(input) {
|
|
@@ -346,8 +354,7 @@ class IndexedDbBlockStore {
|
|
|
346
354
|
};
|
|
347
355
|
} catch (error) {
|
|
348
356
|
abortIfActive(transaction);
|
|
349
|
-
await
|
|
350
|
-
throw error;
|
|
357
|
+
throw await refusalBehindAbort(transaction, error);
|
|
351
358
|
}
|
|
352
359
|
}
|
|
353
360
|
async listRetiredManifestBlockPage(input) {
|
|
@@ -372,8 +379,7 @@ class IndexedDbBlockStore {
|
|
|
372
379
|
};
|
|
373
380
|
} catch (error) {
|
|
374
381
|
abortIfActive(transaction);
|
|
375
|
-
await
|
|
376
|
-
throw error;
|
|
382
|
+
throw await refusalBehindAbort(transaction, error);
|
|
377
383
|
}
|
|
378
384
|
}
|
|
379
385
|
async putTempRunPage(page) {
|
|
@@ -392,8 +398,7 @@ class IndexedDbBlockStore {
|
|
|
392
398
|
await transactionDone(transaction);
|
|
393
399
|
} catch (error) {
|
|
394
400
|
abortIfActive(transaction);
|
|
395
|
-
await
|
|
396
|
-
throw error;
|
|
401
|
+
throw await refusalBehindAbort(transaction, error);
|
|
397
402
|
}
|
|
398
403
|
}
|
|
399
404
|
async getTempRunPage(ownerId, runId, pageIndex) {
|
|
@@ -412,8 +417,7 @@ class IndexedDbBlockStore {
|
|
|
412
417
|
await transactionDone(transaction);
|
|
413
418
|
} catch (error) {
|
|
414
419
|
abortIfActive(transaction);
|
|
415
|
-
await
|
|
416
|
-
throw error;
|
|
420
|
+
throw await refusalBehindAbort(transaction, error);
|
|
417
421
|
}
|
|
418
422
|
}
|
|
419
423
|
async removeTempOwner(ownerId) {
|
|
@@ -425,8 +429,7 @@ class IndexedDbBlockStore {
|
|
|
425
429
|
await transactionDone(transaction);
|
|
426
430
|
} catch (error) {
|
|
427
431
|
abortIfActive(transaction);
|
|
428
|
-
await
|
|
429
|
-
throw error;
|
|
432
|
+
throw await refusalBehindAbort(transaction, error);
|
|
430
433
|
}
|
|
431
434
|
}
|
|
432
435
|
async createTempOwner(record) {
|
|
@@ -448,8 +451,7 @@ class IndexedDbBlockStore {
|
|
|
448
451
|
await transactionDone(transaction);
|
|
449
452
|
} catch (error) {
|
|
450
453
|
abortIfActive(transaction);
|
|
451
|
-
await
|
|
452
|
-
throw error;
|
|
454
|
+
throw await refusalBehindAbort(transaction, error);
|
|
453
455
|
}
|
|
454
456
|
}
|
|
455
457
|
async getTempOwner(ownerId) {
|
|
@@ -589,8 +591,7 @@ class IndexedDbBlockStore {
|
|
|
589
591
|
await transactionDone(transaction);
|
|
590
592
|
} catch (error) {
|
|
591
593
|
abortIfActive(transaction);
|
|
592
|
-
await
|
|
593
|
-
throw error;
|
|
594
|
+
throw await refusalBehindAbort(transaction, error);
|
|
594
595
|
}
|
|
595
596
|
}
|
|
596
597
|
async getTable(id) {
|
|
@@ -780,8 +781,7 @@ class IndexedDbBlockStore {
|
|
|
780
781
|
return updated;
|
|
781
782
|
} catch (error) {
|
|
782
783
|
abortIfActive(transaction);
|
|
783
|
-
await
|
|
784
|
-
throw error;
|
|
784
|
+
throw await refusalBehindAbort(transaction, error);
|
|
785
785
|
}
|
|
786
786
|
}
|
|
787
787
|
async beginUniqueKeyBuild(input) {
|
|
@@ -836,8 +836,7 @@ class IndexedDbBlockStore {
|
|
|
836
836
|
return structuredClone(record);
|
|
837
837
|
} catch (error) {
|
|
838
838
|
abortIfActive(transaction);
|
|
839
|
-
await
|
|
840
|
-
throw error;
|
|
839
|
+
throw await refusalBehindAbort(transaction, error);
|
|
841
840
|
}
|
|
842
841
|
}
|
|
843
842
|
async getUniqueKeyBuild(buildId) {
|
|
@@ -872,8 +871,7 @@ class IndexedDbBlockStore {
|
|
|
872
871
|
return structuredClone(record);
|
|
873
872
|
} catch (error) {
|
|
874
873
|
abortIfActive(transaction);
|
|
875
|
-
await
|
|
876
|
-
throw error;
|
|
874
|
+
throw await refusalBehindAbort(transaction, error);
|
|
877
875
|
}
|
|
878
876
|
}
|
|
879
877
|
async appendUniqueKeyBuildChunk(input) {
|
|
@@ -946,8 +944,7 @@ class IndexedDbBlockStore {
|
|
|
946
944
|
return structuredClone(record);
|
|
947
945
|
} catch (error) {
|
|
948
946
|
abortIfActive(transaction);
|
|
949
|
-
await
|
|
950
|
-
throw error;
|
|
947
|
+
throw await refusalBehindAbort(transaction, error);
|
|
951
948
|
}
|
|
952
949
|
}
|
|
953
950
|
async finishUniqueKeyBuild(input) {
|
|
@@ -1039,8 +1036,7 @@ class IndexedDbBlockStore {
|
|
|
1039
1036
|
return structuredClone(updated);
|
|
1040
1037
|
} catch (error) {
|
|
1041
1038
|
abortIfActive(transaction);
|
|
1042
|
-
await
|
|
1043
|
-
throw error;
|
|
1039
|
+
throw await refusalBehindAbort(transaction, error);
|
|
1044
1040
|
}
|
|
1045
1041
|
}
|
|
1046
1042
|
async abortUniqueKeyBuild(input) {
|
|
@@ -1067,8 +1063,7 @@ class IndexedDbBlockStore {
|
|
|
1067
1063
|
await transactionDone(transaction);
|
|
1068
1064
|
} catch (error) {
|
|
1069
1065
|
abortIfActive(transaction);
|
|
1070
|
-
await
|
|
1071
|
-
throw error;
|
|
1066
|
+
throw await refusalBehindAbort(transaction, error);
|
|
1072
1067
|
}
|
|
1073
1068
|
await this.#cleanupUniqueKeyBuildArtifacts(input.buildId);
|
|
1074
1069
|
return true;
|
|
@@ -1093,8 +1088,7 @@ class IndexedDbBlockStore {
|
|
|
1093
1088
|
}
|
|
1094
1089
|
} catch (error) {
|
|
1095
1090
|
abortIfActive(transaction);
|
|
1096
|
-
await
|
|
1097
|
-
throw error;
|
|
1091
|
+
throw await refusalBehindAbort(transaction, error);
|
|
1098
1092
|
}
|
|
1099
1093
|
}
|
|
1100
1094
|
async dropTable(input) {
|
|
@@ -1181,14 +1175,13 @@ class IndexedDbBlockStore {
|
|
|
1181
1175
|
this.#journalCache = void 0;
|
|
1182
1176
|
if (this.#uniqueKeyCache?.tableId === input.tableId || this.#uniqueKeyCache?.tableId.startsWith(`${input.tableId}\0secondary-index\0`) === true) {
|
|
1183
1177
|
this.#uniqueKeyCache = void 0;
|
|
1184
|
-
} else
|
|
1185
|
-
this.#
|
|
1178
|
+
} else {
|
|
1179
|
+
this.#carryUniqueKeyCache(input.expectedManifestVersion, manifest.version);
|
|
1186
1180
|
}
|
|
1187
1181
|
return manifest;
|
|
1188
1182
|
} catch (error) {
|
|
1189
1183
|
abortIfActive(transaction);
|
|
1190
|
-
await
|
|
1191
|
-
throw error;
|
|
1184
|
+
throw await refusalBehindAbort(transaction, error);
|
|
1192
1185
|
}
|
|
1193
1186
|
}
|
|
1194
1187
|
async dropTableColumn(input) {
|
|
@@ -1320,13 +1313,11 @@ class IndexedDbBlockStore {
|
|
|
1320
1313
|
await transactionDone(transaction);
|
|
1321
1314
|
this.#manifestCache = void 0;
|
|
1322
1315
|
this.#journalCache = void 0;
|
|
1323
|
-
|
|
1324
|
-
this.#uniqueKeyCache.version = manifest.version;
|
|
1316
|
+
this.#carryUniqueKeyCache(input.expectedManifestVersion, manifest.version);
|
|
1325
1317
|
return manifest;
|
|
1326
1318
|
} catch (error) {
|
|
1327
1319
|
abortIfActive(transaction);
|
|
1328
|
-
await
|
|
1329
|
-
throw error;
|
|
1320
|
+
throw await refusalBehindAbort(transaction, error);
|
|
1330
1321
|
}
|
|
1331
1322
|
}
|
|
1332
1323
|
async writeFtsBase(tableId, columnId, input) {
|
|
@@ -1462,8 +1453,7 @@ class IndexedDbBlockStore {
|
|
|
1462
1453
|
await transactionDone(transaction);
|
|
1463
1454
|
} catch (error) {
|
|
1464
1455
|
abortIfActive(transaction);
|
|
1465
|
-
await
|
|
1466
|
-
throw error;
|
|
1456
|
+
throw await refusalBehindAbort(transaction, error);
|
|
1467
1457
|
}
|
|
1468
1458
|
}
|
|
1469
1459
|
async writeFtsBaseBuildChunk(input) {
|
|
@@ -1881,8 +1871,7 @@ class IndexedDbBlockStore {
|
|
|
1881
1871
|
};
|
|
1882
1872
|
} catch (error) {
|
|
1883
1873
|
abortIfActive(transaction);
|
|
1884
|
-
await
|
|
1885
|
-
throw error;
|
|
1874
|
+
throw await refusalBehindAbort(transaction, error);
|
|
1886
1875
|
}
|
|
1887
1876
|
}
|
|
1888
1877
|
async removeAbortedSegment(segmentId, expectedTransactionId) {
|
|
@@ -1958,8 +1947,7 @@ class IndexedDbBlockStore {
|
|
|
1958
1947
|
return true;
|
|
1959
1948
|
} catch (error) {
|
|
1960
1949
|
abortIfActive(transaction);
|
|
1961
|
-
await
|
|
1962
|
-
throw error;
|
|
1950
|
+
throw await refusalBehindAbort(transaction, error);
|
|
1963
1951
|
}
|
|
1964
1952
|
}
|
|
1965
1953
|
async adoptAbortedSegment(input) {
|
|
@@ -2100,8 +2088,7 @@ class IndexedDbBlockStore {
|
|
|
2100
2088
|
return structuredClone(updatedReplacement);
|
|
2101
2089
|
} catch (error) {
|
|
2102
2090
|
abortIfActive(transaction);
|
|
2103
|
-
await
|
|
2104
|
-
throw error;
|
|
2091
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2105
2092
|
}
|
|
2106
2093
|
}
|
|
2107
2094
|
async reserveRowIds(tableId, count) {
|
|
@@ -2123,8 +2110,7 @@ class IndexedDbBlockStore {
|
|
|
2123
2110
|
return { start, endExclusive };
|
|
2124
2111
|
} catch (error) {
|
|
2125
2112
|
abortIfActive(transaction);
|
|
2126
|
-
await
|
|
2127
|
-
throw error;
|
|
2113
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2128
2114
|
}
|
|
2129
2115
|
}
|
|
2130
2116
|
async reserveAutoIncrement(tableId, columnId, count, atLeast) {
|
|
@@ -2145,8 +2131,17 @@ class IndexedDbBlockStore {
|
|
|
2145
2131
|
return { start, endExclusive };
|
|
2146
2132
|
} catch (error) {
|
|
2147
2133
|
abortIfActive(transaction);
|
|
2148
|
-
await
|
|
2149
|
-
|
|
2134
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
#carryUniqueKeyCache(basedOn, version) {
|
|
2138
|
+
const cache = this.#uniqueKeyCache;
|
|
2139
|
+
if (cache === void 0 || cache.version === version)
|
|
2140
|
+
return;
|
|
2141
|
+
if (basedOn !== null && basedOn !== void 0 && cache.version === basedOn) {
|
|
2142
|
+
cache.version = version;
|
|
2143
|
+
} else {
|
|
2144
|
+
this.#uniqueKeyCache = void 0;
|
|
2150
2145
|
}
|
|
2151
2146
|
}
|
|
2152
2147
|
async getExistingUniqueKeys(tableId, keyTokens) {
|
|
@@ -2255,8 +2250,7 @@ class IndexedDbBlockStore {
|
|
|
2255
2250
|
};
|
|
2256
2251
|
} catch (error) {
|
|
2257
2252
|
abortIfActive(transaction);
|
|
2258
|
-
await
|
|
2259
|
-
throw error;
|
|
2253
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2260
2254
|
}
|
|
2261
2255
|
}
|
|
2262
2256
|
async getCurrentManifest() {
|
|
@@ -2393,8 +2387,7 @@ class IndexedDbBlockStore {
|
|
|
2393
2387
|
};
|
|
2394
2388
|
} catch (error) {
|
|
2395
2389
|
abortIfActive(transaction);
|
|
2396
|
-
await
|
|
2397
|
-
throw error;
|
|
2390
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2398
2391
|
}
|
|
2399
2392
|
}
|
|
2400
2393
|
async createTransaction(record) {
|
|
@@ -2440,8 +2433,7 @@ class IndexedDbBlockStore {
|
|
|
2440
2433
|
await transactionDone(transaction);
|
|
2441
2434
|
} catch (error) {
|
|
2442
2435
|
abortIfActive(transaction);
|
|
2443
|
-
await
|
|
2444
|
-
throw error;
|
|
2436
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2445
2437
|
}
|
|
2446
2438
|
}
|
|
2447
2439
|
async getTransaction(id) {
|
|
@@ -2511,15 +2503,14 @@ class IndexedDbBlockStore {
|
|
|
2511
2503
|
});
|
|
2512
2504
|
}
|
|
2513
2505
|
if (addedBlocks.length > 0 || addedSegments.length > 0) {
|
|
2514
|
-
appendTransactionJournalChunks(transaction, stored,
|
|
2506
|
+
appendTransactionJournalChunks(transaction, stored, await readTransactionJournalTail(transaction, stored), addedBlocks, addedSegments);
|
|
2515
2507
|
}
|
|
2516
2508
|
putStoredTransactionRecord(transaction, storedTransactionRecord(updated));
|
|
2517
2509
|
await transactionDone(transaction);
|
|
2518
2510
|
return updated;
|
|
2519
2511
|
} catch (error) {
|
|
2520
2512
|
abortIfActive(transaction);
|
|
2521
|
-
await
|
|
2522
|
-
throw error;
|
|
2513
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2523
2514
|
}
|
|
2524
2515
|
}
|
|
2525
2516
|
async renewTransaction(input) {
|
|
@@ -2550,8 +2541,7 @@ class IndexedDbBlockStore {
|
|
|
2550
2541
|
return true;
|
|
2551
2542
|
} catch (error) {
|
|
2552
2543
|
abortIfActive(transaction);
|
|
2553
|
-
await
|
|
2554
|
-
throw error;
|
|
2544
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2555
2545
|
}
|
|
2556
2546
|
}
|
|
2557
2547
|
async abortTransactionIfExpired(input) {
|
|
@@ -2588,8 +2578,7 @@ class IndexedDbBlockStore {
|
|
|
2588
2578
|
return structuredClone(updated);
|
|
2589
2579
|
} catch (error) {
|
|
2590
2580
|
abortIfActive(transaction);
|
|
2591
|
-
await
|
|
2592
|
-
throw error;
|
|
2581
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2593
2582
|
}
|
|
2594
2583
|
}
|
|
2595
2584
|
async stageTransactionArtifacts(input) {
|
|
@@ -2694,8 +2683,7 @@ class IndexedDbBlockStore {
|
|
|
2694
2683
|
return transactionRecordWithJournal(updated, journal.blockIds, journal.segmentIds);
|
|
2695
2684
|
} catch (error) {
|
|
2696
2685
|
abortIfActive(transaction);
|
|
2697
|
-
await
|
|
2698
|
-
throw error;
|
|
2686
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2699
2687
|
}
|
|
2700
2688
|
}
|
|
2701
2689
|
async #journaledIds(transaction, stored, tail) {
|
|
@@ -2849,8 +2837,7 @@ class IndexedDbBlockStore {
|
|
|
2849
2837
|
return structuredClone(updated);
|
|
2850
2838
|
} catch (error) {
|
|
2851
2839
|
abortIfActive(transaction);
|
|
2852
|
-
await
|
|
2853
|
-
throw error;
|
|
2840
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2854
2841
|
}
|
|
2855
2842
|
}
|
|
2856
2843
|
async commitTransaction(input) {
|
|
@@ -2881,8 +2868,7 @@ class IndexedDbBlockStore {
|
|
|
2881
2868
|
return outcome.manifest;
|
|
2882
2869
|
} catch (error) {
|
|
2883
2870
|
abortIfActive(transaction);
|
|
2884
|
-
await
|
|
2885
|
-
throw error;
|
|
2871
|
+
throw await refusalBehindAbort(transaction, error);
|
|
2886
2872
|
}
|
|
2887
2873
|
}
|
|
2888
2874
|
async writeTransaction(input) {
|
|
@@ -3014,8 +3000,7 @@ class IndexedDbBlockStore {
|
|
|
3014
3000
|
return outcome.manifest;
|
|
3015
3001
|
} catch (error) {
|
|
3016
3002
|
abortIfActive(transaction);
|
|
3017
|
-
await
|
|
3018
|
-
throw error;
|
|
3003
|
+
throw await refusalBehindAbort(transaction, error);
|
|
3019
3004
|
}
|
|
3020
3005
|
}
|
|
3021
3006
|
async #commitInTransaction(transaction, record, journal, input) {
|
|
@@ -3076,15 +3061,11 @@ class IndexedDbBlockStore {
|
|
|
3076
3061
|
if (pendingRemovedBlock !== void 0) {
|
|
3077
3062
|
throw new Error(`Cannot supersede a pending block: ${pendingRemovedBlock}`);
|
|
3078
3063
|
}
|
|
3079
|
-
let baseBlockIdSet;
|
|
3080
3064
|
const removedMembership = await manifestBlockMembershipInTransaction(catalog, input.expectedManifestVersion, removedBlockIds);
|
|
3081
3065
|
const invalidRemovedIndex = removedMembership.findIndex((present) => !present);
|
|
3082
3066
|
if (invalidRemovedIndex >= 0) {
|
|
3083
3067
|
throw new Error(`Cannot supersede a block outside the transaction snapshot: ${removedBlockIds[invalidRemovedIndex] ?? ""}`);
|
|
3084
3068
|
}
|
|
3085
|
-
if ((input.levelZeroSegmentLimits?.length ?? 0) > 0) {
|
|
3086
|
-
baseBlockIdSet = await resolveManifestBlockSetInTransaction(catalog, input.expectedManifestVersion);
|
|
3087
|
-
}
|
|
3088
3069
|
if (removedBlockIds.length > 0) {
|
|
3089
3070
|
await assertCompactionRetirementInTransaction(transaction, record, input, removedBlockIds);
|
|
3090
3071
|
}
|
|
@@ -3106,7 +3087,7 @@ class IndexedDbBlockStore {
|
|
|
3106
3087
|
throw new Error(`Segment ${foreignSegment.id} belongs to another transaction`);
|
|
3107
3088
|
}
|
|
3108
3089
|
await assertCompactionOutputSegmentsInTransaction(transaction, record, input.compactionJobId, pendingSegments);
|
|
3109
|
-
await assertLevelZeroSegmentLimits(transaction, input.levelZeroSegmentLimits ?? [], pendingSegments,
|
|
3090
|
+
await assertLevelZeroSegmentLimits(transaction, input.levelZeroSegmentLimits ?? [], pendingSegments, input.expectedManifestVersion, pendingTable);
|
|
3110
3091
|
const uniqueKeyEntries = input.uniqueKeyChanges ?? [];
|
|
3111
3092
|
const coveredUniqueNamespaces = new Set(uniqueKeyEntries.map((entry) => entry.tableId));
|
|
3112
3093
|
const changedTableIds = /* @__PURE__ */ new Set([
|
|
@@ -3509,13 +3490,11 @@ class IndexedDbBlockStore {
|
|
|
3509
3490
|
} : void 0;
|
|
3510
3491
|
} else if (this.#uniqueKeyCache?.tableId === uniqueKeyChanges.tableId) {
|
|
3511
3492
|
this.#uniqueKeyCache = void 0;
|
|
3512
|
-
} else
|
|
3513
|
-
this.#
|
|
3493
|
+
} else {
|
|
3494
|
+
this.#carryUniqueKeyCache(input.expectedManifestVersion, manifest.version);
|
|
3514
3495
|
}
|
|
3515
|
-
} else
|
|
3516
|
-
this.#
|
|
3517
|
-
} else if (this.#uniqueKeyCache !== void 0) {
|
|
3518
|
-
this.#uniqueKeyCache.version = manifest.version;
|
|
3496
|
+
} else {
|
|
3497
|
+
this.#carryUniqueKeyCache(input.expectedManifestVersion, manifest.version);
|
|
3519
3498
|
}
|
|
3520
3499
|
this.#manifestCache = void 0;
|
|
3521
3500
|
this.#journalCache = void 0;
|
|
@@ -3547,8 +3526,7 @@ class IndexedDbBlockStore {
|
|
|
3547
3526
|
await transactionDone(transaction);
|
|
3548
3527
|
} catch (error) {
|
|
3549
3528
|
abortIfActive(transaction);
|
|
3550
|
-
await
|
|
3551
|
-
throw error;
|
|
3529
|
+
throw await refusalBehindAbort(transaction, error);
|
|
3552
3530
|
}
|
|
3553
3531
|
}
|
|
3554
3532
|
async getLease(id) {
|
|
@@ -3627,8 +3605,7 @@ class IndexedDbBlockStore {
|
|
|
3627
3605
|
return structuredClone(renewed);
|
|
3628
3606
|
} catch (error) {
|
|
3629
3607
|
abortIfActive(transaction);
|
|
3630
|
-
await
|
|
3631
|
-
throw error;
|
|
3608
|
+
throw await refusalBehindAbort(transaction, error);
|
|
3632
3609
|
}
|
|
3633
3610
|
}
|
|
3634
3611
|
async moveLease(input) {
|
|
@@ -3669,8 +3646,7 @@ class IndexedDbBlockStore {
|
|
|
3669
3646
|
return structuredClone(moved);
|
|
3670
3647
|
} catch (error) {
|
|
3671
3648
|
abortIfActive(transaction);
|
|
3672
|
-
await
|
|
3673
|
-
throw error;
|
|
3649
|
+
throw await refusalBehindAbort(transaction, error);
|
|
3674
3650
|
}
|
|
3675
3651
|
}
|
|
3676
3652
|
async removeLeaseIfExpired(id, expectedRevision, expiresAtCutoff) {
|
|
@@ -3937,8 +3913,7 @@ class IndexedDbBlockStore {
|
|
|
3937
3913
|
return true;
|
|
3938
3914
|
} catch (error) {
|
|
3939
3915
|
abortIfActive(transaction);
|
|
3940
|
-
await
|
|
3941
|
-
throw error;
|
|
3916
|
+
throw await refusalBehindAbort(transaction, error);
|
|
3942
3917
|
}
|
|
3943
3918
|
}
|
|
3944
3919
|
async createGarbageCollectionJob(input) {
|
|
@@ -3953,13 +3928,13 @@ class IndexedDbBlockStore {
|
|
|
3953
3928
|
const quota = await readMaintenanceQuota(gcStore);
|
|
3954
3929
|
let activeGarbageCollectionJobs;
|
|
3955
3930
|
if (record.state !== "completed") {
|
|
3956
|
-
activeGarbageCollectionJobs = checkedQuotaIncrement(quota.activeGarbageCollectionJobs, "Active garbage collection job count");
|
|
3957
|
-
assertMaintenanceLimit("garbage collection job", activeGarbageCollectionJobs, MAX_ACTIVE_GARBAGE_COLLECTION_JOBS);
|
|
3958
3931
|
const markerValue = await requestResult(gcStore.get(ACTIVE_GARBAGE_COLLECTION_KEY));
|
|
3959
3932
|
if (markerValue !== void 0) {
|
|
3960
3933
|
const marker = asActiveGarbageCollectionMarker(markerValue);
|
|
3961
|
-
throw new
|
|
3934
|
+
throw new GarbageCollectionJobConflictError(marker.jobId, record.revision, null);
|
|
3962
3935
|
}
|
|
3936
|
+
activeGarbageCollectionJobs = checkedQuotaIncrement(quota.activeGarbageCollectionJobs, "Active garbage collection job count");
|
|
3937
|
+
assertMaintenanceLimit("garbage collection job", activeGarbageCollectionJobs, MAX_ACTIVE_GARBAGE_COLLECTION_JOBS);
|
|
3963
3938
|
}
|
|
3964
3939
|
await assertGarbageCollectionCandidateProvenanceInTransaction(transaction, record);
|
|
3965
3940
|
if (record.state !== "completed") {
|
|
@@ -3978,8 +3953,7 @@ class IndexedDbBlockStore {
|
|
|
3978
3953
|
return structuredClone(record);
|
|
3979
3954
|
} catch (error) {
|
|
3980
3955
|
abortIfActive(transaction);
|
|
3981
|
-
await
|
|
3982
|
-
throw error;
|
|
3956
|
+
throw await refusalBehindAbort(transaction, error);
|
|
3983
3957
|
}
|
|
3984
3958
|
}
|
|
3985
3959
|
async updateGarbageCollectionPlanning(input) {
|
|
@@ -4003,12 +3977,14 @@ class IndexedDbBlockStore {
|
|
|
4003
3977
|
candidateTransactionIds: input.candidateTransactionIds ?? []
|
|
4004
3978
|
});
|
|
4005
3979
|
gcStore.put(garbageCollectionJobEnvelope(updated), key);
|
|
3980
|
+
if (updated.state === "completed" && current.state !== "completed") {
|
|
3981
|
+
await releaseGarbageCollectionAdmission(gcStore);
|
|
3982
|
+
}
|
|
4006
3983
|
await transactionDone(transaction);
|
|
4007
3984
|
return structuredClone(updated);
|
|
4008
3985
|
} catch (error) {
|
|
4009
3986
|
abortIfActive(transaction);
|
|
4010
|
-
await
|
|
4011
|
-
throw error;
|
|
3987
|
+
throw await refusalBehindAbort(transaction, error);
|
|
4012
3988
|
}
|
|
4013
3989
|
}
|
|
4014
3990
|
async getGarbageCollectionJob(id) {
|
|
@@ -4228,17 +4204,8 @@ class IndexedDbBlockStore {
|
|
|
4228
4204
|
updatedAt: input.updatedAt
|
|
4229
4205
|
});
|
|
4230
4206
|
gcStore.put(garbageCollectionJobEnvelope(updated), key);
|
|
4231
|
-
if (updated.state === "completed")
|
|
4232
|
-
|
|
4233
|
-
const completedGarbageCollectionJobs = checkedQuotaIncrement(quota.completedGarbageCollectionJobs, "Completed garbage collection job count");
|
|
4234
|
-
assertMaintenanceLimit("completed garbage collection job", completedGarbageCollectionJobs, MAX_COMPLETED_GARBAGE_COLLECTION_JOB_RECORDS);
|
|
4235
|
-
gcStore.put({
|
|
4236
|
-
...quota,
|
|
4237
|
-
activeGarbageCollectionJobs: checkedQuotaDecrement(quota.activeGarbageCollectionJobs, "active garbage collection job count"),
|
|
4238
|
-
completedGarbageCollectionJobs
|
|
4239
|
-
}, MAINTENANCE_QUOTA_KEY);
|
|
4240
|
-
await requestResult(gcStore.delete(ACTIVE_GARBAGE_COLLECTION_KEY));
|
|
4241
|
-
}
|
|
4207
|
+
if (updated.state === "completed")
|
|
4208
|
+
await releaseGarbageCollectionAdmission(gcStore);
|
|
4242
4209
|
await transactionDone(transaction);
|
|
4243
4210
|
return {
|
|
4244
4211
|
job: structuredClone(updated),
|
|
@@ -4259,8 +4226,7 @@ class IndexedDbBlockStore {
|
|
|
4259
4226
|
};
|
|
4260
4227
|
} catch (error) {
|
|
4261
4228
|
abortIfActive(transaction);
|
|
4262
|
-
await
|
|
4263
|
-
throw error;
|
|
4229
|
+
throw await refusalBehindAbort(transaction, error);
|
|
4264
4230
|
}
|
|
4265
4231
|
}
|
|
4266
4232
|
async removePrunedManifestRecords(maxItems) {
|
|
@@ -4322,8 +4288,7 @@ class IndexedDbBlockStore {
|
|
|
4322
4288
|
return removed;
|
|
4323
4289
|
} catch (error) {
|
|
4324
4290
|
abortIfActive(transaction);
|
|
4325
|
-
await
|
|
4326
|
-
throw error;
|
|
4291
|
+
throw await refusalBehindAbort(transaction, error);
|
|
4327
4292
|
}
|
|
4328
4293
|
}
|
|
4329
4294
|
async removeGarbageCollectionJob(id) {
|
|
@@ -4426,8 +4391,7 @@ class IndexedDbBlockStore {
|
|
|
4426
4391
|
};
|
|
4427
4392
|
} catch (error) {
|
|
4428
4393
|
abortIfActive(transaction);
|
|
4429
|
-
await
|
|
4430
|
-
throw error;
|
|
4394
|
+
throw await refusalBehindAbort(transaction, error);
|
|
4431
4395
|
}
|
|
4432
4396
|
}
|
|
4433
4397
|
async getStorageStats() {
|
|
@@ -5619,8 +5583,7 @@ class IndexedDbBlockStore {
|
|
|
5619
5583
|
return { sessionId, ownerId: input.ownerId, expiresAt: input.expiresAt, header };
|
|
5620
5584
|
} catch (error) {
|
|
5621
5585
|
abortIfActive(transaction);
|
|
5622
|
-
await
|
|
5623
|
-
throw error;
|
|
5586
|
+
throw await refusalBehindAbort(transaction, error);
|
|
5624
5587
|
}
|
|
5625
5588
|
}
|
|
5626
5589
|
async readSnapshotExportFrame(input) {
|
|
@@ -5696,8 +5659,7 @@ class IndexedDbBlockStore {
|
|
|
5696
5659
|
return frame;
|
|
5697
5660
|
} catch (error) {
|
|
5698
5661
|
abortIfActive(transaction);
|
|
5699
|
-
await
|
|
5700
|
-
throw error;
|
|
5662
|
+
throw await refusalBehindAbort(transaction, error);
|
|
5701
5663
|
}
|
|
5702
5664
|
}
|
|
5703
5665
|
async closeSnapshotFrameExport(input) {
|
|
@@ -5725,8 +5687,7 @@ class IndexedDbBlockStore {
|
|
|
5725
5687
|
return true;
|
|
5726
5688
|
} catch (error) {
|
|
5727
5689
|
abortIfActive(transaction);
|
|
5728
|
-
await
|
|
5729
|
-
throw error;
|
|
5690
|
+
throw await refusalBehindAbort(transaction, error);
|
|
5730
5691
|
}
|
|
5731
5692
|
}
|
|
5732
5693
|
async beginSnapshotFrameImport(input) {
|
|
@@ -5857,8 +5818,7 @@ class IndexedDbBlockStore {
|
|
|
5857
5818
|
return snapshotFrameImportSession(marker);
|
|
5858
5819
|
} catch (error) {
|
|
5859
5820
|
abortIfActive(transaction);
|
|
5860
|
-
await
|
|
5861
|
-
throw error;
|
|
5821
|
+
throw await refusalBehindAbort(transaction, error);
|
|
5862
5822
|
}
|
|
5863
5823
|
}
|
|
5864
5824
|
async renewSnapshotFrameImport(input) {
|
|
@@ -5876,8 +5836,7 @@ class IndexedDbBlockStore {
|
|
|
5876
5836
|
return snapshotFrameImportSession(renewed);
|
|
5877
5837
|
} catch (error) {
|
|
5878
5838
|
abortIfActive(transaction);
|
|
5879
|
-
await
|
|
5880
|
-
throw error;
|
|
5839
|
+
throw await refusalBehindAbort(transaction, error);
|
|
5881
5840
|
}
|
|
5882
5841
|
}
|
|
5883
5842
|
async appendSnapshotImportFrames(input) {
|
|
@@ -5998,8 +5957,7 @@ class IndexedDbBlockStore {
|
|
|
5998
5957
|
return snapshotFrameImportSession(marker);
|
|
5999
5958
|
} catch (error) {
|
|
6000
5959
|
abortIfActive(transaction);
|
|
6001
|
-
await
|
|
6002
|
-
throw error;
|
|
5960
|
+
throw await refusalBehindAbort(transaction, error);
|
|
6003
5961
|
}
|
|
6004
5962
|
}
|
|
6005
5963
|
async finishSnapshotFrameImport(input) {
|
|
@@ -6055,8 +6013,7 @@ class IndexedDbBlockStore {
|
|
|
6055
6013
|
this.#journalCache = void 0;
|
|
6056
6014
|
} catch (error) {
|
|
6057
6015
|
abortIfActive(transaction);
|
|
6058
|
-
await
|
|
6059
|
-
throw error;
|
|
6016
|
+
throw await refusalBehindAbort(transaction, error);
|
|
6060
6017
|
}
|
|
6061
6018
|
}
|
|
6062
6019
|
async cancelSnapshotFrameImport(input) {
|
|
@@ -6099,8 +6056,7 @@ class IndexedDbBlockStore {
|
|
|
6099
6056
|
};
|
|
6100
6057
|
} catch (error) {
|
|
6101
6058
|
abortIfActive(transaction);
|
|
6102
|
-
await
|
|
6103
|
-
throw error;
|
|
6059
|
+
throw await refusalBehindAbort(transaction, error);
|
|
6104
6060
|
}
|
|
6105
6061
|
}
|
|
6106
6062
|
close() {
|
|
@@ -6111,6 +6067,7 @@ class IndexedDbBlockStore {
|
|
|
6111
6067
|
this.#uniqueKeyCache = void 0;
|
|
6112
6068
|
this.#manifestCache = void 0;
|
|
6113
6069
|
this.#journalCache = void 0;
|
|
6070
|
+
this.#stallGuard.dispose();
|
|
6114
6071
|
this.#db.close();
|
|
6115
6072
|
}
|
|
6116
6073
|
_residentStateForTests() {
|
|
@@ -6157,8 +6114,7 @@ class IndexedDbBlockStore {
|
|
|
6157
6114
|
return true;
|
|
6158
6115
|
} catch (error) {
|
|
6159
6116
|
abortIfActive(transaction);
|
|
6160
|
-
await
|
|
6161
|
-
throw error;
|
|
6117
|
+
throw await refusalBehindAbort(transaction, error);
|
|
6162
6118
|
}
|
|
6163
6119
|
}
|
|
6164
6120
|
}
|
|
@@ -6174,8 +6130,7 @@ class IndexedDbBlockStore {
|
|
|
6174
6130
|
return;
|
|
6175
6131
|
} catch (error) {
|
|
6176
6132
|
abortIfActive(transaction);
|
|
6177
|
-
await
|
|
6178
|
-
throw error;
|
|
6133
|
+
throw await refusalBehindAbort(transaction, error);
|
|
6179
6134
|
}
|
|
6180
6135
|
}
|
|
6181
6136
|
}
|
|
@@ -6205,8 +6160,7 @@ class IndexedDbBlockStore {
|
|
|
6205
6160
|
await transactionDone(transaction);
|
|
6206
6161
|
} catch (error) {
|
|
6207
6162
|
abortIfActive(transaction);
|
|
6208
|
-
await
|
|
6209
|
-
throw error;
|
|
6163
|
+
throw await refusalBehindAbort(transaction, error);
|
|
6210
6164
|
}
|
|
6211
6165
|
if (cleanup)
|
|
6212
6166
|
await this.#cleanupUniqueKeyBuildArtifacts(buildId);
|
|
@@ -6237,8 +6191,7 @@ class IndexedDbBlockStore {
|
|
|
6237
6191
|
return;
|
|
6238
6192
|
} catch (error) {
|
|
6239
6193
|
abortIfActive(transaction);
|
|
6240
|
-
await
|
|
6241
|
-
throw error;
|
|
6194
|
+
throw await refusalBehindAbort(transaction, error);
|
|
6242
6195
|
}
|
|
6243
6196
|
}
|
|
6244
6197
|
}
|
|
@@ -6373,8 +6326,7 @@ class IndexedDbBlockStore {
|
|
|
6373
6326
|
await transactionDone(transaction);
|
|
6374
6327
|
} catch (error) {
|
|
6375
6328
|
abortIfActive(transaction);
|
|
6376
|
-
await
|
|
6377
|
-
throw error;
|
|
6329
|
+
throw await refusalBehindAbort(transaction, error);
|
|
6378
6330
|
}
|
|
6379
6331
|
}
|
|
6380
6332
|
async #cleanupFtsRetirementPage() {
|
|
@@ -6390,11 +6342,12 @@ class IndexedDbBlockStore {
|
|
|
6390
6342
|
await transactionDone(transaction);
|
|
6391
6343
|
} catch (error) {
|
|
6392
6344
|
abortIfActive(transaction);
|
|
6393
|
-
await
|
|
6394
|
-
throw error;
|
|
6345
|
+
throw await refusalBehindAbort(transaction, error);
|
|
6395
6346
|
}
|
|
6396
6347
|
}
|
|
6397
6348
|
#transaction(stores, mode, options = {}) {
|
|
6349
|
+
if (this.#unresponsive !== void 0)
|
|
6350
|
+
throw this.#unresponsive;
|
|
6398
6351
|
if (this.#closed)
|
|
6399
6352
|
throw new Error("This IndexedDB store connection is closed");
|
|
6400
6353
|
const requested = typeof stores === "string" ? [stores] : stores;
|
|
@@ -6516,49 +6469,156 @@ async function readIndexedDbVersion(factory, name) {
|
|
|
6516
6469
|
return null;
|
|
6517
6470
|
}
|
|
6518
6471
|
}
|
|
6519
|
-
|
|
6472
|
+
const INDEXEDDB_UNRESPONSIVE_AFTER_MS = 3e4;
|
|
6473
|
+
class ConnectionStallGuard {
|
|
6474
|
+
#databaseName;
|
|
6475
|
+
#afterMs;
|
|
6476
|
+
#onTrip;
|
|
6477
|
+
#waiting = /* @__PURE__ */ new Set();
|
|
6478
|
+
#timer;
|
|
6479
|
+
#tripped;
|
|
6480
|
+
#disposed = false;
|
|
6481
|
+
constructor(databaseName, afterMs, onTrip) {
|
|
6482
|
+
this.#databaseName = databaseName;
|
|
6483
|
+
this.#afterMs = afterMs;
|
|
6484
|
+
this.#onTrip = onTrip;
|
|
6485
|
+
}
|
|
6486
|
+
wait(reject) {
|
|
6487
|
+
if (this.#tripped !== void 0) {
|
|
6488
|
+
const tripped = this.#tripped;
|
|
6489
|
+
queueMicrotask(() => reject(tripped));
|
|
6490
|
+
return () => void 0;
|
|
6491
|
+
}
|
|
6492
|
+
if (this.#disposed)
|
|
6493
|
+
return () => void 0;
|
|
6494
|
+
this.#waiting.add(reject);
|
|
6495
|
+
this.#arm();
|
|
6496
|
+
let released = false;
|
|
6497
|
+
return () => {
|
|
6498
|
+
if (released)
|
|
6499
|
+
return;
|
|
6500
|
+
released = true;
|
|
6501
|
+
this.#waiting.delete(reject);
|
|
6502
|
+
this.#progress();
|
|
6503
|
+
};
|
|
6504
|
+
}
|
|
6505
|
+
dispose() {
|
|
6506
|
+
this.#disposed = true;
|
|
6507
|
+
this.#waiting.clear();
|
|
6508
|
+
this.#disarm();
|
|
6509
|
+
}
|
|
6510
|
+
#arm() {
|
|
6511
|
+
if (this.#timer !== void 0 || this.#waiting.size === 0)
|
|
6512
|
+
return;
|
|
6513
|
+
this.#timer = setTimeout(() => {
|
|
6514
|
+
this.#timer = void 0;
|
|
6515
|
+
this.#trip();
|
|
6516
|
+
}, this.#afterMs);
|
|
6517
|
+
this.#timer.unref?.();
|
|
6518
|
+
}
|
|
6519
|
+
#disarm() {
|
|
6520
|
+
if (this.#timer === void 0)
|
|
6521
|
+
return;
|
|
6522
|
+
clearTimeout(this.#timer);
|
|
6523
|
+
this.#timer = void 0;
|
|
6524
|
+
}
|
|
6525
|
+
#progress() {
|
|
6526
|
+
if (this.#tripped !== void 0)
|
|
6527
|
+
return;
|
|
6528
|
+
this.#disarm();
|
|
6529
|
+
this.#arm();
|
|
6530
|
+
}
|
|
6531
|
+
#trip() {
|
|
6532
|
+
if (this.#tripped !== void 0)
|
|
6533
|
+
return;
|
|
6534
|
+
const error = new StorageUnresponsiveError("indexeddb", this.#databaseName, this.#afterMs);
|
|
6535
|
+
this.#tripped = error;
|
|
6536
|
+
const waiting = [...this.#waiting];
|
|
6537
|
+
this.#waiting.clear();
|
|
6538
|
+
this.#onTrip(error);
|
|
6539
|
+
for (const reject of waiting)
|
|
6540
|
+
reject(error);
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
const stallGuards = /* @__PURE__ */ new WeakMap();
|
|
6544
|
+
function stallGuardFor(db) {
|
|
6545
|
+
return db === null || db === void 0 ? void 0 : stallGuards.get(db);
|
|
6546
|
+
}
|
|
6547
|
+
function openDatabaseRequest(request, blockedError, databaseName, unresponsiveAfterMs) {
|
|
6520
6548
|
return new Promise((resolve, reject) => {
|
|
6521
6549
|
let settled = false;
|
|
6550
|
+
const timer = setTimeout(() => {
|
|
6551
|
+
if (settled)
|
|
6552
|
+
return;
|
|
6553
|
+
settled = true;
|
|
6554
|
+
reject(new StorageUnresponsiveError("indexeddb", databaseName, unresponsiveAfterMs));
|
|
6555
|
+
}, unresponsiveAfterMs);
|
|
6556
|
+
timer.unref?.();
|
|
6557
|
+
const settle = () => {
|
|
6558
|
+
if (settled)
|
|
6559
|
+
return false;
|
|
6560
|
+
settled = true;
|
|
6561
|
+
clearTimeout(timer);
|
|
6562
|
+
return true;
|
|
6563
|
+
};
|
|
6522
6564
|
request.addEventListener("success", () => {
|
|
6523
|
-
if (
|
|
6565
|
+
if (!settle()) {
|
|
6524
6566
|
request.result.close();
|
|
6525
6567
|
return;
|
|
6526
6568
|
}
|
|
6527
|
-
settled = true;
|
|
6528
6569
|
resolve(request.result);
|
|
6529
6570
|
}, { once: true });
|
|
6530
6571
|
request.addEventListener("error", () => {
|
|
6531
|
-
if (
|
|
6572
|
+
if (!settle())
|
|
6532
6573
|
return;
|
|
6533
|
-
settled = true;
|
|
6534
6574
|
reject(request.error ?? new Error("IndexedDB open failed"));
|
|
6535
6575
|
}, { once: true });
|
|
6536
6576
|
request.addEventListener("blocked", (event) => {
|
|
6537
|
-
if (
|
|
6577
|
+
if (!settle())
|
|
6538
6578
|
return;
|
|
6539
|
-
settled = true;
|
|
6540
6579
|
reject(blockedError(event));
|
|
6541
6580
|
}, { once: true });
|
|
6542
6581
|
});
|
|
6543
6582
|
}
|
|
6544
6583
|
function requestResult(request) {
|
|
6584
|
+
const guard = stallGuardFor(request.transaction?.db);
|
|
6545
6585
|
return new Promise((resolve, reject) => {
|
|
6546
|
-
|
|
6547
|
-
request.addEventListener("
|
|
6586
|
+
const release = guard?.wait(reject);
|
|
6587
|
+
request.addEventListener("success", () => {
|
|
6588
|
+
release?.();
|
|
6589
|
+
resolve(request.result);
|
|
6590
|
+
}, { once: true });
|
|
6591
|
+
request.addEventListener("error", () => {
|
|
6592
|
+
release?.();
|
|
6593
|
+
reject(request.error ?? new Error("IndexedDB request failed"));
|
|
6594
|
+
}, {
|
|
6548
6595
|
once: true
|
|
6549
6596
|
});
|
|
6550
6597
|
});
|
|
6551
6598
|
}
|
|
6552
6599
|
function readCursorPage(store, limit, decode, acceptKey, seekKey) {
|
|
6600
|
+
const guard = stallGuardFor(store.transaction.db);
|
|
6553
6601
|
return new Promise((resolve, reject) => {
|
|
6554
6602
|
const records = [];
|
|
6555
6603
|
const request = store.openCursor();
|
|
6556
6604
|
let seekPending = seekKey !== void 0;
|
|
6557
|
-
|
|
6605
|
+
let release = guard?.wait(reject);
|
|
6606
|
+
const settle = (value) => {
|
|
6607
|
+
release?.();
|
|
6608
|
+
release = void 0;
|
|
6609
|
+
resolve(value);
|
|
6610
|
+
};
|
|
6611
|
+
request.onerror = () => {
|
|
6612
|
+
release?.();
|
|
6613
|
+
release = void 0;
|
|
6614
|
+
reject(request.error ?? new Error("IndexedDB cursor failed"));
|
|
6615
|
+
};
|
|
6558
6616
|
request.onsuccess = () => {
|
|
6617
|
+
release?.();
|
|
6618
|
+
release = guard?.wait(reject);
|
|
6559
6619
|
const cursor = request.result;
|
|
6560
6620
|
if (cursor === null || records.length === limit) {
|
|
6561
|
-
|
|
6621
|
+
settle(records);
|
|
6562
6622
|
return;
|
|
6563
6623
|
}
|
|
6564
6624
|
try {
|
|
@@ -6572,10 +6632,12 @@ function readCursorPage(store, limit, decode, acceptKey, seekKey) {
|
|
|
6572
6632
|
if (acceptKey(cursor.key))
|
|
6573
6633
|
records.push(decode(cursor.value, cursor.key));
|
|
6574
6634
|
if (records.length === limit)
|
|
6575
|
-
|
|
6635
|
+
settle(records);
|
|
6576
6636
|
else
|
|
6577
6637
|
cursor.continue();
|
|
6578
6638
|
} catch (error) {
|
|
6639
|
+
release?.();
|
|
6640
|
+
release = void 0;
|
|
6579
6641
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
6580
6642
|
}
|
|
6581
6643
|
};
|
|
@@ -7035,9 +7097,17 @@ function transactionDone(transaction) {
|
|
|
7035
7097
|
const existing = transactionCompletions.get(transaction);
|
|
7036
7098
|
if (existing !== void 0)
|
|
7037
7099
|
return existing;
|
|
7100
|
+
const guard = stallGuardFor(transaction.db);
|
|
7038
7101
|
const done = new Promise((resolve, reject) => {
|
|
7039
|
-
|
|
7040
|
-
transaction.addEventListener("
|
|
7102
|
+
const release = guard?.wait(reject);
|
|
7103
|
+
transaction.addEventListener("complete", () => {
|
|
7104
|
+
release?.();
|
|
7105
|
+
resolve();
|
|
7106
|
+
}, { once: true });
|
|
7107
|
+
transaction.addEventListener("abort", () => {
|
|
7108
|
+
release?.();
|
|
7109
|
+
reject(transaction.error ?? new Error("Transaction aborted"));
|
|
7110
|
+
}, {
|
|
7041
7111
|
once: true
|
|
7042
7112
|
});
|
|
7043
7113
|
});
|
|
@@ -7050,6 +7120,14 @@ async function ignoreAbort(transaction) {
|
|
|
7050
7120
|
} catch {
|
|
7051
7121
|
}
|
|
7052
7122
|
}
|
|
7123
|
+
async function refusalBehindAbort(transaction, error) {
|
|
7124
|
+
await ignoreAbort(transaction);
|
|
7125
|
+
const refusal = transaction.error;
|
|
7126
|
+
if (refusal !== null && error instanceof DOMException && error.name === "AbortError") {
|
|
7127
|
+
return refusal;
|
|
7128
|
+
}
|
|
7129
|
+
return error;
|
|
7130
|
+
}
|
|
7053
7131
|
function corruption(location, message) {
|
|
7054
7132
|
return new StorageCorruptionError("indexeddb", location, message);
|
|
7055
7133
|
}
|
|
@@ -8929,8 +9007,12 @@ function asTableRecord(value, location = "catalog/table") {
|
|
|
8929
9007
|
"defaultValue",
|
|
8930
9008
|
"backfill",
|
|
8931
9009
|
"enumValues",
|
|
8932
|
-
"hidden"
|
|
9010
|
+
"hidden",
|
|
9011
|
+
"generatedValue"
|
|
8933
9012
|
], `${location}/columns/${String(index)}`);
|
|
9013
|
+
if (isRecord(column.generatedValue)) {
|
|
9014
|
+
assertKnownFields(column.generatedValue, ["kind", "sql"], `${location}/columns/${String(index)}/generatedValue`);
|
|
9015
|
+
}
|
|
8934
9016
|
if (isRecord(column.sqlDomain)) {
|
|
8935
9017
|
const domainFields = column.sqlDomain.kind === "numeric" ? ["kind", "precision", "scale"] : column.sqlDomain.kind === "array" ? ["kind", "element"] : column.sqlDomain.kind === "enum" ? ["kind", "name", "values"] : ["kind"];
|
|
8936
9018
|
assertKnownFields(column.sqlDomain, domainFields, `${location}/columns/${String(index)}/sqlDomain`);
|
|
@@ -9447,7 +9529,7 @@ async function assertCompactionOutputSegmentsInTransaction(transaction, committi
|
|
|
9447
9529
|
}));
|
|
9448
9530
|
assertCompactionOutputProvenance(job, table, committingTransaction, sourceSegments, pendingSegments);
|
|
9449
9531
|
}
|
|
9450
|
-
async function assertLevelZeroSegmentLimits(transaction, limits, pendingSegments,
|
|
9532
|
+
async function assertLevelZeroSegmentLimits(transaction, limits, pendingSegments, version, pendingTable) {
|
|
9451
9533
|
const pendingTables = new Set(pendingSegments.filter((segment) => segment.level === 0).map((segment) => segment.tableId));
|
|
9452
9534
|
if (limits.length !== pendingTables.size) {
|
|
9453
9535
|
throw new TypeError("Level-zero segment limits must exactly cover pending level-zero tables");
|
|
@@ -9472,7 +9554,7 @@ async function assertLevelZeroSegmentLimits(transaction, limits, pendingSegments
|
|
|
9472
9554
|
if (table === void 0) {
|
|
9473
9555
|
throw new Error(`Level-zero segment limit references missing table: ${entry.tableId}`);
|
|
9474
9556
|
}
|
|
9475
|
-
const existing = await countVisibleLevelZeroSegments(segmentIndex, transaction.objectStore("transactions"), entry.tableId
|
|
9557
|
+
const existing = await countVisibleLevelZeroSegments(segmentIndex, transaction.objectStore("transactions"), catalog, version, entry.tableId);
|
|
9476
9558
|
const added = pendingSegments.reduce((count2, segment) => count2 + (segment.tableId === entry.tableId && segment.level === 0 ? 1 : 0), 0);
|
|
9477
9559
|
const count = existing + added;
|
|
9478
9560
|
if (count > entry.limit) {
|
|
@@ -9480,66 +9562,54 @@ async function assertLevelZeroSegmentLimits(transaction, limits, pendingSegments
|
|
|
9480
9562
|
}
|
|
9481
9563
|
}
|
|
9482
9564
|
}
|
|
9483
|
-
function countVisibleLevelZeroSegments(index, transactions,
|
|
9484
|
-
|
|
9485
|
-
const
|
|
9486
|
-
let count = 0;
|
|
9565
|
+
async function countVisibleLevelZeroSegments(index, transactions, catalog, version, tableId) {
|
|
9566
|
+
const candidates = await new Promise((resolve, reject) => {
|
|
9567
|
+
const found = [];
|
|
9487
9568
|
const request = index.openCursor(tableId);
|
|
9488
9569
|
request.onerror = () => reject(request.error ?? new Error("IndexedDB segment cursor failed"));
|
|
9489
9570
|
request.onsuccess = () => {
|
|
9490
9571
|
const cursor = request.result;
|
|
9491
9572
|
if (cursor === null) {
|
|
9492
|
-
resolve(
|
|
9573
|
+
resolve(found);
|
|
9493
9574
|
return;
|
|
9494
9575
|
}
|
|
9495
|
-
let segment;
|
|
9496
9576
|
try {
|
|
9497
|
-
segment = asSegmentRecord(cursor.value);
|
|
9577
|
+
const segment = asSegmentRecord(cursor.value);
|
|
9498
9578
|
if (segment.id !== cursor.primaryKey || segment.tableId !== tableId) {
|
|
9499
9579
|
throw corruption(`segments/${segment.id}`, "table index does not match its record");
|
|
9500
9580
|
}
|
|
9501
|
-
if (segment.level
|
|
9502
|
-
|
|
9503
|
-
|
|
9504
|
-
}
|
|
9505
|
-
const blockIds = segmentBlockIds(segment);
|
|
9506
|
-
const visibleBlockCount = blockIds.filter((id) => currentBlockIds.has(id)).length;
|
|
9507
|
-
if (visibleBlockCount > 0 && visibleBlockCount < blockIds.length) {
|
|
9508
|
-
throw corruption(`segments/${segment.id}`, "only part of the segment is manifest-live");
|
|
9509
|
-
}
|
|
9510
|
-
if (blockIds.length > 0 && visibleBlockCount === 0) {
|
|
9511
|
-
cursor.continue();
|
|
9512
|
-
return;
|
|
9513
|
-
}
|
|
9581
|
+
if (segment.level === 0)
|
|
9582
|
+
found.push(segment);
|
|
9583
|
+
cursor.continue();
|
|
9514
9584
|
} catch (error) {
|
|
9515
9585
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
9516
|
-
return;
|
|
9517
|
-
}
|
|
9518
|
-
const knownStatus = statuses.get(segment.transactionId);
|
|
9519
|
-
if (knownStatus !== void 0) {
|
|
9520
|
-
if (knownStatus === "committed")
|
|
9521
|
-
count += 1;
|
|
9522
|
-
cursor.continue();
|
|
9523
|
-
return;
|
|
9524
9586
|
}
|
|
9525
|
-
const ownerRequest = transactions.get(segment.transactionId);
|
|
9526
|
-
ownerRequest.onerror = () => reject(ownerRequest.error ?? new Error("IndexedDB transaction lookup failed"));
|
|
9527
|
-
ownerRequest.onsuccess = () => {
|
|
9528
|
-
try {
|
|
9529
|
-
if (ownerRequest.result === void 0) {
|
|
9530
|
-
throw corruption(`segments/${segment.id}`, `owning transaction ${segment.transactionId} is missing`);
|
|
9531
|
-
}
|
|
9532
|
-
const owner = asStoredTransactionRecord(ownerRequest.result, segment.transactionId);
|
|
9533
|
-
statuses.set(owner.id, owner.status);
|
|
9534
|
-
if (owner.status === "committed")
|
|
9535
|
-
count += 1;
|
|
9536
|
-
cursor.continue();
|
|
9537
|
-
} catch (error) {
|
|
9538
|
-
reject(error instanceof Error ? error : new Error(String(error)));
|
|
9539
|
-
}
|
|
9540
|
-
};
|
|
9541
9587
|
};
|
|
9542
9588
|
});
|
|
9589
|
+
const memberships = await Promise.all(candidates.map((segment) => manifestBlockMembershipInTransaction(catalog, version, segmentBlockIds(segment))));
|
|
9590
|
+
const statuses = /* @__PURE__ */ new Map();
|
|
9591
|
+
let count = 0;
|
|
9592
|
+
for (const [position, segment] of candidates.entries()) {
|
|
9593
|
+
const membership = memberships[position] ?? [];
|
|
9594
|
+
const visibleBlockCount = membership.filter((present) => present).length;
|
|
9595
|
+
if (visibleBlockCount > 0 && visibleBlockCount < membership.length) {
|
|
9596
|
+
throw corruption(`segments/${segment.id}`, "only part of the segment is manifest-live");
|
|
9597
|
+
}
|
|
9598
|
+
if (membership.length > 0 && visibleBlockCount === 0)
|
|
9599
|
+
continue;
|
|
9600
|
+
let status = statuses.get(segment.transactionId);
|
|
9601
|
+
if (status === void 0) {
|
|
9602
|
+
const owner = await requestResult(transactions.get(segment.transactionId));
|
|
9603
|
+
if (owner === void 0) {
|
|
9604
|
+
throw corruption(`segments/${segment.id}`, `owning transaction ${segment.transactionId} is missing`);
|
|
9605
|
+
}
|
|
9606
|
+
status = asStoredTransactionRecord(owner, segment.transactionId).status;
|
|
9607
|
+
statuses.set(segment.transactionId, status);
|
|
9608
|
+
}
|
|
9609
|
+
if (status === "committed")
|
|
9610
|
+
count += 1;
|
|
9611
|
+
}
|
|
9612
|
+
return count;
|
|
9543
9613
|
}
|
|
9544
9614
|
async function compactionJobRemovalPreservesProvenance(transaction, removedJob) {
|
|
9545
9615
|
const rootedBlocks = /* @__PURE__ */ new Set();
|
|
@@ -9799,6 +9869,17 @@ async function assertActiveCompactionMarker(store, record) {
|
|
|
9799
9869
|
throw corruption(`gc/${activeCompactionKey(record.tableId)}`, `marker names job ${marker.jobId} instead of ${record.id}`);
|
|
9800
9870
|
}
|
|
9801
9871
|
}
|
|
9872
|
+
async function releaseGarbageCollectionAdmission(gcStore) {
|
|
9873
|
+
const quota = await readMaintenanceQuota(gcStore);
|
|
9874
|
+
const completedGarbageCollectionJobs = checkedQuotaIncrement(quota.completedGarbageCollectionJobs, "Completed garbage collection job count");
|
|
9875
|
+
assertMaintenanceLimit("completed garbage collection job", completedGarbageCollectionJobs, MAX_COMPLETED_GARBAGE_COLLECTION_JOB_RECORDS);
|
|
9876
|
+
gcStore.put({
|
|
9877
|
+
...quota,
|
|
9878
|
+
activeGarbageCollectionJobs: checkedQuotaDecrement(quota.activeGarbageCollectionJobs, "active garbage collection job count"),
|
|
9879
|
+
completedGarbageCollectionJobs
|
|
9880
|
+
}, MAINTENANCE_QUOTA_KEY);
|
|
9881
|
+
await requestResult(gcStore.delete(ACTIVE_GARBAGE_COLLECTION_KEY));
|
|
9882
|
+
}
|
|
9802
9883
|
async function assertActiveGarbageCollectionMarker(store, record) {
|
|
9803
9884
|
const marker = asActiveGarbageCollectionMarker(await requestResult(store.get(ACTIVE_GARBAGE_COLLECTION_KEY)));
|
|
9804
9885
|
if (marker.jobId !== record.id) {
|
|
@@ -12959,5 +13040,6 @@ function utf8Bytes(value) {
|
|
|
12959
13040
|
return storageTextEncoder.encode(value).byteLength;
|
|
12960
13041
|
}
|
|
12961
13042
|
export {
|
|
13043
|
+
INDEXEDDB_UNRESPONSIVE_AFTER_MS,
|
|
12962
13044
|
IndexedDbBlockStore
|
|
12963
13045
|
};
|