@harperfast/harper 5.2.13 → 5.3.0-beta.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/agent/mcpTools.ts +1 -1
- package/agent/session.ts +25 -14
- package/bin/cliOperations.ts +58 -9
- package/bin/copyDb.ts +282 -59
- package/bin/deploySetup.ts +16 -5
- package/bin/harper.ts +1 -1
- package/bin/help.ts +4 -1
- package/bin/lite.ts +4 -1
- package/bin/restart.ts +120 -4
- package/bin/run.ts +6 -11
- package/bin/upgrade.js +7 -3
- package/bin/workloadIdentity.ts +119 -0
- package/components/Application.ts +3436 -242
- package/components/ApplicationScope.ts +8 -0
- package/components/EntryHandler.ts +59 -39
- package/components/OptionsWatcher.ts +440 -98
- package/components/RuntimeModuleTracker.ts +38 -7
- package/components/Scope.ts +56 -15
- package/components/awaitRestart.ts +84 -0
- package/components/componentLoader.ts +381 -32
- package/components/componentPreparationLock.ts +16 -5
- package/components/deploymentOperations.ts +4 -1
- package/components/deploymentRecorder.ts +9 -2
- package/components/mcp/adapters/harperHttp.ts +4 -0
- package/components/mcp/listChanged.ts +4 -0
- package/components/mcp/toolRegistry.ts +2 -0
- package/components/mcp/tools/operations.ts +9 -0
- package/components/mcp/tools/schemas/operationDescriptions.ts +2 -2
- package/components/operations.js +537 -113
- package/components/operationsValidation.js +98 -3
- package/components/packageComponent.ts +25 -1
- package/components/requestRestart.ts +11 -0
- package/components/status/ComponentStatusRegistry.ts +59 -0
- package/config/RootConfigWatcher.ts +240 -40
- package/config/configReadRetry.ts +62 -0
- package/config/configUtils.ts +357 -48
- package/config/harperConfigEnvVars.ts +170 -27
- package/config/parseConfigFile.ts +34 -0
- package/config/readConfigFileSync.ts +44 -0
- package/config/watcherArming.ts +59 -0
- package/config-root.schema.json +33 -0
- package/dataLayer/blobBackup.ts +160 -50
- package/dataLayer/delete.ts +6 -1
- package/dataLayer/harperBridge/ResourceBridge.ts +80 -10
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
- package/dataLayer/hdbInfoController.ts +34 -1
- package/dataLayer/insert.ts +44 -1
- package/dataLayer/rocksdbBackup.ts +53 -10
- package/dataLayer/schema.ts +11 -1
- package/dataLayer/schemaDescribe.ts +8 -1
- package/dist/agent/mcpTools.js +1 -1
- package/dist/agent/mcpTools.js.map +1 -1
- package/dist/agent/session.d.ts +22 -0
- package/dist/agent/session.js +26 -15
- package/dist/agent/session.js.map +1 -1
- package/dist/bin/cliOperations.js +61 -9
- package/dist/bin/cliOperations.js.map +1 -1
- package/dist/bin/copyDb.d.ts +12 -1
- package/dist/bin/copyDb.js +248 -60
- package/dist/bin/copyDb.js.map +1 -1
- package/dist/bin/deploySetup.d.ts +2 -0
- package/dist/bin/deploySetup.js +11 -3
- package/dist/bin/deploySetup.js.map +1 -1
- package/dist/bin/harper.js +1 -1
- package/dist/bin/harper.js.map +1 -1
- package/dist/bin/help.js +4 -1
- package/dist/bin/help.js.map +1 -1
- package/dist/bin/lite.js +4 -1
- package/dist/bin/lite.js.map +1 -1
- package/dist/bin/restart.js +91 -6
- package/dist/bin/restart.js.map +1 -1
- package/dist/bin/run.js +4 -10
- package/dist/bin/run.js.map +1 -1
- package/dist/bin/upgrade.js +4 -3
- package/dist/bin/upgrade.js.map +1 -1
- package/dist/bin/workloadIdentity.d.ts +18 -0
- package/dist/bin/workloadIdentity.js +100 -0
- package/dist/bin/workloadIdentity.js.map +1 -0
- package/dist/components/Application.d.ts +235 -17
- package/dist/components/Application.js +3038 -238
- package/dist/components/Application.js.map +1 -1
- package/dist/components/ApplicationScope.d.ts +8 -0
- package/dist/components/ApplicationScope.js +7 -0
- package/dist/components/ApplicationScope.js.map +1 -1
- package/dist/components/EntryHandler.js +26 -10
- package/dist/components/EntryHandler.js.map +1 -1
- package/dist/components/OptionsWatcher.d.ts +4 -0
- package/dist/components/OptionsWatcher.js +440 -99
- package/dist/components/OptionsWatcher.js.map +1 -1
- package/dist/components/RuntimeModuleTracker.js +40 -6
- package/dist/components/RuntimeModuleTracker.js.map +1 -1
- package/dist/components/Scope.js +52 -13
- package/dist/components/Scope.js.map +1 -1
- package/dist/components/awaitRestart.d.ts +33 -0
- package/dist/components/awaitRestart.js +61 -0
- package/dist/components/awaitRestart.js.map +1 -0
- package/dist/components/componentLoader.d.ts +38 -1
- package/dist/components/componentLoader.js +313 -24
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/componentPreparationLock.d.ts +5 -0
- package/dist/components/componentPreparationLock.js +14 -6
- package/dist/components/componentPreparationLock.js.map +1 -1
- package/dist/components/deploymentOperations.js +4 -1
- package/dist/components/deploymentOperations.js.map +1 -1
- package/dist/components/deploymentRecorder.d.ts +4 -2
- package/dist/components/deploymentRecorder.js +1 -0
- package/dist/components/deploymentRecorder.js.map +1 -1
- package/dist/components/mcp/adapters/harperHttp.js +4 -0
- package/dist/components/mcp/adapters/harperHttp.js.map +1 -1
- package/dist/components/mcp/listChanged.js +5 -0
- package/dist/components/mcp/listChanged.js.map +1 -1
- package/dist/components/mcp/toolRegistry.d.ts +1 -0
- package/dist/components/mcp/toolRegistry.js.map +1 -1
- package/dist/components/mcp/tools/operations.d.ts +5 -0
- package/dist/components/mcp/tools/operations.js +9 -0
- package/dist/components/mcp/tools/operations.js.map +1 -1
- package/dist/components/mcp/tools/schemas/operationDescriptions.js +2 -2
- package/dist/components/mcp/tools/schemas/operationDescriptions.js.map +1 -1
- package/dist/components/operations.d.ts +28 -0
- package/dist/components/operations.js +476 -113
- package/dist/components/operations.js.map +1 -1
- package/dist/components/operationsValidation.js +97 -3
- package/dist/components/operationsValidation.js.map +1 -1
- package/dist/components/packageComponent.js +24 -0
- package/dist/components/packageComponent.js.map +1 -1
- package/dist/components/requestRestart.d.ts +1 -0
- package/dist/components/requestRestart.js +7 -0
- package/dist/components/requestRestart.js.map +1 -1
- package/dist/components/status/ComponentStatusRegistry.d.ts +0 -4
- package/dist/components/status/ComponentStatusRegistry.js +63 -0
- package/dist/components/status/ComponentStatusRegistry.js.map +1 -1
- package/dist/config/RootConfigWatcher.d.ts +9 -1
- package/dist/config/RootConfigWatcher.js +228 -37
- package/dist/config/RootConfigWatcher.js.map +1 -1
- package/dist/config/configReadRetry.d.ts +8 -0
- package/dist/config/configReadRetry.js +62 -0
- package/dist/config/configReadRetry.js.map +1 -0
- package/dist/config/configUtils.d.ts +11 -2
- package/dist/config/configUtils.js +304 -47
- package/dist/config/configUtils.js.map +1 -1
- package/dist/config/harperConfigEnvVars.d.ts +16 -0
- package/dist/config/harperConfigEnvVars.js +162 -25
- package/dist/config/harperConfigEnvVars.js.map +1 -1
- package/dist/config/parseConfigFile.d.ts +4 -0
- package/dist/config/parseConfigFile.js +35 -0
- package/dist/config/parseConfigFile.js.map +1 -0
- package/dist/config/readConfigFileSync.d.ts +1 -0
- package/dist/config/readConfigFileSync.js +47 -0
- package/dist/config/readConfigFileSync.js.map +1 -0
- package/dist/config/watcherArming.d.ts +15 -0
- package/dist/config/watcherArming.js +59 -0
- package/dist/config/watcherArming.js.map +1 -0
- package/dist/dataLayer/blobBackup.d.ts +49 -20
- package/dist/dataLayer/blobBackup.js +139 -50
- package/dist/dataLayer/blobBackup.js.map +1 -1
- package/dist/dataLayer/delete.js +1 -1
- package/dist/dataLayer/delete.js.map +1 -1
- package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +14 -1
- package/dist/dataLayer/harperBridge/ResourceBridge.js +72 -12
- package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
- package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.d.ts +3 -1
- package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +3 -1
- package/dist/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js.map +1 -1
- package/dist/dataLayer/hdbInfoController.d.ts +10 -0
- package/dist/dataLayer/hdbInfoController.js +30 -1
- package/dist/dataLayer/hdbInfoController.js.map +1 -1
- package/dist/dataLayer/insert.d.ts +9 -1
- package/dist/dataLayer/insert.js +30 -0
- package/dist/dataLayer/insert.js.map +1 -1
- package/dist/dataLayer/rocksdbBackup.d.ts +2 -2
- package/dist/dataLayer/rocksdbBackup.js +45 -8
- package/dist/dataLayer/rocksdbBackup.js.map +1 -1
- package/dist/dataLayer/schema.js +8 -0
- package/dist/dataLayer/schema.js.map +1 -1
- package/dist/dataLayer/schemaDescribe.js +8 -1
- package/dist/dataLayer/schemaDescribe.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/json/systemSchema.json +55 -0
- package/dist/resources/DatabaseTransaction.d.ts +77 -0
- package/dist/resources/DatabaseTransaction.js +586 -54
- package/dist/resources/DatabaseTransaction.js.map +1 -1
- package/dist/resources/LMDBTransaction.d.ts +2 -1
- package/dist/resources/LMDBTransaction.js +43 -6
- package/dist/resources/LMDBTransaction.js.map +1 -1
- package/dist/resources/PrimaryRocksDatabase.d.ts +1 -0
- package/dist/resources/PrimaryRocksDatabase.js +49 -5
- package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
- package/dist/resources/RecordEncoder.d.ts +20 -0
- package/dist/resources/RecordEncoder.js +110 -9
- package/dist/resources/RecordEncoder.js.map +1 -1
- package/dist/resources/RequestTarget.d.ts +2 -0
- package/dist/resources/RequestTarget.js.map +1 -1
- package/dist/resources/Resource.js +117 -24
- package/dist/resources/Resource.js.map +1 -1
- package/dist/resources/ResourceInterface.d.ts +28 -1
- package/dist/resources/ResourceInterface.js.map +1 -1
- package/dist/resources/RocksIndexStore.d.ts +6 -1
- package/dist/resources/RocksIndexStore.js +24 -9
- package/dist/resources/RocksIndexStore.js.map +1 -1
- package/dist/resources/RocksTransactionLogStore.d.ts +24 -1
- package/dist/resources/RocksTransactionLogStore.js +160 -49
- package/dist/resources/RocksTransactionLogStore.js.map +1 -1
- package/dist/resources/Table.d.ts +165 -10
- package/dist/resources/Table.js +1805 -303
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/write.js +10 -3
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/auditStore.d.ts +181 -2
- package/dist/resources/auditStore.js +640 -29
- package/dist/resources/auditStore.js.map +1 -1
- package/dist/resources/blob.d.ts +129 -9
- package/dist/resources/blob.js +992 -114
- package/dist/resources/blob.js.map +1 -1
- package/dist/resources/branchDatabase.d.ts +48 -0
- package/dist/resources/branchDatabase.js +892 -0
- package/dist/resources/branchDatabase.js.map +1 -0
- package/dist/resources/crdt.js +50 -12
- package/dist/resources/crdt.js.map +1 -1
- package/dist/resources/dataLoader.js +3 -4
- package/dist/resources/dataLoader.js.map +1 -1
- package/dist/resources/databases.d.ts +157 -14
- package/dist/resources/databases.js +1462 -325
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/defineTable.d.ts +10 -2
- package/dist/resources/defineTable.js +9 -1
- package/dist/resources/defineTable.js.map +1 -1
- package/dist/resources/derivedIndexRegistry.d.ts +5 -0
- package/dist/resources/derivedIndexRegistry.js +68 -0
- package/dist/resources/derivedIndexRegistry.js.map +1 -0
- package/dist/resources/derivedIndexRuntime.d.ts +215 -0
- package/dist/resources/derivedIndexRuntime.js +2027 -0
- package/dist/resources/derivedIndexRuntime.js.map +1 -0
- package/dist/resources/graphql.d.ts +1 -1
- package/dist/resources/graphql.js +52 -16
- package/dist/resources/graphql.js.map +1 -1
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +103 -9
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +854 -41
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
- package/dist/resources/indexes/hnswDerivedIndex.d.ts +67 -0
- package/dist/resources/indexes/hnswDerivedIndex.js +464 -0
- package/dist/resources/indexes/hnswDerivedIndex.js.map +1 -0
- package/dist/resources/indexes/hnswPlaneBinding.d.ts +65 -0
- package/dist/resources/indexes/hnswPlaneBinding.js +91 -0
- package/dist/resources/indexes/hnswPlaneBinding.js.map +1 -0
- package/dist/resources/longLivedTransactions.d.ts +71 -0
- package/dist/resources/longLivedTransactions.js +358 -0
- package/dist/resources/longLivedTransactions.js.map +1 -0
- package/dist/resources/models/backendRegistry.d.ts +26 -0
- package/dist/resources/models/backendRegistry.js +60 -2
- package/dist/resources/models/backendRegistry.js.map +1 -1
- package/dist/resources/models/bootstrap.d.ts +33 -1
- package/dist/resources/models/bootstrap.js +416 -31
- package/dist/resources/models/bootstrap.js.map +1 -1
- package/dist/resources/nodeIdMapping.d.ts +5 -0
- package/dist/resources/nodeIdMapping.js +49 -0
- package/dist/resources/nodeIdMapping.js.map +1 -1
- package/dist/resources/recordLock.d.ts +123 -0
- package/dist/resources/recordLock.js +315 -0
- package/dist/resources/recordLock.js.map +1 -0
- package/dist/resources/recordLockCoordinator.d.ts +557 -0
- package/dist/resources/recordLockCoordinator.js +2565 -0
- package/dist/resources/recordLockCoordinator.js.map +1 -0
- package/dist/resources/replayLogs.d.ts +14 -1
- package/dist/resources/replayLogs.js +157 -24
- package/dist/resources/replayLogs.js.map +1 -1
- package/dist/resources/replayLogsGuards.d.ts +94 -7
- package/dist/resources/replayLogsGuards.js +111 -7
- package/dist/resources/replayLogsGuards.js.map +1 -1
- package/dist/resources/replicatedApplyFailure.d.ts +16 -0
- package/dist/resources/replicatedApplyFailure.js +63 -0
- package/dist/resources/replicatedApplyFailure.js.map +1 -0
- package/dist/resources/scheduler/scheduler.js +3 -3
- package/dist/resources/scheduler/scheduler.js.map +1 -1
- package/dist/resources/search.d.ts +10 -4
- package/dist/resources/search.js +283 -37
- package/dist/resources/search.js.map +1 -1
- package/dist/resources/tracked.d.ts +5 -1
- package/dist/resources/tracked.js +74 -23
- package/dist/resources/tracked.js.map +1 -1
- package/dist/resources/transactionBroadcast.d.ts +1 -1
- package/dist/resources/transactionBroadcast.js +2 -2
- package/dist/resources/transactionBroadcast.js.map +1 -1
- package/dist/security/auth.js +61 -30
- package/dist/security/auth.js.map +1 -1
- package/dist/security/authn/oidc/claims.d.ts +22 -0
- package/dist/security/authn/oidc/claims.js +71 -0
- package/dist/security/authn/oidc/claims.js.map +1 -0
- package/dist/security/authn/oidc/identityToken.d.ts +27 -0
- package/dist/security/authn/oidc/identityToken.js +111 -0
- package/dist/security/authn/oidc/identityToken.js.map +1 -0
- package/dist/security/authn/oidc/jwks.d.ts +25 -0
- package/dist/security/authn/oidc/jwks.js +261 -0
- package/dist/security/authn/oidc/jwks.js.map +1 -0
- package/dist/security/authn/oidc/providers/generic.d.ts +13 -0
- package/dist/security/authn/oidc/providers/generic.js +34 -0
- package/dist/security/authn/oidc/providers/generic.js.map +1 -0
- package/dist/security/authn/oidc/providers/githubActions.d.ts +11 -0
- package/dist/security/authn/oidc/providers/githubActions.js +129 -0
- package/dist/security/authn/oidc/providers/githubActions.js.map +1 -0
- package/dist/security/authn/oidc/providers/index.d.ts +37 -0
- package/dist/security/authn/oidc/providers/index.js +24 -0
- package/dist/security/authn/oidc/providers/index.js.map +1 -0
- package/dist/security/authn/oidc/tokenExchange.d.ts +12 -0
- package/dist/security/authn/oidc/tokenExchange.js +306 -0
- package/dist/security/authn/oidc/tokenExchange.js.map +1 -0
- package/dist/security/authn/oidc/trustPolicyOperations.d.ts +49 -0
- package/dist/security/authn/oidc/trustPolicyOperations.js +358 -0
- package/dist/security/authn/oidc/trustPolicyOperations.js.map +1 -0
- package/dist/security/authn/oidc/types.d.ts +38 -0
- package/dist/security/authn/oidc/types.js +6 -0
- package/dist/security/authn/oidc/types.js.map +1 -0
- package/dist/security/certificateVerification/index.js +40 -11
- package/dist/security/certificateVerification/index.js.map +1 -1
- package/dist/security/certificateVerification/trustedIssuers.d.ts +24 -0
- package/dist/security/certificateVerification/trustedIssuers.js +79 -0
- package/dist/security/certificateVerification/trustedIssuers.js.map +1 -0
- package/dist/security/certificateVerification/types.d.ts +1 -0
- package/dist/security/credentialProvenance.d.ts +35 -0
- package/dist/security/credentialProvenance.js +51 -0
- package/dist/security/credentialProvenance.js.map +1 -0
- package/dist/security/credentialRejection.d.ts +4 -0
- package/dist/security/credentialRejection.js +24 -0
- package/dist/security/credentialRejection.js.map +1 -0
- package/dist/security/deferredAuthentication.d.ts +36 -0
- package/dist/security/deferredAuthentication.js +70 -0
- package/dist/security/deferredAuthentication.js.map +1 -0
- package/dist/security/impersonation.d.ts +21 -0
- package/dist/security/impersonation.js +108 -9
- package/dist/security/impersonation.js.map +1 -1
- package/dist/security/jsLoader.d.ts +6 -0
- package/dist/security/jsLoader.js +77 -15
- package/dist/security/jsLoader.js.map +1 -1
- package/dist/security/keys.js +301 -71
- package/dist/security/keys.js.map +1 -1
- package/dist/security/operationScope.d.ts +21 -0
- package/dist/security/operationScope.js +36 -0
- package/dist/security/operationScope.js.map +1 -0
- package/dist/security/permissionsTranslator.js +21 -0
- package/dist/security/permissionsTranslator.js.map +1 -1
- package/dist/security/tokenAuthentication.d.ts +19 -1
- package/dist/security/tokenAuthentication.js +191 -10
- package/dist/security/tokenAuthentication.js.map +1 -1
- package/dist/security/user.js +4 -3
- package/dist/security/user.js.map +1 -1
- package/dist/server/DurableSubscriptionsSession.d.ts +2 -2
- package/dist/server/DurableSubscriptionsSession.js +67 -10
- package/dist/server/DurableSubscriptionsSession.js.map +1 -1
- package/dist/server/REST.js +106 -2
- package/dist/server/REST.js.map +1 -1
- package/dist/server/graphqlQuerying.js +4 -0
- package/dist/server/graphqlQuerying.js.map +1 -1
- package/dist/server/http.d.ts +16 -1
- package/dist/server/http.js +122 -17
- package/dist/server/http.js.map +1 -1
- package/dist/server/itc/serverHandlers.js +8 -1
- package/dist/server/itc/serverHandlers.js.map +1 -1
- package/dist/server/jobs/jobProcess.js +6 -2
- package/dist/server/jobs/jobProcess.js.map +1 -1
- package/dist/server/jobs/jobs.js +4 -1
- package/dist/server/jobs/jobs.js.map +1 -1
- package/dist/server/liveSubscriptionAuth.d.ts +26 -4
- package/dist/server/liveSubscriptionAuth.js +105 -39
- package/dist/server/liveSubscriptionAuth.js.map +1 -1
- package/dist/server/loadRootComponents.js +49 -10
- package/dist/server/loadRootComponents.js.map +1 -1
- package/dist/server/mqtt.d.ts +2 -0
- package/dist/server/mqtt.js +165 -30
- package/dist/server/mqtt.js.map +1 -1
- package/dist/server/nodeName.d.ts +2 -0
- package/dist/server/nodeName.js +107 -23
- package/dist/server/nodeName.js.map +1 -1
- package/dist/server/serverHelpers/Headers.d.ts +27 -0
- package/dist/server/serverHelpers/Headers.js +145 -1
- package/dist/server/serverHelpers/Headers.js.map +1 -1
- package/dist/server/serverHelpers/NodeAdapterResponse.d.ts +48 -0
- package/dist/server/serverHelpers/NodeAdapterResponse.js +220 -0
- package/dist/server/serverHelpers/NodeAdapterResponse.js.map +1 -0
- package/dist/server/serverHelpers/Request.d.ts +5 -10
- package/dist/server/serverHelpers/Request.js +38 -136
- package/dist/server/serverHelpers/Request.js.map +1 -1
- package/dist/server/serverHelpers/contentTypes.d.ts +11 -0
- package/dist/server/serverHelpers/contentTypes.js +221 -40
- package/dist/server/serverHelpers/contentTypes.js.map +1 -1
- package/dist/server/serverHelpers/deployValidationState.d.ts +3 -0
- package/dist/server/serverHelpers/deployValidationState.js +9 -19
- package/dist/server/serverHelpers/deployValidationState.js.map +1 -1
- package/dist/server/serverHelpers/operationAuthorizationState.d.ts +12 -0
- package/dist/server/serverHelpers/operationAuthorizationState.js +24 -2
- package/dist/server/serverHelpers/operationAuthorizationState.js.map +1 -1
- package/dist/server/serverHelpers/registeredOperations.d.ts +5 -4
- package/dist/server/serverHelpers/registeredOperations.js +74 -21
- package/dist/server/serverHelpers/registeredOperations.js.map +1 -1
- package/dist/server/serverHelpers/requestSanitization.d.ts +11 -0
- package/dist/server/serverHelpers/requestSanitization.js +20 -0
- package/dist/server/serverHelpers/requestSanitization.js.map +1 -0
- package/dist/server/serverHelpers/serverHandlers.js +6 -3
- package/dist/server/serverHelpers/serverHandlers.js.map +1 -1
- package/dist/server/serverHelpers/serverUtilities.d.ts +18 -0
- package/dist/server/serverHelpers/serverUtilities.js +178 -29
- package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
- package/dist/server/serverHelpers/sharedMessageEncoding.d.ts +67 -0
- package/dist/server/serverHelpers/sharedMessageEncoding.js +280 -0
- package/dist/server/serverHelpers/sharedMessageEncoding.js.map +1 -0
- package/dist/server/serverHelpers/uwsServer.js +19 -1
- package/dist/server/serverHelpers/uwsServer.js.map +1 -1
- package/dist/server/static.js +24 -28
- package/dist/server/static.js.map +1 -1
- package/dist/server/storageReclamation.d.ts +5 -0
- package/dist/server/storageReclamation.js +17 -1
- package/dist/server/storageReclamation.js.map +1 -1
- package/dist/server/threads/isolatedApplications.d.ts +47 -0
- package/dist/server/threads/isolatedApplications.js +171 -0
- package/dist/server/threads/isolatedApplications.js.map +1 -0
- package/dist/server/threads/itc.d.ts +7 -2
- package/dist/server/threads/itc.js +5 -1
- package/dist/server/threads/itc.js.map +1 -1
- package/dist/server/threads/logRotationTransport.d.ts +1 -0
- package/dist/server/threads/logRotationTransport.js +33 -0
- package/dist/server/threads/logRotationTransport.js.map +1 -0
- package/dist/server/threads/manageThreads.d.ts +83 -3
- package/dist/server/threads/manageThreads.js +769 -75
- package/dist/server/threads/manageThreads.js.map +1 -1
- package/dist/server/threads/socketRouter.d.ts +1 -0
- package/dist/server/threads/socketRouter.js +277 -31
- package/dist/server/threads/socketRouter.js.map +1 -1
- package/dist/server/threads/threadHeapMemory.d.ts +2 -0
- package/dist/server/threads/threadHeapMemory.js +31 -0
- package/dist/server/threads/threadHeapMemory.js.map +1 -0
- package/dist/server/threads/threadServer.js +76 -22
- package/dist/server/threads/threadServer.js.map +1 -1
- package/dist/sqlEngine/config.d.ts +1 -3
- package/dist/sqlEngine/config.js +19 -16
- package/dist/sqlEngine/config.js.map +1 -1
- package/dist/sqlTranslator/index.d.ts +1 -1
- package/dist/sqlTranslator/index.js +30 -7
- package/dist/sqlTranslator/index.js.map +1 -1
- package/dist/upgrade/directives/5-3-0.d.ts +7 -0
- package/dist/upgrade/directives/5-3-0.js +148 -0
- package/dist/upgrade/directives/5-3-0.js.map +1 -0
- package/dist/upgrade/directives/directivesController.js +2 -1
- package/dist/upgrade/directives/directivesController.js.map +1 -1
- package/dist/utility/OperationFunctionCaller.js +2 -1
- package/dist/utility/OperationFunctionCaller.js.map +1 -1
- package/dist/utility/common_utils.d.ts +16 -0
- package/dist/utility/common_utils.js +32 -6
- package/dist/utility/common_utils.js.map +1 -1
- package/dist/utility/componentNames.d.ts +8 -0
- package/dist/utility/componentNames.js +12 -1
- package/dist/utility/componentNames.js.map +1 -1
- package/dist/utility/environment/environmentManager.js +3 -6
- package/dist/utility/environment/environmentManager.js.map +1 -1
- package/dist/utility/environment/systemInformation.d.ts +1 -0
- package/dist/utility/environment/systemInformation.js +1 -0
- package/dist/utility/environment/systemInformation.js.map +1 -1
- package/dist/utility/errors/commonErrors.d.ts +2 -0
- package/dist/utility/errors/commonErrors.js +2 -0
- package/dist/utility/errors/commonErrors.js.map +1 -1
- package/dist/utility/errors/hdbError.d.ts +33 -0
- package/dist/utility/errors/hdbError.js +58 -1
- package/dist/utility/errors/hdbError.js.map +1 -1
- package/dist/utility/globalSchema.d.ts +18 -0
- package/dist/utility/hdbTerms.d.ts +18 -0
- package/dist/utility/hdbTerms.js +20 -2
- package/dist/utility/hdbTerms.js.map +1 -1
- package/dist/utility/logging/harper_logger.d.ts +2 -0
- package/dist/utility/logging/harper_logger.js +286 -30
- package/dist/utility/logging/harper_logger.js.map +1 -1
- package/dist/utility/logging/logGenerationCoordinator.d.ts +35 -0
- package/dist/utility/logging/logGenerationCoordinator.js +184 -0
- package/dist/utility/logging/logGenerationCoordinator.js.map +1 -0
- package/dist/utility/logging/logRotation.d.ts +46 -0
- package/dist/utility/logging/logRotation.js +365 -0
- package/dist/utility/logging/logRotation.js.map +1 -0
- package/dist/utility/logging/logRotator.d.ts +1 -1
- package/dist/utility/logging/logRotator.js +192 -85
- package/dist/utility/logging/logRotator.js.map +1 -1
- package/dist/utility/nodeIdentity.d.ts +9 -0
- package/dist/utility/nodeIdentity.js +58 -0
- package/dist/utility/nodeIdentity.js.map +1 -0
- package/dist/utility/npmUtilities.js +11 -7
- package/dist/utility/npmUtilities.js.map +1 -1
- package/dist/utility/operationPermissions.d.ts +3 -1
- package/dist/utility/operationPermissions.js +16 -1
- package/dist/utility/operationPermissions.js.map +1 -1
- package/dist/utility/operation_authorization.d.ts +10 -7
- package/dist/utility/operation_authorization.js +212 -41
- package/dist/utility/operation_authorization.js.map +1 -1
- package/dist/utility/watchPath.d.ts +29 -0
- package/dist/utility/watchPath.js +68 -0
- package/dist/utility/watchPath.js.map +1 -0
- package/dist/utility/watcherFallback.d.ts +41 -0
- package/dist/utility/watcherFallback.js +153 -0
- package/dist/utility/watcherFallback.js.map +1 -1
- package/dist/validation/configValidator.d.ts +12 -0
- package/dist/validation/configValidator.js +205 -75
- package/dist/validation/configValidator.js.map +1 -1
- package/dist/validation/installValidator.js +12 -0
- package/dist/validation/installValidator.js.map +1 -1
- package/dist/validation/validationWrapper.d.ts +11 -0
- package/dist/validation/validationWrapper.js +16 -3
- package/dist/validation/validationWrapper.js.map +1 -1
- package/index.ts +8 -0
- package/json/systemSchema.json +55 -0
- package/npm-shrinkwrap.json +286 -194
- package/package.json +15 -7
- package/resources/DESIGN.md +219 -52
- package/resources/DatabaseTransaction.ts +657 -52
- package/resources/LMDBTransaction.ts +46 -6
- package/resources/PrimaryRocksDatabase.ts +46 -7
- package/resources/RecordEncoder.ts +124 -9
- package/resources/RequestTarget.ts +2 -0
- package/resources/Resource.ts +114 -22
- package/resources/ResourceInterface.ts +31 -0
- package/resources/RocksIndexStore.ts +30 -9
- package/resources/RocksTransactionLogStore.ts +188 -51
- package/resources/Table.ts +1960 -301
- package/resources/analytics/write.ts +10 -3
- package/resources/auditStore.ts +647 -32
- package/resources/blob.ts +1029 -110
- package/resources/branchDatabase.ts +941 -0
- package/resources/crdt.ts +76 -12
- package/resources/dataLoader.ts +3 -4
- package/resources/databases.ts +1584 -320
- package/resources/defineTable.ts +18 -2
- package/resources/derivedIndexRegistry.ts +56 -0
- package/resources/derivedIndexRuntime.ts +2292 -0
- package/resources/graphql.ts +72 -17
- package/resources/indexes/HierarchicalNavigableSmallWorld.ts +911 -48
- package/resources/indexes/hnswDerivedIndex.ts +531 -0
- package/resources/indexes/hnswPlaneBinding.ts +174 -0
- package/resources/longLivedTransactions.ts +360 -0
- package/resources/models/backendRegistry.ts +84 -2
- package/resources/models/bootstrap.ts +473 -28
- package/resources/nodeIdMapping.ts +50 -0
- package/resources/recordLock.ts +419 -0
- package/resources/recordLockCoordinator.ts +3043 -0
- package/resources/replayLogs.ts +152 -26
- package/resources/replayLogsGuards.ts +171 -8
- package/resources/replicatedApplyFailure.ts +77 -0
- package/resources/scheduler/scheduler.ts +4 -4
- package/resources/search.ts +288 -46
- package/resources/tracked.ts +73 -22
- package/resources/transactionBroadcast.ts +3 -3
- package/security/auth.ts +68 -29
- package/security/authn/oidc/claims.ts +72 -0
- package/security/authn/oidc/identityToken.ts +129 -0
- package/security/authn/oidc/jwks.ts +260 -0
- package/security/authn/oidc/providers/generic.ts +40 -0
- package/security/authn/oidc/providers/githubActions.ts +137 -0
- package/security/authn/oidc/providers/index.ts +52 -0
- package/security/authn/oidc/tokenExchange.ts +300 -0
- package/security/authn/oidc/trustPolicyOperations.ts +343 -0
- package/security/authn/oidc/types.ts +41 -0
- package/security/certificateVerification/index.ts +54 -13
- package/security/certificateVerification/trustedIssuers.ts +76 -0
- package/security/certificateVerification/types.ts +1 -0
- package/security/credentialProvenance.ts +47 -0
- package/security/credentialRejection.ts +22 -0
- package/security/deferredAuthentication.ts +71 -0
- package/security/impersonation.ts +117 -12
- package/security/jsLoader.ts +83 -18
- package/security/keys.ts +298 -72
- package/security/operationScope.ts +33 -0
- package/security/permissionsTranslator.js +23 -0
- package/security/tokenAuthentication.ts +233 -12
- package/security/user.ts +4 -3
- package/server/DESIGN.md +194 -16
- package/server/DurableSubscriptionsSession.ts +71 -11
- package/server/REST.ts +115 -4
- package/server/graphqlQuerying.ts +4 -0
- package/server/http.ts +133 -20
- package/server/itc/serverHandlers.js +8 -1
- package/server/jobs/jobProcess.ts +8 -2
- package/server/jobs/jobs.ts +4 -1
- package/server/liveSubscriptionAuth.ts +129 -46
- package/server/loadRootComponents.js +50 -8
- package/server/mqtt.ts +179 -38
- package/server/nodeName.ts +103 -21
- package/server/serverHelpers/Headers.ts +135 -0
- package/server/serverHelpers/NodeAdapterResponse.ts +221 -0
- package/server/serverHelpers/Request.ts +33 -131
- package/server/serverHelpers/contentTypes.ts +217 -36
- package/server/serverHelpers/deployValidationState.ts +24 -13
- package/server/serverHelpers/operationAuthorizationState.ts +34 -3
- package/server/serverHelpers/registeredOperations.ts +79 -22
- package/server/serverHelpers/requestSanitization.ts +15 -0
- package/server/serverHelpers/serverHandlers.js +6 -3
- package/server/serverHelpers/serverUtilities.ts +232 -40
- package/server/serverHelpers/sharedMessageEncoding.ts +307 -0
- package/server/serverHelpers/uwsServer.ts +17 -2
- package/server/static.ts +23 -29
- package/server/storageReclamation.ts +15 -2
- package/server/threads/isolatedApplications.ts +157 -0
- package/server/threads/itc.js +11 -1
- package/server/threads/logRotationTransport.ts +40 -0
- package/server/threads/manageThreads.js +771 -66
- package/server/threads/socketRouter.ts +291 -30
- package/server/threads/threadHeapMemory.ts +26 -0
- package/server/threads/threadServer.js +73 -22
- package/sqlTranslator/index.ts +31 -8
- package/studio/web/assets/{Chat-4RrB5134.js → Chat-D3j-1yY1.js} +1 -1
- package/studio/web/assets/{FloatingChat-omlNMDcJ.js → FloatingChat-BxJGYcfB.js} +3 -3
- package/studio/web/assets/{apiToken-Bke3wvfZ.js → apiToken-CT55oWOe.js} +1 -1
- package/studio/web/assets/{applications-DvFDYJgK.js → applications-D9Ct9_vm.js} +1 -1
- package/studio/web/assets/{cssMode-C1vRa7zh.js → cssMode-DV8H7VwA.js} +1 -1
- package/studio/web/assets/{editor-3XRWEDWX.js → editor-uatc0unt.js} +1 -1
- package/studio/web/assets/{html-CTY5tdMr.js → html-Bm6D6paN.js} +1 -1
- package/studio/web/assets/{htmlMode-CG1vSD9t.js → htmlMode-CEn7tpLG.js} +1 -1
- package/studio/web/assets/{index-Dfpeofdu.js → index-BIXW6Pu4.js} +5 -5
- package/studio/web/assets/{index.lazy-B1VOIv-t.js → index.lazy-UI7L-Vrk.js} +1 -1
- package/studio/web/assets/{javascript-CJeJzGnI.js → javascript-CJ0G3AFZ.js} +1 -1
- package/studio/web/assets/{jsonMode-CYPBwM82.js → jsonMode-DQADAYEa.js} +1 -1
- package/studio/web/assets/{languageServices-IKH4GUHl.js → languageServices-CAQJXWcI.js} +1 -1
- package/studio/web/assets/{lspLanguageFeatures-BC8_gxKG.js → lspLanguageFeatures-CCQ8P5sY.js} +1 -1
- package/studio/web/assets/{notifications-BfKBpYcq.js → notifications-BbxTU6Aw.js} +1 -1
- package/studio/web/assets/{notifications-DFbArTfC.js → notifications-Cvb3P1lB.js} +1 -1
- package/studio/web/assets/{profile-Q4-T6c-S.js → profile-Yyb7gsvL.js} +1 -1
- package/studio/web/assets/{regions-CtkV0xje.js → regions-OgjGHlU5.js} +1 -1
- package/studio/web/assets/{register-1ZZuMsiA.js → register-6qwNEOY3.js} +2 -2
- package/studio/web/assets/{setComponentFile-ZWLcWv5X.js → setComponentFile-BilDMtgB.js} +1 -1
- package/studio/web/assets/{setup-DWprJyJy.js → setup-J6qJ7OIU.js} +2 -2
- package/studio/web/assets/{status--aNm8isn.js → status-0RWGcfyD.js} +1 -1
- package/studio/web/assets/{toggleHighContrast-Cq_lt3XD.js → toggleHighContrast-BIn-vErT.js} +1 -1
- package/studio/web/assets/{tsMode-pjgytARx.js → tsMode-DgUXku4d.js} +1 -1
- package/studio/web/assets/{typescript-Cdg0mqUh.js → typescript-C9orXcsM.js} +1 -1
- package/studio/web/assets/{useEntityRestURL-RZhaY8Rn.js → useEntityRestURL-BEoXXbUB.js} +1 -1
- package/studio/web/assets/{workers-BgoXIqQe.js → workers-JVzSDmgx.js} +1 -1
- package/studio/web/assets/{xml-BwSeDMiP.js → xml-Cq-S8S4X.js} +1 -1
- package/studio/web/assets/{yaml-DotCUG5l.js → yaml-sfoRdh1M.js} +1 -1
- package/studio/web/index.html +1 -1
- package/upgrade/directives/5-3-0.ts +132 -0
- package/upgrade/directives/directivesController.ts +2 -1
- package/utility/OperationFunctionCaller.ts +2 -1
- package/utility/common_utils.ts +30 -5
- package/utility/componentNames.ts +12 -0
- package/utility/environment/environmentManager.ts +3 -7
- package/utility/environment/systemInformation.ts +7 -0
- package/utility/errors/commonErrors.ts +4 -0
- package/utility/errors/hdbError.ts +57 -0
- package/utility/hdbTerms.ts +19 -0
- package/utility/logging/harper_logger.ts +278 -26
- package/utility/logging/logGenerationCoordinator.ts +196 -0
- package/utility/logging/logRotation.ts +367 -0
- package/utility/logging/logRotator.ts +213 -81
- package/utility/nodeIdentity.ts +45 -0
- package/utility/npmUtilities.ts +12 -8
- package/utility/operationPermissions.ts +18 -1
- package/utility/operation_authorization.ts +231 -42
- package/utility/watchPath.ts +63 -0
- package/utility/watcherFallback.ts +148 -0
- package/validation/configValidator.ts +215 -75
- package/validation/installValidator.ts +15 -0
- package/validation/validationWrapper.ts +18 -4
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { isMainThread, threadId } from 'node:worker_threads';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { registryStatus } from '@harperfast/rocksdb-js';
|
|
4
|
+
import { logger } from '../utility/logging/logger.ts';
|
|
5
|
+
import { CONFIG_PARAMS } from '../utility/hdbTerms.ts';
|
|
6
|
+
import * as envMngr from '../utility/environment/environmentManager.ts';
|
|
7
|
+
import { convertToMS, prettyDuration } from '../utility/common_utils.ts';
|
|
8
|
+
|
|
9
|
+
const DEFAULT_REPORT_THRESHOLD_MS = 300000;
|
|
10
|
+
const SWEEP_INTERVAL_MS = 60000;
|
|
11
|
+
// One line per over-age handle would, against a large leak, block the main thread's socket routing
|
|
12
|
+
// for as long as it took to format them. The per-handle backoff below rotates the cap over the whole
|
|
13
|
+
// set across passes, so every holder is still named eventually.
|
|
14
|
+
export const MAX_LONG_LIVED_TRANSACTION_REPORTS_PER_PASS = 10;
|
|
15
|
+
const MAX_HOLDER_CANDIDATES = 3;
|
|
16
|
+
// The sweep prunes against the handles it just enumerated; the attribution map has no such
|
|
17
|
+
// enumeration, so its entries expire instead. Far longer than a sweep interval, so a still-live
|
|
18
|
+
// holder keeps its backoff.
|
|
19
|
+
const ATTRIBUTION_STATE_TTL_MS = 3600000;
|
|
20
|
+
// The prune is O(map) and the monitor calls reportLongLivedHolder once per over-threshold transaction
|
|
21
|
+
// per tick, so pruning per call is O(N^2) in exactly the leak this reporting exists to describe.
|
|
22
|
+
const ATTRIBUTION_PRUNE_INTERVAL_MS = 60000;
|
|
23
|
+
|
|
24
|
+
type RegistryStatusFn = typeof registryStatus;
|
|
25
|
+
let registryStatusFn: RegistryStatusFn | undefined = typeof registryStatus === 'function' ? registryStatus : undefined;
|
|
26
|
+
|
|
27
|
+
// Report state is keyed by database path AND native id: rocksdb-js allocates transaction ids per
|
|
28
|
+
// database descriptor, so two databases routinely both have id 2, and a reopen restarts the counter.
|
|
29
|
+
type ReportState = { nextReportAgeMs: number; lastAgeMs: number; touchedAt: number };
|
|
30
|
+
const sweepReports = new Map<string, ReportState>();
|
|
31
|
+
const attributionReports = new Map<string, ReportState>();
|
|
32
|
+
let sweepTimer: NodeJS.Timeout | undefined;
|
|
33
|
+
let invalidThresholdWarned = false;
|
|
34
|
+
let missingDetailsWarned = false;
|
|
35
|
+
let lastAttributionPruneAt = 0;
|
|
36
|
+
let thresholdInEffectMs = -1;
|
|
37
|
+
|
|
38
|
+
function reportKey(databasePath: string | undefined, nativeId: number, openedAt?: number): string {
|
|
39
|
+
return `${databasePath ?? '?'} ${nativeId}${openedAt == null ? '' : ` ${openedAt}`}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Record this observation of a handle and return its report state. A shrinking age means the id was
|
|
44
|
+
* reused by a reopened descriptor, so the previous holder's backoff must not suppress the new one.
|
|
45
|
+
*/
|
|
46
|
+
function observeHandle(
|
|
47
|
+
reports: Map<string, ReportState>,
|
|
48
|
+
key: string,
|
|
49
|
+
ageMs: number,
|
|
50
|
+
thresholdMs: number
|
|
51
|
+
): ReportState {
|
|
52
|
+
let state = reports.get(key);
|
|
53
|
+
if (state && ageMs < state.lastAgeMs) state = undefined;
|
|
54
|
+
if (!state) {
|
|
55
|
+
state = { nextReportAgeMs: thresholdMs, lastAgeMs: ageMs, touchedAt: 0 };
|
|
56
|
+
reports.set(key, state);
|
|
57
|
+
}
|
|
58
|
+
state.lastAgeMs = ageMs;
|
|
59
|
+
state.touchedAt = Date.now();
|
|
60
|
+
return state;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Drop the accrued backoff when the configured threshold changes, so a handle already under
|
|
65
|
+
* observation is re-measured against the new one. Without this, `nextReportAgeMs` keeps whatever it
|
|
66
|
+
* was given at first observation: lowering the threshold during an incident would not bring a
|
|
67
|
+
* silent handle's first report forward, and raising it would not quiet one. Reporting each live
|
|
68
|
+
* holder once more at the new threshold is what an operator who just changed it is asking for.
|
|
69
|
+
*/
|
|
70
|
+
function rebaseIfThresholdChanged(thresholdMs: number): void {
|
|
71
|
+
if (thresholdMs === thresholdInEffectMs) return;
|
|
72
|
+
thresholdInEffectMs = thresholdMs;
|
|
73
|
+
sweepReports.clear();
|
|
74
|
+
attributionReports.clear();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Apply a live threshold at the start of every reporting pass, including one that finds no eligible
|
|
79
|
+
* holder. Otherwise a threshold raised above a holder's age leaves its old attribution backoff in
|
|
80
|
+
* place when the threshold is lowered again.
|
|
81
|
+
*/
|
|
82
|
+
export function rebaseLongLivedTransactionReports(thresholdMs: number): void {
|
|
83
|
+
rebaseIfThresholdChanged(thresholdMs);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Push this handle's next report out to twice its current age, so one held for hours produces a
|
|
88
|
+
* handful of lines rather than one per pass. Called only where a line was actually emitted: advancing
|
|
89
|
+
* it for a handle the per-pass cap skipped would silence that handle without ever naming it.
|
|
90
|
+
*/
|
|
91
|
+
function markReported(state: ReportState, ageMs: number): void {
|
|
92
|
+
state.nextReportAgeMs = ageMs * 2;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* How old a native transaction handle must be before it is reported, in ms; 0 disables every surface
|
|
97
|
+
* here. Read per pass rather than cached so a live config reload takes effect. A value that cannot
|
|
98
|
+
* be a duration falls back to the default instead of silently disabling reporting.
|
|
99
|
+
*/
|
|
100
|
+
export function getReportThresholdMs(): number {
|
|
101
|
+
const configured = envMngr.get(CONFIG_PARAMS.STORAGE_LONGTRANSACTIONREPORTTHRESHOLD);
|
|
102
|
+
if (configured == null) return DEFAULT_REPORT_THRESHOLD_MS;
|
|
103
|
+
// convertToMS returns 0 for anything that is neither string nor number, which YAML hands us for
|
|
104
|
+
// `yes`/`no` (booleans) and for an object left by a config merge — indistinguishable from the
|
|
105
|
+
// documented 0 that disables reporting, so it would silently switch off what the operator configured.
|
|
106
|
+
const ms = typeof configured === 'string' || typeof configured === 'number' ? convertToMS(configured) : NaN;
|
|
107
|
+
if (ms === 0) return 0;
|
|
108
|
+
if (!Number.isFinite(ms) || ms < 0) {
|
|
109
|
+
if (!invalidThresholdWarned) {
|
|
110
|
+
invalidThresholdWarned = true;
|
|
111
|
+
logger.warn?.(
|
|
112
|
+
`Invalid storage.longTransactionReportThreshold "${configured}"; using default ${DEFAULT_REPORT_THRESHOLD_MS}ms`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
return DEFAULT_REPORT_THRESHOLD_MS;
|
|
116
|
+
}
|
|
117
|
+
return ms;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Report every native transaction handle in the process-global rocksdb-js registry that has been open
|
|
122
|
+
* past the threshold — including handles no `DatabaseTransaction` owns, which is the one class of
|
|
123
|
+
* holder no other surface can see (harper#2471). The registry spans worker threads, so this runs on
|
|
124
|
+
* the main thread only; a per-thread sweep would report each handle once per worker.
|
|
125
|
+
*/
|
|
126
|
+
export function runLongLivedTransactionSweep(): void {
|
|
127
|
+
try {
|
|
128
|
+
const thresholdMs = getReportThresholdMs();
|
|
129
|
+
rebaseLongLivedTransactionReports(thresholdMs);
|
|
130
|
+
if (thresholdMs === 0 || !registryStatusFn) return;
|
|
131
|
+
const status = registryStatusFn();
|
|
132
|
+
const seen = new Set<string>();
|
|
133
|
+
const due: { path: string | undefined; id: number; ageMs: number; state: ReportState }[] = [];
|
|
134
|
+
let missingDetails = false;
|
|
135
|
+
for (const database of status) {
|
|
136
|
+
const details = database.transactionDetails;
|
|
137
|
+
if (!details) {
|
|
138
|
+
missingDetails = true;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
for (const handle of details) {
|
|
142
|
+
if (handle.ageMs < thresholdMs) continue;
|
|
143
|
+
const key = reportKey(database.path, handle.id);
|
|
144
|
+
seen.add(key);
|
|
145
|
+
const state = observeHandle(sweepReports, key, handle.ageMs, thresholdMs);
|
|
146
|
+
if (handle.ageMs >= state.nextReportAgeMs)
|
|
147
|
+
due.push({ path: database.path, id: handle.id, ageMs: handle.ageMs, state });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (const key of sweepReports.keys()) if (!seen.has(key)) sweepReports.delete(key);
|
|
151
|
+
if (missingDetails && !missingDetailsWarned) {
|
|
152
|
+
missingDetailsWarned = true;
|
|
153
|
+
logger.warn?.(
|
|
154
|
+
'Long-lived transaction reporting is degraded: the installed @harperfast/rocksdb-js does not expose registryStatus().transactionDetails (requires 2.8.0)'
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
if (due.length === 0) return;
|
|
158
|
+
due.sort((a, b) => b.ageMs - a.ageMs);
|
|
159
|
+
for (const handle of due.slice(0, MAX_LONG_LIVED_TRANSACTION_REPORTS_PER_PASS)) {
|
|
160
|
+
markReported(handle.state, handle.ageMs);
|
|
161
|
+
logger.warn?.(
|
|
162
|
+
`Long-lived RocksDB transaction handle: id ${handle.id} has been open for ${prettyDuration(handle.ageMs)} on database ${handle.path ?? '?'}. ` +
|
|
163
|
+
`A handle this old can hold write intents that park other writers' commits, and may pin a read snapshot that blocks version reclamation.`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
if (due.length > MAX_LONG_LIVED_TRANSACTION_REPORTS_PER_PASS) {
|
|
167
|
+
logger.warn?.(
|
|
168
|
+
`${due.length - MAX_LONG_LIVED_TRANSACTION_REPORTS_PER_PASS} further RocksDB transaction handle(s) are open past the ${prettyDuration(thresholdMs)} reporting threshold and were not listed individually.`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
} catch (error) {
|
|
172
|
+
logger.error?.('Error sweeping for long-lived transaction handles', error);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Start the periodic sweep. Armed unconditionally on the main thread — the pass itself honors a live
|
|
178
|
+
* threshold change, including one that disables it — and idempotent because the thread startup path
|
|
179
|
+
* that calls it can run more than once.
|
|
180
|
+
*/
|
|
181
|
+
export function startLongLivedTransactionReporting(): void {
|
|
182
|
+
if (!isMainThread || sweepTimer) return;
|
|
183
|
+
if (!registryStatusFn) {
|
|
184
|
+
logger.debug?.('Long-lived transaction reporting unavailable; @harperfast/rocksdb-js exposes no registryStatus()');
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
sweepTimer = setInterval(runLongLivedTransactionSweep, SWEEP_INTERVAL_MS).unref();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export type LongLivedHolder = {
|
|
191
|
+
databasePath: string | undefined;
|
|
192
|
+
nativeId: number;
|
|
193
|
+
openedAt: number;
|
|
194
|
+
ageMs: number;
|
|
195
|
+
databaseName?: string;
|
|
196
|
+
tableName?: string;
|
|
197
|
+
// A thunk, not a number: the caller's count walks the whole staged write set, and the backoff below
|
|
198
|
+
// suppresses most ticks — the #2471 shape is a transaction holding a large write set for hours, so
|
|
199
|
+
// paying for that walk on every suppressed tick is the one cost this reporting must not add.
|
|
200
|
+
countPendingWrites: () => number;
|
|
201
|
+
states: string[];
|
|
202
|
+
timeoutBudget?: number;
|
|
203
|
+
startedFrom?: { resourceName: string; method: string };
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
export type LongLivedHolderReportBudget = {
|
|
207
|
+
remaining: number;
|
|
208
|
+
skipped: number;
|
|
209
|
+
thresholdMs: number;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export function createLongLivedHolderReportBudget(thresholdMs: number): LongLivedHolderReportBudget {
|
|
213
|
+
return { remaining: MAX_LONG_LIVED_TRANSACTION_REPORTS_PER_PASS, skipped: 0, thresholdMs };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function finishLongLivedHolderReports(reportBudget: LongLivedHolderReportBudget): void {
|
|
217
|
+
if (reportBudget.skipped === 0) return;
|
|
218
|
+
try {
|
|
219
|
+
logger.warn?.(
|
|
220
|
+
`${reportBudget.skipped} further Harper transaction holder(s) are open past the ${prettyDuration(reportBudget.thresholdMs)} reporting threshold and were deferred.`
|
|
221
|
+
);
|
|
222
|
+
} catch {}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Report a handle this thread owns, with the attribution the registry sweep cannot supply. The native
|
|
227
|
+
* id is the join key between the two: the sweep names an id, this names who holds it and which state
|
|
228
|
+
* kept the open-transaction monitor from reaping it (harper#2471). Never throws — the monitor
|
|
229
|
+
* interval that calls it has no handler.
|
|
230
|
+
*/
|
|
231
|
+
export function reportLongLivedHolder(holder: LongLivedHolder, reportBudget?: LongLivedHolderReportBudget): void {
|
|
232
|
+
try {
|
|
233
|
+
if (!registryStatusFn) return;
|
|
234
|
+
const thresholdMs = reportBudget?.thresholdMs ?? getReportThresholdMs();
|
|
235
|
+
rebaseLongLivedTransactionReports(thresholdMs);
|
|
236
|
+
if (thresholdMs === 0) return;
|
|
237
|
+
const now = Date.now();
|
|
238
|
+
if (now - lastAttributionPruneAt >= ATTRIBUTION_PRUNE_INTERVAL_MS) {
|
|
239
|
+
lastAttributionPruneAt = now;
|
|
240
|
+
const expiredBefore = now - ATTRIBUTION_STATE_TTL_MS;
|
|
241
|
+
for (const [key, state] of attributionReports)
|
|
242
|
+
if (state.touchedAt < expiredBefore) attributionReports.delete(key);
|
|
243
|
+
}
|
|
244
|
+
const state = observeHandle(
|
|
245
|
+
attributionReports,
|
|
246
|
+
reportKey(holder.databasePath, holder.nativeId, holder.openedAt),
|
|
247
|
+
holder.ageMs,
|
|
248
|
+
thresholdMs
|
|
249
|
+
);
|
|
250
|
+
if (holder.ageMs < state.nextReportAgeMs) return;
|
|
251
|
+
if (reportBudget && reportBudget.remaining <= 0) {
|
|
252
|
+
reportBudget.skipped++;
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
markReported(state, holder.ageMs);
|
|
256
|
+
if (reportBudget) reportBudget.remaining--;
|
|
257
|
+
const table = holder.tableName ? `.${holder.tableName}` : '';
|
|
258
|
+
logger.warn?.(
|
|
259
|
+
`Harper transaction has held RocksDB transaction ${holder.nativeId} for ${prettyDuration(holder.ageMs)} ` +
|
|
260
|
+
`on thread ${threadId}, database ${holder.databaseName ?? '?'}${table} (${holder.databasePath ?? '?'}), ` +
|
|
261
|
+
`holding ${holder.countPendingWrites()} staged write(s), state: ${holder.states.join('+')}` +
|
|
262
|
+
(holder.timeoutBudget ? `, open-transaction budget ${holder.timeoutBudget}ms` : '') +
|
|
263
|
+
(holder.startedFrom?.resourceName
|
|
264
|
+
? `, started from ${holder.startedFrom.resourceName}${holder.startedFrom.method ? '.' + holder.startedFrom.method : ''}`
|
|
265
|
+
: '') +
|
|
266
|
+
'. It is not being reaped by the open-transaction monitor; the state tells you why.'
|
|
267
|
+
);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
logger.debug?.('Failed to report a long-lived transaction holder', error);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* The live handles that could be holding the write intent a stuck commit is parked on, as a sentence
|
|
275
|
+
* to append to that commit's log. A handle on another database is offered too, labelled with its path:
|
|
276
|
+
* the verification table is one process-global slot array whose hash mixes in the database id, so a
|
|
277
|
+
* holder in `system` or `oauth` collides with — and parks — a `data` commit at the same rate two `data`
|
|
278
|
+
* keys do. Rank puts the stuck commit's own database first, then age. Age only ranks: a coordinated
|
|
279
|
+
* retry parks on whichever transaction holds the slot when the commit reaches it, which can be younger
|
|
280
|
+
* than the commit itself, so filtering by age could drop the real holder.
|
|
281
|
+
* Returns '' rather than throwing — the caller's own 503 must survive a failure here.
|
|
282
|
+
*/
|
|
283
|
+
export function describeHolderCandidates(
|
|
284
|
+
databasePath: string | undefined,
|
|
285
|
+
excludeNativeId: number | undefined
|
|
286
|
+
): string {
|
|
287
|
+
if (!databasePath || !registryStatusFn) return '';
|
|
288
|
+
try {
|
|
289
|
+
if (getReportThresholdMs() === 0) return '';
|
|
290
|
+
const target = resolve(databasePath);
|
|
291
|
+
const candidates: { id: number; ageMs: number; sameDatabase: boolean; path: string | undefined }[] = [];
|
|
292
|
+
let targetSeen = false;
|
|
293
|
+
let targetHasDetails = false;
|
|
294
|
+
for (const database of registryStatusFn()) {
|
|
295
|
+
// An entry with no path can never be the target, and resolve() would throw on it — which,
|
|
296
|
+
// inside this loop, would drop the candidate list for every database rather than just this one.
|
|
297
|
+
const sameDatabase = database.path != null && resolve(database.path) === target;
|
|
298
|
+
const details = database.transactionDetails;
|
|
299
|
+
if (sameDatabase) {
|
|
300
|
+
targetSeen = true;
|
|
301
|
+
if (details) targetHasDetails = true;
|
|
302
|
+
}
|
|
303
|
+
if (!details) continue;
|
|
304
|
+
for (const handle of details)
|
|
305
|
+
if (!sameDatabase || handle.id !== excludeNativeId)
|
|
306
|
+
candidates.push({ id: handle.id, ageMs: handle.ageMs, sameDatabase, path: database.path });
|
|
307
|
+
}
|
|
308
|
+
if (!targetHasDetails) {
|
|
309
|
+
// A database with no other handles is normal; no entry at all means the join between a store's
|
|
310
|
+
// path and the registry's path has drifted, which is the one worth telling an operator apart.
|
|
311
|
+
logger.debug?.(
|
|
312
|
+
targetSeen
|
|
313
|
+
? `Registry entry for ${target} exposes no transactionDetails; only other databases' handles can be offered as holder candidates for its stuck commit`
|
|
314
|
+
: `No registry entry for ${target}; only other databases' handles can be offered as holder candidates for its stuck commit`
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
if (candidates.length === 0) return '';
|
|
318
|
+
candidates.sort((a, b) => Number(b.sameDatabase) - Number(a.sameDatabase) || b.ageMs - a.ageMs);
|
|
319
|
+
const shortlist = candidates.slice(0, MAX_HOLDER_CANDIDATES);
|
|
320
|
+
// Ranking this database first and then capping can bury the one candidate the cross-database
|
|
321
|
+
// search exists to surface: a busy database routinely has MAX_HOLDER_CANDIDATES handles of its
|
|
322
|
+
// own, so a foreign holder would only ever appear inside the "and N more" count. Give the oldest
|
|
323
|
+
// one the last slot instead.
|
|
324
|
+
if (shortlist.length === MAX_HOLDER_CANDIDATES && shortlist.every((candidate) => candidate.sameDatabase)) {
|
|
325
|
+
const foreign = candidates.find((candidate) => !candidate.sameDatabase);
|
|
326
|
+
if (foreign) shortlist[MAX_HOLDER_CANDIDATES - 1] = foreign;
|
|
327
|
+
}
|
|
328
|
+
const named = shortlist
|
|
329
|
+
.map(
|
|
330
|
+
(candidate) =>
|
|
331
|
+
`${candidate.id} (open ${prettyDuration(candidate.ageMs)}${candidate.sameDatabase ? '' : ` on ${candidate.path ?? '?'}`})`
|
|
332
|
+
)
|
|
333
|
+
.join(', ');
|
|
334
|
+
return (
|
|
335
|
+
` Live transaction handles, any of which could hold the write intent this commit is parked on ` +
|
|
336
|
+
`(the verification table is one process-global slot array, so a handle on another database can hold it), ` +
|
|
337
|
+
`this database first, oldest first: ${named}` +
|
|
338
|
+
(candidates.length > MAX_HOLDER_CANDIDATES ? `, and ${candidates.length - MAX_HOLDER_CANDIDATES} more.` : '.')
|
|
339
|
+
);
|
|
340
|
+
} catch {
|
|
341
|
+
return '';
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export function setRegistryStatusForTests(fn?: RegistryStatusFn): void {
|
|
346
|
+
registryStatusFn = fn;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export function resetLongLivedTransactionReportsForTests(): void {
|
|
350
|
+
sweepReports.clear();
|
|
351
|
+
attributionReports.clear();
|
|
352
|
+
invalidThresholdWarned = false;
|
|
353
|
+
missingDetailsWarned = false;
|
|
354
|
+
lastAttributionPruneAt = 0;
|
|
355
|
+
thresholdInEffectMs = -1;
|
|
356
|
+
if (sweepTimer) {
|
|
357
|
+
clearInterval(sweepTimer);
|
|
358
|
+
sweepTimer = undefined;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
1
2
|
import { ServerError } from '../../utility/errors/hdbError.ts';
|
|
2
3
|
import type { DefineBackendSpec, GenerateResult, ModelBackend, ModelCapabilities, ToolCall } from './types.ts';
|
|
3
4
|
|
|
@@ -24,14 +25,95 @@ type ModelKind = 'embedding' | 'generative';
|
|
|
24
25
|
const embedding: Map<string, ModelBackend> = new Map();
|
|
25
26
|
const generative: Map<string, ModelBackend> = new Map();
|
|
26
27
|
|
|
28
|
+
/** A registration a factory made during construction, deferred to the caller. */
|
|
29
|
+
export interface CapturedInstall {
|
|
30
|
+
kind: ModelKind;
|
|
31
|
+
logicalName: string;
|
|
32
|
+
backend: ModelBackend;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface CaptureSlot {
|
|
36
|
+
kind: ModelKind;
|
|
37
|
+
logicalName: string;
|
|
38
|
+
backend?: ModelBackend;
|
|
39
|
+
/** Deferred with the primary, so no request observes a new helper next to an old primary. */
|
|
40
|
+
extras: CapturedInstall[];
|
|
41
|
+
/** Async work spawned by a factory retains the ALS context past construction; once construction
|
|
42
|
+
* ends the scope deactivates so a late same-slot registration installs normally. */
|
|
43
|
+
active: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Async-context scoped: a module-global slot would divert unrelated registrations and collide
|
|
47
|
+
// concurrent constructions.
|
|
48
|
+
const captureScope = new AsyncLocalStorage<CaptureSlot>();
|
|
49
|
+
|
|
50
|
+
function install(kind: ModelKind, logicalName: string, backend: ModelBackend): void {
|
|
51
|
+
const slot = captureScope.getStore();
|
|
52
|
+
if (slot?.active) {
|
|
53
|
+
if (slot.kind === kind && slot.logicalName === logicalName) slot.backend = backend;
|
|
54
|
+
else slot.extras.push({ kind, logicalName, backend });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
(kind === 'embedding' ? embedding : generative).set(logicalName, backend);
|
|
58
|
+
}
|
|
59
|
+
|
|
27
60
|
/** Map `logicalName` to a backend for embedding calls. Re-set replaces. */
|
|
28
61
|
export function setEmbedding(logicalName: string, backend: ModelBackend): void {
|
|
29
|
-
embedding
|
|
62
|
+
install('embedding', logicalName, backend);
|
|
30
63
|
}
|
|
31
64
|
|
|
32
65
|
/** Map `logicalName` to a backend for generative calls. Re-set replaces. */
|
|
33
66
|
export function setGenerative(logicalName: string, backend: ModelBackend): void {
|
|
34
|
-
generative
|
|
67
|
+
install('generative', logicalName, backend);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Build a backend through its normal registration path but return it instead of installing it, so a
|
|
72
|
+
* config reload can install it conditionally. A scratch logical name would be briefly visible
|
|
73
|
+
* through `listBackends`, which backs the public `GET /v1/models`.
|
|
74
|
+
*/
|
|
75
|
+
export async function constructBackend(
|
|
76
|
+
kind: ModelKind,
|
|
77
|
+
logicalName: string,
|
|
78
|
+
register: () => void | Promise<void>
|
|
79
|
+
): Promise<{ backend?: ModelBackend; extras: CapturedInstall[] }> {
|
|
80
|
+
const slot: CaptureSlot = { kind, logicalName, extras: [], active: true };
|
|
81
|
+
try {
|
|
82
|
+
await captureScope.run(slot, async () => {
|
|
83
|
+
await register();
|
|
84
|
+
});
|
|
85
|
+
} finally {
|
|
86
|
+
slot.active = false;
|
|
87
|
+
}
|
|
88
|
+
return { backend: slot.backend, extras: slot.extras };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Replace `logicalName`'s backend for `kind` only if it is still `expected`. A plain `set` is atomic
|
|
93
|
+
* but unconditional, so concurrent writers resolve by arrival order rather than by which value is
|
|
94
|
+
* newer. A caller that loses the swap must re-derive from current state rather than overwrite.
|
|
95
|
+
*/
|
|
96
|
+
export function replaceIfCurrent(
|
|
97
|
+
kind: ModelKind,
|
|
98
|
+
logicalName: string,
|
|
99
|
+
expected: ModelBackend | undefined,
|
|
100
|
+
next: ModelBackend
|
|
101
|
+
): boolean {
|
|
102
|
+
const map = kind === 'embedding' ? embedding : generative;
|
|
103
|
+
if (map.get(logicalName) !== expected) return false;
|
|
104
|
+
map.set(logicalName, next);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Remove `logicalName`'s backend for `kind` only if it is still `expected`, returning whether it was
|
|
110
|
+
* removed. Withdrawing a credential must not delete a slot another writer has since taken over.
|
|
111
|
+
*/
|
|
112
|
+
export function removeIfCurrent(kind: ModelKind, logicalName: string, expected: ModelBackend | undefined): boolean {
|
|
113
|
+
const map = kind === 'embedding' ? embedding : generative;
|
|
114
|
+
if (map.get(logicalName) !== expected) return false;
|
|
115
|
+
map.delete(logicalName);
|
|
116
|
+
return true;
|
|
35
117
|
}
|
|
36
118
|
|
|
37
119
|
/** Non-throwing lookup of the backend mapped to `logicalName` for `kind`, or `undefined`. Used by the router to assemble + filter candidate lists without exceptions. */
|