@harperfast/harper 5.3.0 → 5.3.1
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/bin/copyDb.ts +5 -1
- package/bin/deployRenderer.ts +3 -0
- package/components/Application.ts +66 -22
- package/components/DESIGN.md +89 -36
- package/components/componentLoader.ts +2 -0
- package/components/deploymentRecorder.ts +18 -1
- package/components/installFingerprint.ts +123 -0
- package/components/mcp/DESIGN.md +4 -4
- package/components/operations.js +29 -0
- package/config/DESIGN.md +5 -5
- package/dataLayer/DESIGN.md +37 -22
- package/dataLayer/backupRepository.ts +248 -0
- package/dataLayer/restoreMarker.ts +30 -75
- package/dataLayer/rocksdbBackup.ts +253 -110
- package/dist/bin/copyDb.js +3 -0
- package/dist/bin/copyDb.js.map +1 -1
- package/dist/bin/deployRenderer.js +3 -0
- package/dist/bin/deployRenderer.js.map +1 -1
- package/dist/components/Application.d.ts +5 -0
- package/dist/components/Application.js +51 -19
- package/dist/components/Application.js.map +1 -1
- package/dist/components/componentLoader.js +2 -0
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/deploymentRecorder.js +18 -1
- package/dist/components/deploymentRecorder.js.map +1 -1
- package/dist/components/installFingerprint.d.ts +39 -0
- package/dist/components/installFingerprint.js +113 -0
- package/dist/components/installFingerprint.js.map +1 -0
- package/dist/components/operations.d.ts +2 -0
- package/dist/components/operations.js +31 -0
- package/dist/components/operations.js.map +1 -1
- package/dist/dataLayer/backupRepository.d.ts +33 -0
- package/dist/dataLayer/backupRepository.js +232 -0
- package/dist/dataLayer/backupRepository.js.map +1 -0
- package/dist/dataLayer/restoreMarker.d.ts +4 -1
- package/dist/dataLayer/restoreMarker.js +29 -68
- package/dist/dataLayer/restoreMarker.js.map +1 -1
- package/dist/dataLayer/rocksdbBackup.js +221 -112
- package/dist/dataLayer/rocksdbBackup.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js.map +1 -1
- package/dist/json/systemSchema.json +14 -0
- package/dist/resources/DatabaseTransaction.d.ts +140 -11
- package/dist/resources/DatabaseTransaction.js +1055 -464
- package/dist/resources/DatabaseTransaction.js.map +1 -1
- package/dist/resources/IterableEventQueue.d.ts +2 -1
- package/dist/resources/IterableEventQueue.js +16 -8
- package/dist/resources/IterableEventQueue.js.map +1 -1
- package/dist/resources/LMDBTransaction.d.ts +13 -2
- package/dist/resources/LMDBTransaction.js +219 -93
- package/dist/resources/LMDBTransaction.js.map +1 -1
- package/dist/resources/RecordEncoder.js +2 -3
- package/dist/resources/RecordEncoder.js.map +1 -1
- package/dist/resources/Resource.js +5 -6
- package/dist/resources/Resource.js.map +1 -1
- package/dist/resources/ResourceInterface.d.ts +3 -1
- package/dist/resources/ResourceInterface.js.map +1 -1
- package/dist/resources/RocksIndexStore.d.ts +2 -1
- package/dist/resources/RocksIndexStore.js +3 -0
- package/dist/resources/RocksIndexStore.js.map +1 -1
- package/dist/resources/Table.js +116 -12
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/write.js +6 -2
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/auditStore.d.ts +71 -17
- package/dist/resources/auditStore.js +248 -64
- package/dist/resources/auditStore.js.map +1 -1
- package/dist/resources/branchDatabase.js +2 -0
- package/dist/resources/branchDatabase.js.map +1 -1
- package/dist/resources/databases.js +8 -2
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/indexes/fullTextNativeBinding.d.ts +6 -2
- package/dist/resources/indexes/fullTextNativeBinding.js +12 -2
- package/dist/resources/indexes/fullTextNativeBinding.js.map +1 -1
- package/dist/resources/indexes/fullTextQueryIndex.d.ts +4 -0
- package/dist/resources/indexes/fullTextQueryIndex.js +207 -10
- package/dist/resources/indexes/fullTextQueryIndex.js.map +1 -1
- package/dist/resources/models/Models.d.ts +11 -0
- package/dist/resources/models/Models.js +95 -4
- package/dist/resources/models/Models.js.map +1 -1
- package/dist/resources/models/backendRegistry.d.ts +8 -0
- package/dist/resources/models/backendRegistry.js +15 -1
- package/dist/resources/models/backendRegistry.js.map +1 -1
- package/dist/resources/models/bootstrap.d.ts +2 -0
- package/dist/resources/models/bootstrap.js +6 -0
- package/dist/resources/models/bootstrap.js.map +1 -1
- package/dist/resources/models/calibration.d.ts +88 -0
- package/dist/resources/models/calibration.js +244 -0
- package/dist/resources/models/calibration.js.map +1 -0
- package/dist/resources/models/calibrationStore.d.ts +163 -0
- package/dist/resources/models/calibrationStore.js +986 -0
- package/dist/resources/models/calibrationStore.js.map +1 -0
- package/dist/resources/models/decisionStore.d.ts +24 -0
- package/dist/resources/models/decisionStore.js +45 -0
- package/dist/resources/models/decisionStore.js.map +1 -1
- package/dist/resources/models/generativeDecision.js +44 -15
- package/dist/resources/models/generativeDecision.js.map +1 -1
- package/dist/resources/models/types.d.ts +7 -0
- package/dist/resources/recordLock.d.ts +8 -5
- package/dist/resources/recordLock.js +6 -4
- package/dist/resources/recordLock.js.map +1 -1
- package/dist/resources/replayLogs.js +8 -1
- package/dist/resources/replayLogs.js.map +1 -1
- package/dist/resources/scheduler/engine.d.ts +4 -0
- package/dist/resources/scheduler/engine.js +30 -2
- package/dist/resources/scheduler/engine.js.map +1 -1
- package/dist/resources/search.d.ts +16 -4
- package/dist/resources/search.js +117 -13
- package/dist/resources/search.js.map +1 -1
- package/dist/resources/transaction.js +85 -5
- package/dist/resources/transaction.js.map +1 -1
- package/dist/resources/transactionBroadcast.d.ts +8 -0
- package/dist/resources/transactionBroadcast.js +65 -0
- package/dist/resources/transactionBroadcast.js.map +1 -1
- package/dist/security/keys.d.ts +1 -1
- package/dist/security/keys.js +170 -120
- package/dist/security/keys.js.map +1 -1
- package/dist/server/http.js +10 -0
- package/dist/server/http.js.map +1 -1
- package/dist/server/serverHelpers/Request.js +11 -2
- package/dist/server/serverHelpers/Request.js.map +1 -1
- package/dist/server/serverHelpers/contentTypes.js +8 -3
- package/dist/server/serverHelpers/contentTypes.js.map +1 -1
- package/dist/server/serverHelpers/uwsServer.js +38 -7
- package/dist/server/serverHelpers/uwsServer.js.map +1 -1
- package/dist/server/threads/manageThreads.d.ts +3 -3
- package/dist/server/threads/manageThreads.js +15 -13
- package/dist/server/threads/manageThreads.js.map +1 -1
- package/dist/server/threads/threadServer.d.ts +3 -0
- package/dist/server/threads/threadServer.js +24 -6
- package/dist/server/threads/threadServer.js.map +1 -1
- package/dist/upgrade/directives/5-3-0.js +9 -3
- package/dist/upgrade/directives/5-3-0.js.map +1 -1
- package/dist/utility/durableFile.d.ts +36 -0
- package/dist/utility/durableFile.js +106 -0
- package/dist/utility/durableFile.js.map +1 -0
- package/dist/utility/errors/hdbError.d.ts +4 -0
- package/dist/utility/errors/hdbError.js +10 -1
- package/dist/utility/errors/hdbError.js.map +1 -1
- package/dist/utility/globalSchema.d.ts +9 -0
- package/dist/utility/hdbTerms.d.ts +1 -0
- package/dist/utility/hdbTerms.js +1 -0
- package/dist/utility/hdbTerms.js.map +1 -1
- package/dist/validation/configValidator.js +29 -0
- package/dist/validation/configValidator.js.map +1 -1
- package/index.ts +7 -0
- package/json/systemSchema.json +14 -0
- package/npm-shrinkwrap.json +22 -22
- package/package.json +2 -2
- package/resources/DESIGN.md +57 -272
- package/resources/DatabaseTransaction.ts +708 -87
- package/resources/FULL_TEXT.md +6 -2
- package/resources/IterableEventQueue.ts +14 -7
- package/resources/LMDBTransaction.ts +212 -84
- package/resources/RecordEncoder.ts +2 -3
- package/resources/Resource.ts +5 -6
- package/resources/ResourceInterface.ts +3 -1
- package/resources/RocksIndexStore.ts +5 -0
- package/resources/Table.ts +118 -15
- package/resources/analytics/write.ts +6 -2
- package/resources/audit-retention.md +203 -0
- package/resources/auditStore.ts +306 -84
- package/resources/branchDatabase.ts +2 -0
- package/resources/databases.ts +6 -2
- package/resources/indexes/DESIGN.md +120 -177
- package/resources/indexes/fullTextNativeBinding.ts +22 -3
- package/resources/indexes/fullTextQueryIndex.ts +274 -11
- package/resources/models/DESIGN.md +11 -3
- package/resources/models/Models.ts +127 -4
- package/resources/models/backendRegistry.ts +17 -0
- package/resources/models/bootstrap.ts +9 -1
- package/resources/models/calibration.ts +298 -0
- package/resources/models/calibrationStore.ts +1167 -0
- package/resources/models/decisionStore.ts +57 -0
- package/resources/models/generativeDecision.ts +54 -16
- package/resources/models/types.ts +6 -0
- package/resources/record-locks.md +155 -141
- package/resources/recordLock.ts +12 -6
- package/resources/replayLogs.ts +9 -2
- package/resources/scheduler/DESIGN.md +4 -3
- package/resources/scheduler/engine.ts +35 -2
- package/resources/search.ts +154 -16
- package/resources/transaction.ts +50 -5
- package/resources/transactionBroadcast.ts +69 -0
- package/security/DESIGN.md +9 -30
- package/security/keys.ts +175 -127
- package/server/DESIGN.md +70 -36
- package/server/http.ts +10 -0
- package/server/serverHelpers/Request.ts +10 -2
- package/server/serverHelpers/contentTypes.ts +5 -3
- package/server/serverHelpers/uwsServer.ts +34 -7
- package/server/threads/manageThreads.js +16 -14
- package/server/threads/threadServer.js +24 -6
- package/studio/web/assets/{Chat-CNEKMllJ.js → Chat-4LMxI0yB.js} +1 -1
- package/studio/web/assets/{FloatingChat-CEnWhHeR.js → FloatingChat-kWHApEtF.js} +3 -3
- package/studio/web/assets/{SearchDialog-CwhJdEdY.js → SearchDialog-B7ymna97.js} +1 -1
- package/studio/web/assets/{apiToken-DC5vsaaO.js → apiToken-CE3AAt9f.js} +1 -1
- package/studio/web/assets/{applications-DQZxDy0x.js → applications-DdN7CqsB.js} +1 -1
- package/studio/web/assets/{cssMode-Dz2DxF4e.js → cssMode-BpySZUSt.js} +1 -1
- package/studio/web/assets/{editor-B3mjd3tz.js → editor-myLCVv9C.js} +1 -1
- package/studio/web/assets/{html-BsRGM7tp.js → html-DGNYO55O.js} +1 -1
- package/studio/web/assets/{htmlMode-tUKJaA3o.js → htmlMode-BUgpQr41.js} +1 -1
- package/studio/web/assets/{index-BuqFjN5K.js → index-FN4KC9va.js} +39 -39
- package/studio/web/assets/index-QLZw6xrU.css +1 -0
- package/studio/web/assets/{index.lazy-CcpfQFY_.js → index.lazy-DZFuaumG.js} +1 -1
- package/studio/web/assets/{javascript-BZ_uRGHl.js → javascript-DiBzh4pj.js} +1 -1
- package/studio/web/assets/{jsonMode-DgB-aFMj.js → jsonMode-Bm312nmu.js} +1 -1
- package/studio/web/assets/{languageServices-BleuBw17.js → languageServices-Dz2K9rZN.js} +1 -1
- package/studio/web/assets/{lspLanguageFeatures-ByVYLSsQ.js → lspLanguageFeatures-CNu1L5xn.js} +1 -1
- package/studio/web/assets/{notifications-TuzN0IMi.js → notifications--nwFLGmM.js} +1 -1
- package/studio/web/assets/{notifications-D1Nf-Edn.js → notifications-BelKw5bR.js} +1 -1
- package/studio/web/assets/{profile-D7C7Lupz.js → profile-AU5FjOBx.js} +1 -1
- package/studio/web/assets/{regions-nGQCm-v8.js → regions-C0sTSEHH.js} +1 -1
- package/studio/web/assets/{register-C3x9Ze6P.js → register-DyNR2rGk.js} +2 -2
- package/studio/web/assets/{setComponentFile-DpjrRqeG.js → setComponentFile-BkWx8AN3.js} +1 -1
- package/studio/web/assets/{setup-CGiKLZ9e.js → setup-D6LZS78d.js} +2 -2
- package/studio/web/assets/{status-CGJwrNPH.js → status-BCWnn70o.js} +1 -1
- package/studio/web/assets/{toggleHighContrast-C-Ne6P7T.js → toggleHighContrast-pyeGJ6W1.js} +1 -1
- package/studio/web/assets/{tsMode-CSreYTys.js → tsMode-CGV3iaWC.js} +1 -1
- package/studio/web/assets/{typescript-MnxBk89W.js → typescript-Ci7Khvwo.js} +1 -1
- package/studio/web/assets/{useEntityRestURL-TNrh77-s.js → useEntityRestURL-DNiz3aZ0.js} +1 -1
- package/studio/web/assets/{workers-BfZlUNVI.js → workers-byzxjbqy.js} +1 -1
- package/studio/web/assets/{xml-BHd6qGH7.js → xml-DGnHQ3CX.js} +1 -1
- package/studio/web/assets/{yaml-C53R8OQq.js → yaml-BUoTnPWb.js} +1 -1
- package/studio/web/index.html +2 -2
- package/upgrade/directives/5-3-0.ts +10 -3
- package/utility/durableFile.ts +96 -0
- package/utility/errors/hdbError.ts +9 -0
- package/utility/hdbTerms.ts +1 -0
- package/validation/configValidator.ts +31 -0
- package/studio/web/assets/index-72cEH474.css +0 -1
package/dist/resources/Table.js
CHANGED
|
@@ -561,6 +561,15 @@ function scopeViolation(handle, resolved, databaseName) {
|
|
|
561
561
|
return undefined;
|
|
562
562
|
return new hdbError_ts_1.ClientError('This transaction already holds a node-scoped lock on this record, so a cluster-scoped lock cannot be taken on top of it', 409);
|
|
563
563
|
}
|
|
564
|
+
function rescope(resolved, tableReplicates) {
|
|
565
|
+
if (resolved.scopeRequested)
|
|
566
|
+
return resolved;
|
|
567
|
+
const scope = tableReplicates ? 'cluster' : 'node';
|
|
568
|
+
return scope === resolved.scope ? resolved : { ...resolved, scope };
|
|
569
|
+
}
|
|
570
|
+
function transportUnavailable(databaseName) {
|
|
571
|
+
return new hdbError_ts_1.LockUnavailableError(`Cluster-scoped record locks are not available on ${databaseName}: no record lock transport is registered`);
|
|
572
|
+
}
|
|
564
573
|
/** Distinguishes bare lock options from a record target (id, URL, {id:...}). */
|
|
565
574
|
function isPlainOptions(value) {
|
|
566
575
|
return (typeof value === 'object' &&
|
|
@@ -577,6 +586,26 @@ function isPlainOptions(value) {
|
|
|
577
586
|
return undefined;
|
|
578
587
|
return (entry) => Table.writeLockControlEntry(entry);
|
|
579
588
|
});
|
|
589
|
+
// Valid for one synchronous notify pass, in which a key's subscribers on this thread all receive the same
|
|
590
|
+
// freshly decoded audit record; cleared after it so it pins no store or record once delivery is done.
|
|
591
|
+
let memoizedEntryAuditRecord;
|
|
592
|
+
let memoizedEntryStore;
|
|
593
|
+
let memoizedEntryId;
|
|
594
|
+
let memoizedEntry;
|
|
595
|
+
function clearEntryMemo() {
|
|
596
|
+
memoizedEntryAuditRecord = memoizedEntryStore = memoizedEntryId = memoizedEntry = undefined;
|
|
597
|
+
}
|
|
598
|
+
function currentEntryForAudit(store, id, auditRecord) {
|
|
599
|
+
if (auditRecord !== memoizedEntryAuditRecord || store !== memoizedEntryStore || id !== memoizedEntryId) {
|
|
600
|
+
if (memoizedEntryAuditRecord === undefined)
|
|
601
|
+
queueMicrotask(clearEntryMemo);
|
|
602
|
+
memoizedEntry = store.getEntry(id);
|
|
603
|
+
memoizedEntryAuditRecord = auditRecord;
|
|
604
|
+
memoizedEntryStore = store;
|
|
605
|
+
memoizedEntryId = id;
|
|
606
|
+
}
|
|
607
|
+
return memoizedEntry;
|
|
608
|
+
}
|
|
580
609
|
function makeTable(options) {
|
|
581
610
|
var _a;
|
|
582
611
|
const { primaryKey, indices, tableId, tableName, primaryStore, databasePath, databaseName, auditStore, schemaDefined, dbisDB: dbisDb, sealed, splitSegments, replicate, description, hidden, cacheControl, isBranch, fullTextIndexes = [], fullTextFields = [], fullTextIndexGenerations = Object.create(null), fullTextIndexRetirements = [], } = options;
|
|
@@ -865,12 +894,26 @@ function makeTable(options) {
|
|
|
865
894
|
return;
|
|
866
895
|
return { key, descriptor };
|
|
867
896
|
}
|
|
897
|
+
const COMMIT_BASE_METHODS = new Set(['put', 'patch', 'delete']);
|
|
898
|
+
function entryBeforeWrite(loadedEntry, id, transaction, reloadsCommitBase) {
|
|
899
|
+
if (loadedEntry != null)
|
|
900
|
+
return loadedEntry;
|
|
901
|
+
if (isRocksDB && reloadsCommitBase) {
|
|
902
|
+
// save() reads this write's base from the staging snapshot (harper#2259); the read handle is still opened
|
|
903
|
+
// here because it is what gives the staged write coordinated conflict retries
|
|
904
|
+
transaction.getReadTxn();
|
|
905
|
+
return undefined;
|
|
906
|
+
}
|
|
907
|
+
return primaryStore.getEntry(id, { transaction: transaction.getReadTxn() });
|
|
908
|
+
}
|
|
868
909
|
class TableResource extends Resource_ts_1.Resource {
|
|
869
910
|
#record; // the stored/frozen record from the database and stored in the cache (should not be modified directly)
|
|
870
911
|
#changes; // the changes to the record that have been made (should not be modified directly)
|
|
871
912
|
#version; // version of the record
|
|
872
913
|
#entry; // the entry from the database
|
|
873
914
|
#savingOperation; // operation for the record is currently being saved
|
|
915
|
+
#baseReadTxn; // staging handle this instance's uncached pre-load read through
|
|
916
|
+
#baseReadEntry; // what that read returned, reusable as the commit base only while it is still #entry
|
|
874
917
|
#lockHandle; // the record lock acquired by lock() — scoped or hold
|
|
875
918
|
#lockWritable; // set by #reloadLocked to let save() stage lock-writable updates
|
|
876
919
|
#writeGeneration;
|
|
@@ -1611,12 +1654,25 @@ function makeTable(options) {
|
|
|
1611
1654
|
if (readTxn?.isDone) {
|
|
1612
1655
|
throw new Error('You can not read from a transaction that has already been committed/aborted');
|
|
1613
1656
|
}
|
|
1614
|
-
|
|
1657
|
+
const readsCommitBase = isRocksDB &&
|
|
1658
|
+
COMMIT_BASE_METHODS.has(resourceOptions?.method) &&
|
|
1659
|
+
!resourceOptions?.ensureLoaded &&
|
|
1660
|
+
readTxn &&
|
|
1661
|
+
!readTxn.snapshotDisabled;
|
|
1662
|
+
return loadLocalRecord(id, request, {
|
|
1663
|
+
transaction: readTxn,
|
|
1664
|
+
ensureLoaded: resourceOptions?.ensureLoaded,
|
|
1665
|
+
uncachedRead: readsCommitBase || undefined,
|
|
1666
|
+
}, sync, (entry) => {
|
|
1615
1667
|
if (entry) {
|
|
1616
1668
|
_a._updateResource(this, entry);
|
|
1617
1669
|
}
|
|
1618
1670
|
else
|
|
1619
1671
|
this.#record = null;
|
|
1672
|
+
if (readsCommitBase) {
|
|
1673
|
+
this.#baseReadTxn = readTxn;
|
|
1674
|
+
this.#baseReadEntry = entry;
|
|
1675
|
+
}
|
|
1620
1676
|
if (request.onlyIfCached) {
|
|
1621
1677
|
// don't go into the loading from source condition, but HTTP spec says to
|
|
1622
1678
|
// return 504 (rather than 404) if there is no content and the cache-control header
|
|
@@ -1647,6 +1703,16 @@ function makeTable(options) {
|
|
|
1647
1703
|
throw error;
|
|
1648
1704
|
}
|
|
1649
1705
|
}
|
|
1706
|
+
// Reusable only for the key this instance read and while #entry is the entry that read returned: a source fill
|
|
1707
|
+
// or retry replaces #entry, and ensureLoaded() can evict it in place, so ensureLoaded() drops the receipt.
|
|
1708
|
+
#commitBaseTxn(id) {
|
|
1709
|
+
const baseReadTxn = this.#baseReadTxn;
|
|
1710
|
+
if (!baseReadTxn || this.#baseReadEntry !== this.#entry)
|
|
1711
|
+
return;
|
|
1712
|
+
const receiverId = this.getId();
|
|
1713
|
+
if (Object.is(id, receiverId) || (0, DatabaseTransaction_ts_1.writeKeyId)(id) === (0, DatabaseTransaction_ts_1.writeKeyId)(receiverId))
|
|
1714
|
+
return baseReadTxn;
|
|
1715
|
+
}
|
|
1650
1716
|
static _updateResource(resource, entry) {
|
|
1651
1717
|
resource.#entry = entry;
|
|
1652
1718
|
resource.#record = entry?.value ?? null;
|
|
@@ -1658,6 +1724,7 @@ function makeTable(options) {
|
|
|
1658
1724
|
* @returns
|
|
1659
1725
|
*/
|
|
1660
1726
|
ensureLoaded() {
|
|
1727
|
+
this.#baseReadTxn = undefined;
|
|
1661
1728
|
const loadedFromSource = ensureLoadedFromSource(this.constructor.source, this.getId(), this.#entry, this.getContext());
|
|
1662
1729
|
if (loadedFromSource) {
|
|
1663
1730
|
return (0, when_ts_1.when)(loadedFromSource, (entry) => {
|
|
@@ -2848,6 +2915,7 @@ function makeTable(options) {
|
|
|
2848
2915
|
additionalAuditRefs: isRocksDB && audit && txnLogKey !== txnTime
|
|
2849
2916
|
? [{ version: txnLogKey, nodeId: options?.nodeId }]
|
|
2850
2917
|
: undefined,
|
|
2918
|
+
localOnly: options?.localOnly,
|
|
2851
2919
|
}, 'invalidate');
|
|
2852
2920
|
if (write.trackRecordVersion)
|
|
2853
2921
|
write.recordVersionApplied = true;
|
|
@@ -2906,6 +2974,7 @@ function makeTable(options) {
|
|
|
2906
2974
|
additionalAuditRefs: isRocksDB && audit && txnLogKey !== txnTime
|
|
2907
2975
|
? [{ version: txnLogKey, nodeId: options?.nodeId }]
|
|
2908
2976
|
: undefined,
|
|
2977
|
+
localOnly: options?.localOnly,
|
|
2909
2978
|
}, 'relocate', false, null);
|
|
2910
2979
|
if (write.trackRecordVersion)
|
|
2911
2980
|
write.recordVersionApplied = true;
|
|
@@ -3078,7 +3147,7 @@ function makeTable(options) {
|
|
|
3078
3147
|
const id = target != null ? requestTargetToId(target) : this.getId();
|
|
3079
3148
|
checkValidId(id);
|
|
3080
3149
|
this.#assertLiveHandle(id);
|
|
3081
|
-
const resolved = (0, recordLock_ts_1.resolveLockOptions)(options);
|
|
3150
|
+
const resolved = (0, recordLock_ts_1.resolveLockOptions)(options, _a.replicate !== false);
|
|
3082
3151
|
const context = this.getContext();
|
|
3083
3152
|
const link = txnForContext(context);
|
|
3084
3153
|
const keyId = (0, DatabaseTransaction_ts_1.writeKeyId)(id);
|
|
@@ -3088,7 +3157,7 @@ function makeTable(options) {
|
|
|
3088
3157
|
if (resolved.scope === 'cluster' &&
|
|
3089
3158
|
(resolved.scopeRequested || (0, recordLockCoordinator_ts_1.isClusterLockRequired)(databaseName)) &&
|
|
3090
3159
|
!(0, recordLockCoordinator_ts_1.getClusterLockTransport)(databaseName))
|
|
3091
|
-
return Promise.reject(
|
|
3160
|
+
return Promise.reject(transportUnavailable(databaseName));
|
|
3092
3161
|
const held = this.#lockHandle;
|
|
3093
3162
|
if (held && !held.isExpired() && held.keyId === keyId) {
|
|
3094
3163
|
// Re-entrant: upgrade to hold if requested, then preserve staged changes.
|
|
@@ -3181,7 +3250,7 @@ function makeTable(options) {
|
|
|
3181
3250
|
clearTimeout(followerTimer);
|
|
3182
3251
|
const acquired = link.recordLockFor(primaryStore, keyId);
|
|
3183
3252
|
if (acquired && !acquired.isExpired()) {
|
|
3184
|
-
const violation = scopeViolation(acquired, resolved, databaseName);
|
|
3253
|
+
const violation = scopeViolation(acquired, rescope(resolved, _a.replicate !== false), databaseName);
|
|
3185
3254
|
if (violation)
|
|
3186
3255
|
throw violation;
|
|
3187
3256
|
if (resolved.hold && !acquired.hold) {
|
|
@@ -3223,9 +3292,9 @@ function makeTable(options) {
|
|
|
3223
3292
|
// caller's whole timeout, long enough for harper-pro to register the transport on this
|
|
3224
3293
|
// worker. Using the snapshot would take the native key alone and hand back a node-scoped
|
|
3225
3294
|
// handle while a peer that already had the transport is granted the same key.
|
|
3295
|
+
const current = rescope(resolved, _a.replicate !== false);
|
|
3226
3296
|
try {
|
|
3227
|
-
|
|
3228
|
-
coordinator = _a.lockCoordinator ?? coordinator;
|
|
3297
|
+
coordinator = current.scope === 'cluster' ? (_a.lockCoordinator ?? coordinator) : undefined;
|
|
3229
3298
|
}
|
|
3230
3299
|
catch (error) {
|
|
3231
3300
|
// The getter fails closed on an unusable node identity, and that has to reach the caller
|
|
@@ -3235,6 +3304,13 @@ function makeTable(options) {
|
|
|
3235
3304
|
handle.release();
|
|
3236
3305
|
throw error;
|
|
3237
3306
|
}
|
|
3307
|
+
// The entry check cannot cover this: the wait is where the call became cluster-scoped.
|
|
3308
|
+
if (current.scope === 'cluster' &&
|
|
3309
|
+
!coordinator &&
|
|
3310
|
+
(current.scopeRequested || (0, recordLockCoordinator_ts_1.isClusterLockRequired)(databaseName))) {
|
|
3311
|
+
handle.release();
|
|
3312
|
+
throw transportUnavailable(databaseName);
|
|
3313
|
+
}
|
|
3238
3314
|
if (coordinator) {
|
|
3239
3315
|
try {
|
|
3240
3316
|
// Not a 423 when the budget is gone, and not a skip either: the native wait can consume
|
|
@@ -3538,7 +3614,9 @@ function makeTable(options) {
|
|
|
3538
3614
|
}
|
|
3539
3615
|
};
|
|
3540
3616
|
}
|
|
3541
|
-
const
|
|
3617
|
+
const reloadsCommitBase = options?.isCopyApply !== true;
|
|
3618
|
+
const entry = entryBeforeWrite(this.#entry, id, transaction, reloadsCommitBase);
|
|
3619
|
+
const baseReadTxn = this.#commitBaseTxn(id);
|
|
3542
3620
|
const writeToSource = () => {
|
|
3543
3621
|
if (!this.constructor.source || context?.source)
|
|
3544
3622
|
return;
|
|
@@ -3567,11 +3645,12 @@ function makeTable(options) {
|
|
|
3567
3645
|
key: id,
|
|
3568
3646
|
store: primaryStore,
|
|
3569
3647
|
entry,
|
|
3648
|
+
baseReadTxn,
|
|
3570
3649
|
nodeName: context?.nodeName,
|
|
3571
3650
|
fullUpdate,
|
|
3572
3651
|
chainsStagedState: true,
|
|
3573
3652
|
// copy-apply rows keep their pre-read base: one read per row, healed by the post-copy replay
|
|
3574
|
-
reloadCommitBase:
|
|
3653
|
+
reloadCommitBase: reloadsCommitBase,
|
|
3575
3654
|
deferSave: true,
|
|
3576
3655
|
// the origin's record version on an applied write; absent for a locally-originated one
|
|
3577
3656
|
recordVersion: options?.version,
|
|
@@ -4373,11 +4452,13 @@ function makeTable(options) {
|
|
|
4373
4452
|
const transaction = txnForContext(context);
|
|
4374
4453
|
assertDerivedIndexAdmission(options, transaction);
|
|
4375
4454
|
checkValidId(id);
|
|
4376
|
-
const entry = this.#entry
|
|
4455
|
+
const entry = entryBeforeWrite(this.#entry, id, transaction, true);
|
|
4456
|
+
const baseReadTxn = this.#commitBaseTxn(id);
|
|
4377
4457
|
const write = {
|
|
4378
4458
|
key: id,
|
|
4379
4459
|
store: primaryStore,
|
|
4380
4460
|
entry,
|
|
4461
|
+
baseReadTxn,
|
|
4381
4462
|
chainsStagedState: true,
|
|
4382
4463
|
reloadCommitBase: true,
|
|
4383
4464
|
nodeName: context?.nodeName,
|
|
@@ -4428,6 +4509,7 @@ function makeTable(options) {
|
|
|
4428
4509
|
additionalAuditRefs: isRocksDB && audit && txnLogKey !== txnTime
|
|
4429
4510
|
? [{ version: txnLogKey, nodeId: options?.nodeId }]
|
|
4430
4511
|
: undefined,
|
|
4512
|
+
localOnly: options?.localOnly,
|
|
4431
4513
|
}, 'delete');
|
|
4432
4514
|
if (!audit || isRocksDB)
|
|
4433
4515
|
scheduleCleanup();
|
|
@@ -5027,8 +5109,12 @@ function makeTable(options) {
|
|
|
5027
5109
|
results = results.slice(offset, end);
|
|
5028
5110
|
results.onDone = () => {
|
|
5029
5111
|
results.onDone = null; // ensure that it isn't called twice
|
|
5112
|
+
txn.unregisterReadIterator(results);
|
|
5030
5113
|
txn.doneReadTxn();
|
|
5031
5114
|
};
|
|
5115
|
+
// Recorded ownership: if the request dies before anything consumes these results, the
|
|
5116
|
+
// transaction closes them itself rather than leaving its read snapshot pinned.
|
|
5117
|
+
txn.registerReadIterator(results);
|
|
5032
5118
|
results.selectApplied = true;
|
|
5033
5119
|
results.getColumns = getColumns;
|
|
5034
5120
|
return results;
|
|
@@ -5869,7 +5955,12 @@ function makeTable(options) {
|
|
|
5869
5955
|
if (subscription.closed)
|
|
5870
5956
|
return;
|
|
5871
5957
|
harper_logger_ts_1.default.error?.('Error in real-time subscription:', error);
|
|
5872
|
-
|
|
5958
|
+
try {
|
|
5959
|
+
subscription.close(error);
|
|
5960
|
+
}
|
|
5961
|
+
catch (listenerError) {
|
|
5962
|
+
harper_logger_ts_1.default.error?.('Error in real-time subscription listener:', listenerError);
|
|
5963
|
+
}
|
|
5873
5964
|
}
|
|
5874
5965
|
function eventFromAudit(id, auditRecord, localTime, beginTxn) {
|
|
5875
5966
|
let type = auditRecord.type;
|
|
@@ -5878,7 +5969,7 @@ function makeTable(options) {
|
|
|
5878
5969
|
if (isMutation && !includeSuperseded) {
|
|
5879
5970
|
if (id === undefined)
|
|
5880
5971
|
return;
|
|
5881
|
-
const entry = primaryStore
|
|
5972
|
+
const entry = currentEntryForAudit(primaryStore, id, auditRecord);
|
|
5882
5973
|
if (!entry || entry.version !== auditRecord.version)
|
|
5883
5974
|
return;
|
|
5884
5975
|
if (getFullRecord) {
|
|
@@ -6076,7 +6167,7 @@ function makeTable(options) {
|
|
|
6076
6167
|
logger_ts_1.logger.trace?.(`Publishing message to id: ${id}, timestamp: ${new Date(txnTime).toISOString()}`);
|
|
6077
6168
|
// always audit this, but don't change existing version
|
|
6078
6169
|
// TODO: Use direct writes in the future (copying binary data is hard because it invalidates the cache)
|
|
6079
|
-
return updateRecord(id, existingEntry?.value ?? null, existingEntry, txnTime, 0, true, {
|
|
6170
|
+
return updateRecord(id, existingEntry?.value ?? null, existingEntry, txnTime, (existingEntry?.metadataFlags ?? 0) & auditStore_ts_1.LOCAL_ONLY, true, {
|
|
6080
6171
|
user: context?.user,
|
|
6081
6172
|
residencyId: options?.residencyId,
|
|
6082
6173
|
expiresAt: context?.expiresAt,
|
|
@@ -6084,6 +6175,7 @@ function makeTable(options) {
|
|
|
6084
6175
|
viaNodeId: options?.viaNodeId,
|
|
6085
6176
|
transaction,
|
|
6086
6177
|
tableToTrack: tableName,
|
|
6178
|
+
auditLocalOnly: options?.localOnly,
|
|
6087
6179
|
}, 'message', false, message);
|
|
6088
6180
|
},
|
|
6089
6181
|
};
|
|
@@ -7712,6 +7804,16 @@ function makeTable(options) {
|
|
|
7712
7804
|
// regardless of this state.
|
|
7713
7805
|
transaction.next.open = DatabaseTransaction_ts_1.TRANSACTION_STATE.CLOSED;
|
|
7714
7806
|
}
|
|
7807
|
+
// A poison flag must travel with `open`, or a link created after the poisoning (a
|
|
7808
|
+
// handler touching this database for the first time post-poison) sees CLOSED but not
|
|
7809
|
+
// the reason, takes save()'s immediateCommit path, and commits on behalf of a request
|
|
7810
|
+
// that was supposed to have been cut off.
|
|
7811
|
+
if (transaction.timedOut)
|
|
7812
|
+
transaction.next.timedOut = true;
|
|
7813
|
+
if (transaction.disconnected)
|
|
7814
|
+
transaction.next.disconnected = true;
|
|
7815
|
+
if (transaction.postSubmitPoisoned)
|
|
7816
|
+
transaction.next.postSubmitPoisoned = true;
|
|
7715
7817
|
transaction = transaction.next;
|
|
7716
7818
|
transaction.db = primaryStore;
|
|
7717
7819
|
return transaction;
|
|
@@ -7725,6 +7827,8 @@ function makeTable(options) {
|
|
|
7725
7827
|
context.transaction = transaction;
|
|
7726
7828
|
if (context.timestamp)
|
|
7727
7829
|
transaction.timestamp = context.timestamp;
|
|
7830
|
+
if (!context.sourceApply)
|
|
7831
|
+
transaction.requestSignal = context.signal;
|
|
7728
7832
|
}
|
|
7729
7833
|
return transaction;
|
|
7730
7834
|
}
|