@harperfast/harper 5.3.0-beta.3 → 5.3.0-beta.4
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/cliOperations.ts +25 -3
- package/bin/run.ts +18 -0
- package/components/Application.ts +52 -78
- package/components/DESIGN.md +76 -3
- package/components/Scope.ts +10 -4
- package/components/anthropic/index.ts +10 -1
- package/components/bedrock/index.ts +10 -1
- package/components/componentLoader.ts +23 -14
- package/components/mcp/tools/operations.ts +3 -1
- package/components/ollama/index.ts +10 -1
- package/components/openai/index.ts +265 -18
- package/components/operations.js +40 -1
- package/config/configUtils.ts +3 -19
- package/dataLayer/DESIGN.md +29 -5
- package/dataLayer/harperBridge/ResourceBridge.ts +39 -3
- package/dataLayer/restoreMarker.ts +250 -14
- package/dataLayer/schema.ts +2 -7
- package/dataLayer/schemaDescribe.ts +10 -0
- package/dist/bin/cliOperations.js +28 -3
- package/dist/bin/cliOperations.js.map +1 -1
- package/dist/bin/run.js +19 -0
- package/dist/bin/run.js.map +1 -1
- package/dist/components/Application.d.ts +8 -2
- package/dist/components/Application.js +43 -69
- package/dist/components/Application.js.map +1 -1
- package/dist/components/Scope.d.ts +1 -1
- package/dist/components/Scope.js +9 -4
- package/dist/components/Scope.js.map +1 -1
- package/dist/components/anthropic/index.d.ts +0 -10
- package/dist/components/anthropic/index.js +9 -1
- package/dist/components/anthropic/index.js.map +1 -1
- package/dist/components/bedrock/index.d.ts +0 -12
- package/dist/components/bedrock/index.js +9 -1
- package/dist/components/bedrock/index.js.map +1 -1
- package/dist/components/componentLoader.js +23 -14
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/mcp/tools/operations.js +1 -1
- package/dist/components/mcp/tools/operations.js.map +1 -1
- package/dist/components/ollama/index.d.ts +0 -13
- package/dist/components/ollama/index.js +9 -1
- package/dist/components/ollama/index.js.map +1 -1
- package/dist/components/openai/index.d.ts +11 -15
- package/dist/components/openai/index.js +224 -12
- package/dist/components/openai/index.js.map +1 -1
- package/dist/components/operations.d.ts +9 -0
- package/dist/components/operations.js +32 -2
- package/dist/components/operations.js.map +1 -1
- package/dist/config/configUtils.d.ts +1 -2
- package/dist/config/configUtils.js +7 -22
- package/dist/config/configUtils.js.map +1 -1
- package/dist/dataLayer/harperBridge/ResourceBridge.js +29 -2
- package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
- package/dist/dataLayer/restoreMarker.d.ts +25 -3
- package/dist/dataLayer/restoreMarker.js +213 -13
- package/dist/dataLayer/restoreMarker.js.map +1 -1
- package/dist/dataLayer/schema.js +1 -4
- package/dist/dataLayer/schema.js.map +1 -1
- package/dist/dataLayer/schemaDescribe.js +10 -0
- package/dist/dataLayer/schemaDescribe.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/json/systemSchema.json +28 -0
- package/dist/resources/DatabaseTransaction.d.ts +21 -1
- package/dist/resources/DatabaseTransaction.js +147 -8
- package/dist/resources/DatabaseTransaction.js.map +1 -1
- package/dist/resources/PrimaryRocksDatabase.js +1 -1
- package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
- package/dist/resources/Table.d.ts +31 -3
- package/dist/resources/Table.js +397 -79
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/auditStore.js +16 -10
- package/dist/resources/auditStore.js.map +1 -1
- package/dist/resources/blob.d.ts +1 -0
- package/dist/resources/blob.js +14 -5
- package/dist/resources/blob.js.map +1 -1
- package/dist/resources/branchDatabase.js +3 -3
- package/dist/resources/branchDatabase.js.map +1 -1
- package/dist/resources/databaseDropPreparation.d.ts +20 -0
- package/dist/resources/databaseDropPreparation.js +106 -0
- package/dist/resources/databaseDropPreparation.js.map +1 -0
- package/dist/resources/databases.d.ts +26 -21
- package/dist/resources/databases.js +1040 -204
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/derivedIndexRegistry.d.ts +23 -0
- package/dist/resources/derivedIndexRegistry.js +92 -0
- package/dist/resources/derivedIndexRegistry.js.map +1 -1
- package/dist/resources/derivedIndexRuntime.d.ts +10 -0
- package/dist/resources/derivedIndexRuntime.js +136 -25
- package/dist/resources/derivedIndexRuntime.js.map +1 -1
- package/dist/resources/derivedIndexes.d.ts +39 -0
- package/dist/resources/derivedIndexes.js +733 -0
- package/dist/resources/derivedIndexes.js.map +1 -0
- package/dist/resources/fullTextSchema.d.ts +8 -0
- package/dist/resources/fullTextSchema.js +42 -0
- package/dist/resources/fullTextSchema.js.map +1 -1
- package/dist/resources/fullTextSchemaLifecycle.d.ts +0 -5
- package/dist/resources/fullTextSchemaLifecycle.js +0 -9
- package/dist/resources/fullTextSchemaLifecycle.js.map +1 -1
- package/dist/resources/graphql.js +101 -9
- package/dist/resources/graphql.js.map +1 -1
- package/dist/resources/indexes/hnswDerivedIndex.d.ts +0 -10
- package/dist/resources/indexes/hnswDerivedIndex.js +0 -230
- package/dist/resources/indexes/hnswDerivedIndex.js.map +1 -1
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.d.ts +3 -0
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js +57 -8
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js.map +1 -1
- package/dist/resources/models/Models.d.ts +26 -3
- package/dist/resources/models/Models.js +256 -13
- package/dist/resources/models/Models.js.map +1 -1
- package/dist/resources/models/TestBackend.d.ts +3 -1
- package/dist/resources/models/TestBackend.js +35 -1
- package/dist/resources/models/TestBackend.js.map +1 -1
- package/dist/resources/models/analyticsTable.d.ts +2 -2
- package/dist/resources/models/analyticsTable.js +4 -2
- package/dist/resources/models/analyticsTable.js.map +1 -1
- package/dist/resources/models/backendHelpers.d.ts +24 -0
- package/dist/resources/models/backendHelpers.js +18 -1
- package/dist/resources/models/backendHelpers.js.map +1 -1
- package/dist/resources/models/backendRegistry.d.ts +10 -21
- package/dist/resources/models/backendRegistry.js +74 -18
- package/dist/resources/models/backendRegistry.js.map +1 -1
- package/dist/resources/models/bootstrap.d.ts +7 -0
- package/dist/resources/models/bootstrap.js +36 -4
- package/dist/resources/models/bootstrap.js.map +1 -1
- package/dist/resources/models/decideHook.d.ts +33 -0
- package/dist/resources/models/decideHook.js +105 -0
- package/dist/resources/models/decideHook.js.map +1 -0
- package/dist/resources/models/decision.d.ts +64 -0
- package/dist/resources/models/decision.js +507 -0
- package/dist/resources/models/decision.js.map +1 -0
- package/dist/resources/models/decisionStore.d.ts +134 -0
- package/dist/resources/models/decisionStore.js +350 -0
- package/dist/resources/models/decisionStore.js.map +1 -0
- package/dist/resources/models/embedHook.d.ts +66 -8
- package/dist/resources/models/embedHook.js +228 -61
- package/dist/resources/models/embedHook.js.map +1 -1
- package/dist/resources/models/generativeDecision.d.ts +58 -0
- package/dist/resources/models/generativeDecision.js +315 -0
- package/dist/resources/models/generativeDecision.js.map +1 -0
- package/dist/resources/models/types.d.ts +232 -4
- package/dist/security/authn/oidc/tokenExchange.js +3 -33
- package/dist/security/authn/oidc/tokenExchange.js.map +1 -1
- package/dist/security/authn/oidc/tokenUseTable.d.ts +9 -0
- package/dist/security/authn/oidc/tokenUseTable.js +28 -0
- package/dist/security/authn/oidc/tokenUseTable.js.map +1 -0
- package/dist/security/certificateVerification/certificateVerificationSource.d.ts +0 -1
- package/dist/security/certificateVerification/certificateVerificationSource.js +3 -3
- package/dist/security/certificateVerification/certificateVerificationSource.js.map +1 -1
- package/dist/security/certificateVerification/crlVerification.js +77 -165
- package/dist/security/certificateVerification/crlVerification.js.map +1 -1
- package/dist/security/certificateVerification/types.d.ts +0 -3
- package/dist/security/certificateVerification/verificationTables.d.ts +19 -0
- package/dist/security/certificateVerification/verificationTables.js +125 -0
- package/dist/security/certificateVerification/verificationTables.js.map +1 -0
- package/dist/security/certificateVerification/verificationUtils.d.ts +1 -1
- package/dist/security/certificateVerification/verificationUtils.js +6 -31
- package/dist/security/certificateVerification/verificationUtils.js.map +1 -1
- package/dist/security/jsLoader.d.ts +5 -0
- package/dist/security/jsLoader.js +8 -0
- package/dist/security/jsLoader.js.map +1 -1
- package/dist/server/Server.d.ts +1 -0
- package/dist/server/Server.js.map +1 -1
- package/dist/server/http.js +2 -2
- package/dist/server/http.js.map +1 -1
- package/dist/server/itc/serverHandlers.js +21 -2
- package/dist/server/itc/serverHandlers.js.map +1 -1
- package/dist/server/jobs/jobOwnership.d.ts +25 -0
- package/dist/server/jobs/jobOwnership.js +127 -0
- package/dist/server/jobs/jobOwnership.js.map +1 -0
- package/dist/server/jobs/jobProcess.js +9 -2
- package/dist/server/jobs/jobProcess.js.map +1 -1
- package/dist/server/jobs/jobs.js +18 -5
- package/dist/server/jobs/jobs.js.map +1 -1
- package/dist/server/loadRootComponents.js +10 -0
- package/dist/server/loadRootComponents.js.map +1 -1
- package/dist/server/serverHelpers/contentTypes.js +11 -1
- package/dist/server/serverHelpers/contentTypes.js.map +1 -1
- package/dist/server/serverHelpers/serverHandlers.js +12 -2
- package/dist/server/serverHelpers/serverHandlers.js.map +1 -1
- package/dist/server/threads/itc.d.ts +4 -1
- package/dist/server/threads/itc.js +29 -6
- package/dist/server/threads/itc.js.map +1 -1
- package/dist/server/threads/manageThreads.d.ts +12 -4
- package/dist/server/threads/manageThreads.js +241 -119
- package/dist/server/threads/manageThreads.js.map +1 -1
- package/dist/server/threads/threadServer.d.ts +1 -0
- package/dist/server/threads/threadServer.js +15 -1
- package/dist/server/threads/threadServer.js.map +1 -1
- package/dist/server/threads/windowsProcessTree.d.ts +91 -0
- package/dist/server/threads/windowsProcessTree.js +361 -0
- package/dist/server/threads/windowsProcessTree.js.map +1 -0
- package/dist/server/throttle.d.ts +1 -1
- package/dist/server/throttle.js +8 -1
- package/dist/server/throttle.js.map +1 -1
- package/dist/upgrade/directives/5-3-0.js +53 -46
- package/dist/upgrade/directives/5-3-0.js.map +1 -1
- package/dist/utility/errors/hdbError.d.ts +10 -1
- package/dist/utility/errors/hdbError.js +55 -11
- package/dist/utility/errors/hdbError.js.map +1 -1
- package/dist/utility/fsync.d.ts +2 -0
- package/dist/utility/fsync.js +20 -0
- package/dist/utility/fsync.js.map +1 -0
- package/dist/utility/globalSchema.d.ts +18 -0
- package/dist/utility/hdbTerms.d.ts +3 -0
- package/dist/utility/hdbTerms.js +3 -0
- package/dist/utility/hdbTerms.js.map +1 -1
- package/dist/utility/signalling.d.ts +7 -1
- package/dist/utility/signalling.js +27 -3
- package/dist/utility/signalling.js.map +1 -1
- package/dist/utility/when.d.ts +1 -0
- package/dist/utility/when.js +21 -0
- package/dist/utility/when.js.map +1 -1
- package/dist/validation/configValidator.js +30 -3
- package/dist/validation/configValidator.js.map +1 -1
- package/index.ts +13 -0
- package/json/systemSchema.json +28 -0
- package/npm-shrinkwrap.json +151 -55
- package/package.json +14 -13
- package/resources/DESIGN.md +80 -100
- package/resources/DatabaseTransaction.ts +157 -10
- package/resources/PrimaryRocksDatabase.ts +2 -2
- package/resources/Table.ts +494 -101
- package/resources/auditStore.ts +18 -10
- package/resources/blob.ts +13 -6
- package/resources/branchDatabase.ts +3 -3
- package/resources/databaseDropPreparation.ts +120 -0
- package/resources/databases.ts +1155 -205
- package/resources/derivedIndexRegistry.ts +122 -0
- package/resources/derivedIndexRuntime.ts +157 -30
- package/resources/derivedIndexes.ts +856 -0
- package/resources/fullTextSchema.ts +55 -0
- package/resources/fullTextSchemaLifecycle.ts +0 -15
- package/resources/graphql.ts +107 -12
- package/resources/indexes/DESIGN.md +7 -0
- package/resources/indexes/hnswDerivedIndex.ts +0 -260
- package/resources/indexes/nativeFullTextDerivedIndexLifecycle.ts +72 -9
- package/resources/models/DESIGN.md +39 -0
- package/resources/models/Models.ts +361 -18
- package/resources/models/TestBackend.ts +56 -1
- package/resources/models/analyticsTable.ts +6 -4
- package/resources/models/backendHelpers.ts +17 -0
- package/resources/models/backendRegistry.ts +76 -21
- package/resources/models/bootstrap.ts +57 -7
- package/resources/models/decideHook.ts +135 -0
- package/resources/models/decision.ts +505 -0
- package/resources/models/decisionStore.ts +419 -0
- package/resources/models/embedHook.ts +272 -55
- package/resources/models/generativeDecision.ts +459 -0
- package/resources/models/types.ts +231 -4
- package/security/DESIGN.md +22 -2
- package/security/authn/oidc/tokenExchange.ts +6 -34
- package/security/authn/oidc/tokenUseTable.ts +27 -0
- package/security/certificateVerification/certificateVerificationSource.ts +2 -3
- package/security/certificateVerification/crlVerification.ts +96 -174
- package/security/certificateVerification/types.ts +0 -3
- package/security/certificateVerification/verificationTables.ts +124 -0
- package/security/certificateVerification/verificationUtils.ts +8 -32
- package/security/jsLoader.ts +9 -1
- package/server/DESIGN.md +27 -1
- package/server/Server.ts +2 -1
- package/server/http.ts +4 -2
- package/server/itc/serverHandlers.js +29 -1
- package/server/jobs/jobOwnership.ts +89 -0
- package/server/jobs/jobProcess.ts +8 -2
- package/server/jobs/jobs.ts +15 -4
- package/server/loadRootComponents.js +11 -0
- package/server/serverHelpers/contentTypes.ts +13 -1
- package/server/serverHelpers/serverHandlers.js +11 -2
- package/server/threads/itc.js +32 -6
- package/server/threads/manageThreads.js +268 -122
- package/server/threads/threadServer.js +13 -1
- package/server/threads/windowsProcessTree.ts +409 -0
- package/server/throttle.ts +11 -1
- package/studio/web/assets/{Chat-CveGbxe6.js → Chat-Bq60AO-g.js} +1 -1
- package/studio/web/assets/{FloatingChat-IpCFgYWL.js → FloatingChat-D4560T0p.js} +3 -3
- package/studio/web/assets/{apiToken-CS8fFTgL.js → apiToken-BEvbFPMc.js} +1 -1
- package/studio/web/assets/{applications-D7F4Jopl.js → applications-CSUVTH4E.js} +1 -1
- package/studio/web/assets/{cssMode-Daw_oLPq.js → cssMode-DJyc9mHj.js} +1 -1
- package/studio/web/assets/{editor-B3Bs1zWX.js → editor-DDIsQfj6.js} +1 -1
- package/studio/web/assets/{html-CDaQwWiE.js → html-g1BJHxLy.js} +1 -1
- package/studio/web/assets/{htmlMode-Cb6emO4U.js → htmlMode-Vh5IglCQ.js} +1 -1
- package/studio/web/assets/{index-B4g2Fu_2.js → index-DGRAzvO4.js} +5 -5
- package/studio/web/assets/{index.lazy-NwhvF1q1.js → index.lazy-vgSic7et.js} +1 -1
- package/studio/web/assets/{javascript-2_86gB9Q.js → javascript-5VIolqf7.js} +1 -1
- package/studio/web/assets/{jsonMode-DX-i86uQ.js → jsonMode-DG4zQraI.js} +1 -1
- package/studio/web/assets/{languageServices-B85WN-Ej.js → languageServices-t5FBpX-i.js} +1 -1
- package/studio/web/assets/{lspLanguageFeatures-JCWHIsKg.js → lspLanguageFeatures-DgVnNPh-.js} +1 -1
- package/studio/web/assets/{notifications-D9ejzt52.js → notifications-BeWcX04m.js} +1 -1
- package/studio/web/assets/{notifications-B7hjKhai.js → notifications-DUGWrWoO.js} +1 -1
- package/studio/web/assets/{profile-D8B6No3F.js → profile-BvUEDBzW.js} +1 -1
- package/studio/web/assets/{regions-DFazIfTK.js → regions-CB-_2m7M.js} +1 -1
- package/studio/web/assets/{register-CwFLviLF.js → register-1w1Zr3b2.js} +2 -2
- package/studio/web/assets/{setComponentFile-VnJ80SSJ.js → setComponentFile-z4-qJCbA.js} +1 -1
- package/studio/web/assets/{setup-BYQxFy-C.js → setup-CS50uJ4x.js} +2 -2
- package/studio/web/assets/{status-Cn5XjmsL.js → status-CI0wOdOE.js} +1 -1
- package/studio/web/assets/{toggleHighContrast-g9xIh6TX.js → toggleHighContrast-BsAE4jPe.js} +1 -1
- package/studio/web/assets/{tsMode-EC-n0Wqc.js → tsMode-D83Gg3cq.js} +1 -1
- package/studio/web/assets/{typescript-DHmM9JCO.js → typescript-Dfp-GrNq.js} +1 -1
- package/studio/web/assets/{useEntityRestURL-BUdnVSVv.js → useEntityRestURL-BKetlINf.js} +1 -1
- package/studio/web/assets/{workers-BVl9bBB-.js → workers-CCvmDLH3.js} +1 -1
- package/studio/web/assets/{xml-C4_sqOkX.js → xml-06pZp00U.js} +1 -1
- package/studio/web/assets/{yaml-CVkbDqtW.js → yaml-iSnWMVlV.js} +1 -1
- package/studio/web/index.html +1 -1
- package/upgrade/directives/5-3-0.ts +61 -54
- package/utility/DESIGN.md +5 -1
- package/utility/errors/hdbError.ts +56 -8
- package/utility/fsync.ts +16 -0
- package/utility/hdbTerms.ts +3 -0
- package/utility/signalling.ts +33 -4
- package/utility/when.ts +22 -0
- package/validation/configValidator.ts +36 -7
|
@@ -1,5 +1,127 @@
|
|
|
1
|
+
import { DerivedIndexLagError } from '../utility/errors/hdbError.ts';
|
|
2
|
+
|
|
1
3
|
const registrations = new WeakMap<object, Map<number, number>>();
|
|
2
4
|
const admissions = new WeakMap<object, Map<number, Array<() => string | undefined>>>();
|
|
5
|
+
type LockStore = { status?: string; tryLock(key: string): boolean; unlock(key: string): void };
|
|
6
|
+
type FenceWaitOptions = { shouldContinue?: () => boolean; timeoutMilliseconds?: number };
|
|
7
|
+
const DEFAULT_FENCE_WAIT_MILLISECONDS = 70_000;
|
|
8
|
+
|
|
9
|
+
function fullTextClearLockKey(tableId: number): string {
|
|
10
|
+
return `derived-index:fulltext:${tableId}:table-clear`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function fullTextRetirementLockKey(tableName: string): string {
|
|
14
|
+
return `derived-index:fulltext:${tableName}:retirement`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Hold this node-wide fence for the full duration of an asynchronous table clear. */
|
|
18
|
+
export function acquireFullTextClearFence(rootStore: LockStore, tableId: number): (() => void) | undefined {
|
|
19
|
+
const key = fullTextClearLockKey(tableId);
|
|
20
|
+
if (!rootStore.tryLock(key)) return;
|
|
21
|
+
let held = true;
|
|
22
|
+
return () => {
|
|
23
|
+
if (!held) return;
|
|
24
|
+
held = false;
|
|
25
|
+
rootStore.unlock(key);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Probe without waiting; callers hold the schema lock so a clear cannot start between this and persistence. */
|
|
30
|
+
export function fullTextClearInProgress(rootStore: LockStore, tableId: number): boolean {
|
|
31
|
+
const release = acquireFullTextClearFence(rootStore, tableId);
|
|
32
|
+
if (!release) return true;
|
|
33
|
+
release();
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Wait until the current clear releases its fence; callers retry admission afterwards. */
|
|
38
|
+
export function waitForFullTextClear(
|
|
39
|
+
rootStore: LockStore,
|
|
40
|
+
tableId: number,
|
|
41
|
+
options?: FenceWaitOptions
|
|
42
|
+
): Promise<boolean> {
|
|
43
|
+
return waitForFence(rootStore, () => acquireFullTextClearFence(rootStore, tableId), 'table clear', options);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Fence same-name recreation while a dropped table's native directories are being retired. */
|
|
47
|
+
export function acquireFullTextRetirementFence(rootStore: LockStore, tableName: string): (() => void) | undefined {
|
|
48
|
+
const key = fullTextRetirementLockKey(tableName);
|
|
49
|
+
if (!rootStore.tryLock(key)) return;
|
|
50
|
+
let held = true;
|
|
51
|
+
return () => {
|
|
52
|
+
if (!held) return;
|
|
53
|
+
held = false;
|
|
54
|
+
rootStore.unlock(key);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Probe under the schema lock so recreation cannot pass between the probe and catalog persistence. */
|
|
59
|
+
export function fullTextRetirementInProgress(rootStore: LockStore, tableName: string): boolean {
|
|
60
|
+
const release = acquireFullTextRetirementFence(rootStore, tableName);
|
|
61
|
+
if (!release) return true;
|
|
62
|
+
release();
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Wait until the current retirement releases its fence; the caller must recheck its generation afterwards. */
|
|
67
|
+
export function waitForFullTextRetirement(
|
|
68
|
+
rootStore: LockStore,
|
|
69
|
+
tableName: string,
|
|
70
|
+
options?: FenceWaitOptions
|
|
71
|
+
): Promise<boolean> {
|
|
72
|
+
return waitForFence(
|
|
73
|
+
rootStore,
|
|
74
|
+
() => acquireFullTextRetirementFence(rootStore, tableName),
|
|
75
|
+
`retirement of full-text storage for '${tableName}'`,
|
|
76
|
+
options
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function waitForFullTextRetirementLease(
|
|
81
|
+
rootStore: LockStore,
|
|
82
|
+
tableName: string,
|
|
83
|
+
options?: FenceWaitOptions
|
|
84
|
+
): Promise<(() => void) | undefined> {
|
|
85
|
+
return waitForFenceLease(
|
|
86
|
+
rootStore,
|
|
87
|
+
() => acquireFullTextRetirementFence(rootStore, tableName),
|
|
88
|
+
`retirement of full-text storage for '${tableName}'`,
|
|
89
|
+
options
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function waitForFence(
|
|
94
|
+
rootStore: LockStore,
|
|
95
|
+
acquire: () => (() => void) | undefined,
|
|
96
|
+
description: string,
|
|
97
|
+
options: FenceWaitOptions = {}
|
|
98
|
+
): Promise<boolean> {
|
|
99
|
+
const release = await waitForFenceLease(rootStore, acquire, description, options);
|
|
100
|
+
if (!release) return false;
|
|
101
|
+
release();
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function waitForFenceLease(
|
|
106
|
+
rootStore: LockStore,
|
|
107
|
+
acquire: () => (() => void) | undefined,
|
|
108
|
+
description: string,
|
|
109
|
+
options: FenceWaitOptions = {}
|
|
110
|
+
): Promise<(() => void) | undefined> {
|
|
111
|
+
const deadline = Date.now() + (options.timeoutMilliseconds ?? DEFAULT_FENCE_WAIT_MILLISECONDS);
|
|
112
|
+
let retryDelayMilliseconds = 1;
|
|
113
|
+
for (;;) {
|
|
114
|
+
if (options.shouldContinue && !options.shouldContinue()) return;
|
|
115
|
+
if (rootStore.status !== undefined && rootStore.status !== 'open')
|
|
116
|
+
throw new Error(`Cannot wait for ${description} on a ${rootStore.status} store`);
|
|
117
|
+
const release = acquire();
|
|
118
|
+
if (release) return release;
|
|
119
|
+
if (Date.now() >= deadline)
|
|
120
|
+
throw new DerivedIndexLagError(`Timed out waiting for ${description}; retry the operation`);
|
|
121
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMilliseconds));
|
|
122
|
+
retryDelayMilliseconds = Math.min(retryDelayMilliseconds * 2, 50);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
3
125
|
|
|
4
126
|
/** `admission` returns a reason while writes to these tables must be rejected. */
|
|
5
127
|
export function registerDerivedIndexTables(
|
|
@@ -188,6 +188,10 @@ export type DerivedIndexRegistration = {
|
|
|
188
188
|
backend: DerivedIndexBackend;
|
|
189
189
|
projections: ReadonlyMap<number, (record: unknown) => unknown>;
|
|
190
190
|
options?: DerivedIndexRunnerOptions;
|
|
191
|
+
/** Shared readiness identity when it must be narrower than the stable backend/lock identity. */
|
|
192
|
+
readinessId?: string;
|
|
193
|
+
/** False once this table generation has been superseded. Must be synchronous and allocation-free. */
|
|
194
|
+
isCurrent?: () => boolean;
|
|
191
195
|
};
|
|
192
196
|
|
|
193
197
|
/**
|
|
@@ -246,6 +250,8 @@ const READINESS_STATES: DerivedIndexReadinessState[] = [
|
|
|
246
250
|
'needs-rebuild',
|
|
247
251
|
'unavailable',
|
|
248
252
|
];
|
|
253
|
+
const READINESS_BACKEND_FAILED = READINESS_STATES.length;
|
|
254
|
+
const READINESS_RETRYING = READINESS_BACKEND_FAILED + 1;
|
|
249
255
|
const READINESS_REASONS: DerivedIndexReadinessReason[] = [
|
|
250
256
|
'none',
|
|
251
257
|
'cursor-missing',
|
|
@@ -333,6 +339,7 @@ export class DerivedIndexRuntime {
|
|
|
333
339
|
this.#listening = true;
|
|
334
340
|
}
|
|
335
341
|
runner.wake(true);
|
|
342
|
+
let releaseStarted = false;
|
|
336
343
|
return () => {
|
|
337
344
|
if (this.#runners.get(registration.backend.id) === runner) {
|
|
338
345
|
this.#runners.delete(registration.backend.id);
|
|
@@ -343,6 +350,8 @@ export class DerivedIndexRuntime {
|
|
|
343
350
|
}
|
|
344
351
|
this.#stopListeningIfIdle();
|
|
345
352
|
}
|
|
353
|
+
if (releaseStarted) return this.#retryRunnerRelease(registration.backend.id, runner);
|
|
354
|
+
releaseStarted = true;
|
|
346
355
|
return this.#track(runner, runner.stop());
|
|
347
356
|
};
|
|
348
357
|
}
|
|
@@ -417,7 +426,7 @@ export class DerivedIndexRuntime {
|
|
|
417
426
|
|
|
418
427
|
#pollCoverage(backendId: string, group: CoverageWaitGroup) {
|
|
419
428
|
try {
|
|
420
|
-
const views = getReadinessViews(this.#logStore, backendId);
|
|
429
|
+
const views = getReadinessViews(this.#logStore, this.#runners.get(backendId)?.readinessId ?? backendId);
|
|
421
430
|
const before = readReadiness(views);
|
|
422
431
|
const time = Atomics.load(views.coverage, 0);
|
|
423
432
|
const after = readReadiness(views);
|
|
@@ -443,23 +452,31 @@ export class DerivedIndexRuntime {
|
|
|
443
452
|
/** Force a rebuild (or retry one that became `unavailable`). Returns false when the backend cannot be rebuilt by the runtime. */
|
|
444
453
|
requestRebuild(backendId: string): boolean {
|
|
445
454
|
const held = this.#heldRunners.get(backendId);
|
|
446
|
-
if (held)
|
|
447
|
-
const released = held.runner.retryRelease();
|
|
448
|
-
this.#pendingStops.add(released);
|
|
449
|
-
released.then(
|
|
450
|
-
() => {
|
|
451
|
-
this.#pendingStops.delete(released);
|
|
452
|
-
this.#pendingStops.delete(held.stopped);
|
|
453
|
-
if (this.#heldRunners.get(backendId) === held) this.#heldRunners.delete(backendId);
|
|
454
|
-
},
|
|
455
|
-
() => {}
|
|
456
|
-
);
|
|
457
|
-
}
|
|
455
|
+
if (held) void this.#retryRunnerRelease(backendId, held.runner);
|
|
458
456
|
const runner = this.#runners.get(backendId);
|
|
459
457
|
if (runner) return runner.requestRebuild();
|
|
460
458
|
return held !== undefined;
|
|
461
459
|
}
|
|
462
460
|
|
|
461
|
+
#retryRunnerRelease(backendId: string, runner: DerivedIndexRunner): Promise<void> {
|
|
462
|
+
const held = this.#heldRunners.get(backendId);
|
|
463
|
+
const released = runner.retryRelease();
|
|
464
|
+
this.#pendingStops.add(released);
|
|
465
|
+
released.then(
|
|
466
|
+
() => {
|
|
467
|
+
this.#pendingStops.delete(released);
|
|
468
|
+
if (held?.runner === runner) this.#pendingStops.delete(held.stopped);
|
|
469
|
+
if (this.#heldRunners.get(backendId)?.runner === runner) this.#heldRunners.delete(backendId);
|
|
470
|
+
},
|
|
471
|
+
() => {
|
|
472
|
+
if (held?.runner === runner && held.stopped !== released) this.#pendingStops.delete(held.stopped);
|
|
473
|
+
const current = this.#heldRunners.get(backendId);
|
|
474
|
+
if (!current || current.runner === runner) this.#heldRunners.set(backendId, { runner, stopped: released });
|
|
475
|
+
}
|
|
476
|
+
);
|
|
477
|
+
return released;
|
|
478
|
+
}
|
|
479
|
+
|
|
463
480
|
/** Resolves once every runner has released ownership and its backend shutdown has settled. */
|
|
464
481
|
stop(): Promise<void> {
|
|
465
482
|
if (this.#stopping) return this.#stopping;
|
|
@@ -485,8 +502,15 @@ export class DerivedIndexRuntime {
|
|
|
485
502
|
|
|
486
503
|
#stopListening() {
|
|
487
504
|
if (!this.#listening) return;
|
|
488
|
-
|
|
489
|
-
|
|
505
|
+
try {
|
|
506
|
+
this.#logStore.rootStore.off?.('committed', this.#onCommit);
|
|
507
|
+
} catch (error) {
|
|
508
|
+
// An already-closed store cannot emit again and some native stores reject listener access
|
|
509
|
+
// after close. Preserve errors from a live store, where losing the listener would be unsafe.
|
|
510
|
+
if (this.#logStore.rootStore.status === 'open') throw error;
|
|
511
|
+
} finally {
|
|
512
|
+
this.#listening = false;
|
|
513
|
+
}
|
|
490
514
|
}
|
|
491
515
|
}
|
|
492
516
|
|
|
@@ -624,6 +648,7 @@ class DerivedIndexRunner {
|
|
|
624
648
|
#unregisterTables: () => void;
|
|
625
649
|
#ownerEpoch?: bigint;
|
|
626
650
|
#readinessBuffer: SharedReadinessBuffer;
|
|
651
|
+
#wakeBuffer: SharedReadinessBuffer;
|
|
627
652
|
#sharedViews: SharedViews;
|
|
628
653
|
#resetting?: Promise<void>;
|
|
629
654
|
status: DerivedIndexRunnerStatus = { state: 'idle' };
|
|
@@ -632,6 +657,10 @@ class DerivedIndexRunner {
|
|
|
632
657
|
return this.#registration.backend.id;
|
|
633
658
|
}
|
|
634
659
|
|
|
660
|
+
get readinessId() {
|
|
661
|
+
return this.#registration.readinessId ?? this.id;
|
|
662
|
+
}
|
|
663
|
+
|
|
635
664
|
retryRelease(): Promise<void> {
|
|
636
665
|
if (!this.#heldLock) return this.#stopResult ?? Promise.resolve();
|
|
637
666
|
this.#heldLock = false;
|
|
@@ -666,7 +695,13 @@ class DerivedIndexRunner {
|
|
|
666
695
|
typeof root?.getSync === 'function' &&
|
|
667
696
|
typeof root?.removeSync === 'function';
|
|
668
697
|
this.#lagBudget = effectiveLagBudget(options);
|
|
669
|
-
|
|
698
|
+
const notified = () => this.#notified();
|
|
699
|
+
this.#readinessBuffer = readinessBuffer(
|
|
700
|
+
logStore,
|
|
701
|
+
this.readinessId,
|
|
702
|
+
this.readinessId === this.id ? notified : undefined
|
|
703
|
+
);
|
|
704
|
+
this.#wakeBuffer = this.readinessId === this.id ? this.#readinessBuffer : wakeBuffer(logStore, this.id, notified);
|
|
670
705
|
this.#sharedViews = sharedViewsOf(this.#readinessBuffer);
|
|
671
706
|
try {
|
|
672
707
|
registration.backend.attach({
|
|
@@ -678,6 +713,7 @@ class DerivedIndexRunner {
|
|
|
678
713
|
);
|
|
679
714
|
} catch (error) {
|
|
680
715
|
this.#readinessBuffer.cancel?.();
|
|
716
|
+
if (this.#wakeBuffer !== this.#readinessBuffer) this.#wakeBuffer.cancel?.();
|
|
681
717
|
throw error;
|
|
682
718
|
}
|
|
683
719
|
this.#unregisterTables = registerDerivedIndexTables(
|
|
@@ -700,11 +736,7 @@ class DerivedIndexRunner {
|
|
|
700
736
|
if (this.#stopped || this.#rebuilding) return;
|
|
701
737
|
if (!fromBackend && !forCoverage && this.#lagBudget > 0) this.#unreadSince ??= this.#options.now();
|
|
702
738
|
if (this.status.state === 'unavailable') {
|
|
703
|
-
if (
|
|
704
|
-
this.#heldLock ||
|
|
705
|
-
Atomics.load(this.#shared().words, READINESS_STATE) === READINESS_STATES.indexOf('unavailable')
|
|
706
|
-
)
|
|
707
|
-
return;
|
|
739
|
+
if (this.#heldLock || isUnavailableReadinessState(Atomics.load(this.#shared().words, READINESS_STATE))) return;
|
|
708
740
|
this.status = { state: 'idle' };
|
|
709
741
|
}
|
|
710
742
|
// A shared rebuild request must reach an owner parked on backpressure or backoff at its next wake.
|
|
@@ -742,6 +774,7 @@ class DerivedIndexRunner {
|
|
|
742
774
|
try {
|
|
743
775
|
this.#unsubscribeBackend?.();
|
|
744
776
|
this.#readinessBuffer.cancel?.();
|
|
777
|
+
if (this.#wakeBuffer !== this.#readinessBuffer) this.#wakeBuffer.cancel?.();
|
|
745
778
|
} catch (error) {
|
|
746
779
|
logger.warn?.(`Derived index '${this.id}' cleanup hook threw`, error);
|
|
747
780
|
}
|
|
@@ -883,9 +916,9 @@ class DerivedIndexRunner {
|
|
|
883
916
|
return true;
|
|
884
917
|
}
|
|
885
918
|
// The owner may be another worker that never idles: leave the request where every runner looks,
|
|
886
|
-
// and notify
|
|
919
|
+
// and notify every generation sharing the stable runner lock.
|
|
887
920
|
Atomics.store(this.#shared().words, READINESS_REBUILD_REQUEST, 1);
|
|
888
|
-
this.#
|
|
921
|
+
this.#wakeBuffer.notify?.();
|
|
889
922
|
this.wake(true);
|
|
890
923
|
return true;
|
|
891
924
|
}
|
|
@@ -927,12 +960,14 @@ class DerivedIndexRunner {
|
|
|
927
960
|
* The lock is taken without an unlock callback. rocksdb-js queues such a callback as a
|
|
928
961
|
* thread-safe function of the caller's env, and on Node 22 a callback left behind by a worker that
|
|
929
962
|
* was terminated aborts the process when another thread unlocks (HarperFast/rocksdb-js, pending).
|
|
930
|
-
* A successor is woken by the releasing owner's `notify()` on the
|
|
931
|
-
* tolerates a dead listener's env — and by the retry timer below.
|
|
963
|
+
* A successor is woken by the releasing owner's `notify()` on the stable-id wake buffer — which
|
|
964
|
+
* tolerates a dead listener's env — and by the retry timer below. Registrations without a
|
|
965
|
+
* generation-specific readiness id keep using the readiness buffer itself.
|
|
932
966
|
*/
|
|
933
967
|
#acquire() {
|
|
934
968
|
// Commit wakes are frequent; neither a parked nor a backing-off runner may re-probe on each one.
|
|
935
969
|
if (this.#waitingForLock || this.#lockBackoff) return;
|
|
970
|
+
if (this.#registration.isCurrent && !this.#registration.isCurrent()) return;
|
|
936
971
|
if (this.#releasing) {
|
|
937
972
|
this.#releasing.then(() => this.wake(true));
|
|
938
973
|
return;
|
|
@@ -982,6 +1017,15 @@ class DerivedIndexRunner {
|
|
|
982
1017
|
this.#reachedEndOfLog = false;
|
|
983
1018
|
try {
|
|
984
1019
|
if (!reviving) this.#ownerEpoch = this.#mintEpoch();
|
|
1020
|
+
// A worker that could not construct this generation may have published a setup-only
|
|
1021
|
+
// failure before this healthy backend acquired the stable runner lock. Ownership is
|
|
1022
|
+
// stronger evidence: clear only that sentinel, never a runner-published unavailable state.
|
|
1023
|
+
Atomics.compareExchange(
|
|
1024
|
+
this.#shared().words,
|
|
1025
|
+
READINESS_STATE,
|
|
1026
|
+
READINESS_BACKEND_FAILED,
|
|
1027
|
+
READINESS_STATES.indexOf('unknown')
|
|
1028
|
+
);
|
|
985
1029
|
this.status = { state: 'running', ownerEpoch: this.#ownerEpoch };
|
|
986
1030
|
const condemned = this.#readCondemnation();
|
|
987
1031
|
const shared = this.getReadiness();
|
|
@@ -1101,6 +1145,10 @@ class DerivedIndexRunner {
|
|
|
1101
1145
|
|
|
1102
1146
|
#drain() {
|
|
1103
1147
|
if (!this.#owned || this.#stopped || this.#rebuilding) return;
|
|
1148
|
+
if (this.#registration.isCurrent && !this.#registration.isCurrent()) {
|
|
1149
|
+
this.#release();
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1104
1152
|
if (this.#canRebuild() && this.#takeSharedRebuildRequest()) {
|
|
1105
1153
|
if (this.#rebuildTimer) {
|
|
1106
1154
|
clearTimeout(this.#rebuildTimer);
|
|
@@ -2083,10 +2131,10 @@ class DerivedIndexRunner {
|
|
|
2083
2131
|
logger.error(`Failed to release derived index runner '${backend.id}'`, error);
|
|
2084
2132
|
}
|
|
2085
2133
|
// A skip left standing by an absent or throwing `notify` swallows a peer's release instead.
|
|
2086
|
-
if (this.#
|
|
2134
|
+
if (this.#wakeBuffer.notify) {
|
|
2087
2135
|
this.#skipNextNotify = !this.#stopped;
|
|
2088
2136
|
try {
|
|
2089
|
-
this.#
|
|
2137
|
+
this.#wakeBuffer.notify();
|
|
2090
2138
|
} catch (error) {
|
|
2091
2139
|
this.#skipNextNotify = false;
|
|
2092
2140
|
logger.warn?.(`Derived index '${backend.id}' could not notify peers of its release`, error);
|
|
@@ -2134,6 +2182,16 @@ function readinessBuffer(
|
|
|
2134
2182
|
) as SharedReadinessBuffer;
|
|
2135
2183
|
}
|
|
2136
2184
|
|
|
2185
|
+
function wakeBuffer(
|
|
2186
|
+
logStore: RocksTransactionLogStore,
|
|
2187
|
+
backendId: string,
|
|
2188
|
+
callback: () => void
|
|
2189
|
+
): SharedReadinessBuffer {
|
|
2190
|
+
return logStore.getUserSharedBuffer(`derived-index:${backendId}:wake`, new ArrayBuffer(1), {
|
|
2191
|
+
callback,
|
|
2192
|
+
}) as SharedReadinessBuffer;
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2137
2195
|
type SharedViews = {
|
|
2138
2196
|
words: Int32Array;
|
|
2139
2197
|
epoch: BigInt64Array;
|
|
@@ -2151,12 +2209,19 @@ function sharedViewsOf(buffer: ArrayBufferLike): SharedViews {
|
|
|
2151
2209
|
const readinessViews = new WeakMap<object, Map<string, SharedViews>>();
|
|
2152
2210
|
|
|
2153
2211
|
function readReadiness({ words, epoch }: SharedViews): DerivedIndexReadiness {
|
|
2154
|
-
const
|
|
2155
|
-
const
|
|
2212
|
+
const stateIndex = Atomics.load(words, READINESS_STATE);
|
|
2213
|
+
const setupFailed = stateIndex === READINESS_BACKEND_FAILED;
|
|
2214
|
+
const retrying = stateIndex === READINESS_RETRYING;
|
|
2215
|
+
const state = setupFailed ? 'unavailable' : retrying ? 'unknown' : (READINESS_STATES[stateIndex] ?? 'unknown');
|
|
2216
|
+
const reason = setupFailed
|
|
2217
|
+
? 'backend-failed'
|
|
2218
|
+
: retrying
|
|
2219
|
+
? 'none'
|
|
2220
|
+
: (READINESS_REASONS[Atomics.load(words, READINESS_REASON)] ?? 'none');
|
|
2156
2221
|
const readiness: DerivedIndexReadiness = {
|
|
2157
2222
|
state,
|
|
2158
2223
|
ownerEpoch: Atomics.load(epoch, 0),
|
|
2159
|
-
rebuildAttempts: Atomics.load(words, READINESS_ATTEMPTS),
|
|
2224
|
+
rebuildAttempts: retrying || setupFailed ? 0 : Atomics.load(words, READINESS_ATTEMPTS),
|
|
2160
2225
|
};
|
|
2161
2226
|
if (reason !== 'none') readiness.reason = reason;
|
|
2162
2227
|
return readiness;
|
|
@@ -2170,6 +2235,68 @@ export function readDerivedIndexReadiness(
|
|
|
2170
2235
|
return readReadiness(getReadinessViews(logStore, backendId));
|
|
2171
2236
|
}
|
|
2172
2237
|
|
|
2238
|
+
/** Publish setup-time state before a backend runner exists. */
|
|
2239
|
+
export function publishDerivedIndexReadiness(
|
|
2240
|
+
logStore: RocksTransactionLogStore,
|
|
2241
|
+
backendId: string,
|
|
2242
|
+
state: DerivedIndexReadinessState,
|
|
2243
|
+
reason: DerivedIndexReadinessReason = 'none'
|
|
2244
|
+
): void {
|
|
2245
|
+
const views = getReadinessViews(logStore, backendId);
|
|
2246
|
+
if (state === 'unknown') Atomics.store(views.words, READINESS_ATTEMPTS, 0);
|
|
2247
|
+
Atomics.store(views.words, READINESS_REASON, READINESS_REASONS.indexOf(reason));
|
|
2248
|
+
Atomics.store(views.words, READINESS_STATE, READINESS_STATES.indexOf(state));
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
/** Publish a setup failure only while no elected runner has published a stronger state. */
|
|
2252
|
+
export function publishDerivedIndexUnavailableIfUnknown(
|
|
2253
|
+
logStore: RocksTransactionLogStore,
|
|
2254
|
+
backendId: string
|
|
2255
|
+
): boolean {
|
|
2256
|
+
const { words, epoch } = getReadinessViews(logStore, backendId);
|
|
2257
|
+
// RETRYING is an explicit setup retry. Epochs are monotonic, so a prior
|
|
2258
|
+
// owner must not prevent that retry from returning to an observable failure.
|
|
2259
|
+
const retryEpoch = Atomics.load(epoch, 0);
|
|
2260
|
+
if (
|
|
2261
|
+
Atomics.compareExchange(words, READINESS_STATE, READINESS_RETRYING, READINESS_BACKEND_FAILED) === READINESS_RETRYING
|
|
2262
|
+
) {
|
|
2263
|
+
// Close the same owner-election race as the unknown-state path below. A
|
|
2264
|
+
// runner that acquired this epoch owns readiness, even if its worker has
|
|
2265
|
+
// not published ready yet.
|
|
2266
|
+
if (Atomics.load(epoch, 0) !== retryEpoch) {
|
|
2267
|
+
Atomics.compareExchange(words, READINESS_STATE, READINESS_BACKEND_FAILED, READINESS_STATES.indexOf('unknown'));
|
|
2268
|
+
return false;
|
|
2269
|
+
}
|
|
2270
|
+
return true;
|
|
2271
|
+
}
|
|
2272
|
+
if (Atomics.load(epoch, 0) !== 0n) return false;
|
|
2273
|
+
const published =
|
|
2274
|
+
Atomics.compareExchange(words, READINESS_STATE, READINESS_STATES.indexOf('unknown'), READINESS_BACKEND_FAILED) ===
|
|
2275
|
+
READINESS_STATES.indexOf('unknown');
|
|
2276
|
+
if (!published) return false;
|
|
2277
|
+
// Close the race with an owner acquiring between the epoch probe and the state CAS.
|
|
2278
|
+
if (Atomics.load(epoch, 0) !== 0n) {
|
|
2279
|
+
Atomics.compareExchange(words, READINESS_STATE, READINESS_BACKEND_FAILED, READINESS_STATES.indexOf('unknown'));
|
|
2280
|
+
return false;
|
|
2281
|
+
}
|
|
2282
|
+
return true;
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
/** Rearm setup only while no peer has replaced the unavailable state. */
|
|
2286
|
+
export function retryDerivedIndexUnavailable(logStore: RocksTransactionLogStore, backendId: string): boolean {
|
|
2287
|
+
const { words } = getReadinessViews(logStore, backendId);
|
|
2288
|
+
const unavailable = READINESS_STATES.indexOf('unavailable');
|
|
2289
|
+
if (Atomics.compareExchange(words, READINESS_STATE, unavailable, READINESS_RETRYING) === unavailable) return true;
|
|
2290
|
+
return (
|
|
2291
|
+
Atomics.compareExchange(words, READINESS_STATE, READINESS_BACKEND_FAILED, READINESS_RETRYING) ===
|
|
2292
|
+
READINESS_BACKEND_FAILED
|
|
2293
|
+
);
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
function isUnavailableReadinessState(stateIndex: number): boolean {
|
|
2297
|
+
return stateIndex === READINESS_STATES.indexOf('unavailable') || stateIndex === READINESS_BACKEND_FAILED;
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2173
2300
|
function getReadinessViews(logStore: RocksTransactionLogStore, backendId: string): SharedViews {
|
|
2174
2301
|
let byBackend = readinessViews.get(logStore);
|
|
2175
2302
|
if (!byBackend) readinessViews.set(logStore, (byBackend = new Map()));
|