@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
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
startWorker,
|
|
3
|
+
setMonitorListener,
|
|
4
|
+
setMainIsWorker,
|
|
5
|
+
threadsHaveStarted,
|
|
6
|
+
setIsolatedWorkerReconciler,
|
|
7
|
+
setRunningIsolatedApplicationsGetter,
|
|
8
|
+
workersForApplication,
|
|
9
|
+
stopWorker,
|
|
10
|
+
} from './manageThreads.js';
|
|
11
|
+
import {
|
|
12
|
+
presentIsolatedApplicationNames,
|
|
13
|
+
isolatedApplicationRefusal,
|
|
14
|
+
isolatedApplicationCapacityRefusal,
|
|
15
|
+
} from './isolatedApplications.ts';
|
|
16
|
+
import { lifecycle as componentLifecycle } from '../../components/status/index.ts';
|
|
2
17
|
import * as hdbTerms from '../../utility/hdbTerms.ts';
|
|
3
18
|
import * as harperLogger from '../../utility/logging/harper_logger.ts';
|
|
4
19
|
import { recordHostname } from '../../resources/analytics/write.ts';
|
|
5
20
|
import { startTransactionLogCooling } from '../transactionLogCooling.ts';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
21
|
+
import { startLongLivedTransactionReporting } from '../../resources/longLivedTransactions.ts';
|
|
22
|
+
import { isMainThread } from 'node:worker_threads';
|
|
23
|
+
import { join } from 'node:path';
|
|
8
24
|
|
|
9
25
|
const workers = [];
|
|
10
|
-
const
|
|
26
|
+
const HTTP_WORKER_STARTUP_DIAGNOSTIC_MS = 60000;
|
|
11
27
|
// startHTTPThreads() can be called more than once in-process (e.g. a test harness adding more
|
|
12
28
|
// worker threads to an already-running server via addThreads()). The crash-path sweep below must
|
|
13
29
|
// run only on the very first call — a later call happens after real mirrors are already bound, and
|
|
@@ -18,6 +34,9 @@ let sweptSocketsDirectory = false;
|
|
|
18
34
|
if (isMainThread) {
|
|
19
35
|
process.on('uncaughtException', (error) => {
|
|
20
36
|
// TODO: Maybe we should try to log the first of each type of error
|
|
37
|
+
// Same `isHandled` contract as threadServer.js: an error another handler has already
|
|
38
|
+
// classified (a lost native file watch, for instance) must not be logged again here.
|
|
39
|
+
if ((error as any).isHandled) return;
|
|
21
40
|
if ((error as any).code === 'ECONNRESET') return; // that's what network connections do
|
|
22
41
|
if ((error as any).code === 'EIO') {
|
|
23
42
|
// that means the terminal is closed
|
|
@@ -29,6 +48,7 @@ if (isMainThread) {
|
|
|
29
48
|
}
|
|
30
49
|
|
|
31
50
|
export async function startHTTPThreads(threadCount = 2, dynamicThreads?: boolean) {
|
|
51
|
+
const workerSlots = [];
|
|
32
52
|
// Crash-path defense: a hard crash can skip a worker's exit-time UDS cleanup and leave stale
|
|
33
53
|
// mirror files behind. This runs before any worker below can start (and thus before any mirror
|
|
34
54
|
// can bind), so it can only ever clear files nothing is using yet — never a live mirror. The
|
|
@@ -48,13 +68,16 @@ export async function startHTTPThreads(threadCount = 2, dynamicThreads?: boolean
|
|
|
48
68
|
// process-global singleton; see startTransactionLogCooling). Runs for all
|
|
49
69
|
// thread modes below, including the single-threaded (threadCount === 0) path.
|
|
50
70
|
startTransactionLogCooling();
|
|
71
|
+
startLongLivedTransactionReporting();
|
|
51
72
|
try {
|
|
52
73
|
if (dynamicThreads) {
|
|
53
74
|
// No caller currently passes dynamicThreads. If one ever does, note that the main thread
|
|
54
75
|
// does not bind ports in this mode, so on platforms without SO_REUSEPORT (macOS/Windows)
|
|
55
76
|
// worker 0's exclusive HTTP bind would silently swallow an external EADDRINUSE — the
|
|
56
77
|
// external-conflict detection in listenOnPorts() assumes the main thread binds first.
|
|
57
|
-
startHTTPWorker(0, 1);
|
|
78
|
+
const slot = startHTTPWorker(0, 1);
|
|
79
|
+
workerSlots.push(slot);
|
|
80
|
+
poolSlots.push(slot);
|
|
58
81
|
} else {
|
|
59
82
|
const { loadRootComponents } = require('../loadRootComponents.js');
|
|
60
83
|
if (threadCount === 0) {
|
|
@@ -72,44 +95,282 @@ export async function startHTTPThreads(threadCount = 2, dynamicThreads?: boolean
|
|
|
72
95
|
// Windows does not support SO_REUSEPORT, so only a single HTTP worker is supported.
|
|
73
96
|
if (process.platform === 'win32') threadCount = 1;
|
|
74
97
|
}
|
|
98
|
+
poolSize = threadCount;
|
|
99
|
+
nextIsolatedIndex = Math.max(nextIsolatedIndex, threadCount);
|
|
100
|
+
const isolated = admittedIsolatedApplications([...isolatedSlots.keys()]);
|
|
101
|
+
const heapShareCount = threadCount + isolated.length;
|
|
75
102
|
for (let i = 0; i < threadCount; i++) {
|
|
76
|
-
startHTTPWorker(i, threadCount);
|
|
103
|
+
const slot = startHTTPWorker(i, threadCount, undefined, heapShareCount);
|
|
104
|
+
workerSlots.push(slot);
|
|
105
|
+
poolSlots.push(slot);
|
|
77
106
|
}
|
|
78
|
-
|
|
107
|
+
// One dedicated worker per isolated application, numbered past the pool so no pool-only duty
|
|
108
|
+
// (worker 0's startup log, the last worker's cleanup) ever lands on it.
|
|
109
|
+
for (const application of isolated) {
|
|
110
|
+
if (isolatedSlots.has(application)) continue;
|
|
111
|
+
const slot = startHTTPWorker(nextIsolatedIndex++, threadCount, application, heapShareCount);
|
|
112
|
+
isolatedSlots.set(application, slot);
|
|
113
|
+
workerSlots.push(slot);
|
|
114
|
+
void watchDedicatedStart(application, slot);
|
|
115
|
+
}
|
|
116
|
+
await Promise.all(workerSlots.filter((slot) => !slot.application).map((slot) => slot.ready));
|
|
79
117
|
} finally {
|
|
118
|
+
for (const slot of workerSlots) if (!slot.application) slot.finishStartup();
|
|
80
119
|
threadsHaveStarted(undefined as any);
|
|
81
120
|
}
|
|
82
121
|
}
|
|
83
122
|
|
|
84
|
-
|
|
85
|
-
|
|
123
|
+
let poolSize = 0;
|
|
124
|
+
const refusedIsolated = new Set<string>(); // reported once, not on every reconcile
|
|
125
|
+
const ISOLATED_WORKER_READY_TIMEOUT_MS = 60_000; // the pool replacement path's backstop
|
|
126
|
+
let nextIsolatedIndex = 0;
|
|
127
|
+
type IsolatedSlot = {
|
|
128
|
+
ready: Promise<void>;
|
|
129
|
+
finishStartup: () => void;
|
|
130
|
+
shutdown: () => Promise<void>;
|
|
131
|
+
setHeapShareCount: (count: number) => void;
|
|
132
|
+
application?: string;
|
|
133
|
+
};
|
|
134
|
+
const isolatedSlots = new Map<string, IsolatedSlot>();
|
|
135
|
+
const poolSlots: IsolatedSlot[] = [];
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The isolated applications that get a dedicated worker. Ones already running keep their place; new
|
|
139
|
+
* ones are admitted up to `threads.maxIsolated`, and only while a dedicated worker would be reachable
|
|
140
|
+
* at all. Everything refused is refused loudly and loaded nowhere -- never downgraded to the pool.
|
|
141
|
+
*/
|
|
142
|
+
function admittedIsolatedApplications(running: string[]): string[] {
|
|
143
|
+
const names = presentIsolatedApplicationNames();
|
|
144
|
+
const admitted = [];
|
|
145
|
+
for (const name of running) {
|
|
146
|
+
if (!names.includes(name)) continue;
|
|
147
|
+
const refusal = isolatedApplicationRefusal(name);
|
|
148
|
+
if (refusal) {
|
|
149
|
+
reportIsolatedRefusal(name, refusal);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
admitted.push(name);
|
|
153
|
+
}
|
|
154
|
+
for (const name of names) {
|
|
155
|
+
if (admitted.includes(name)) continue;
|
|
156
|
+
const refusal = isolatedApplicationRefusal(name) ?? isolatedApplicationCapacityRefusal(name, admitted);
|
|
157
|
+
if (refusal) {
|
|
158
|
+
reportIsolatedRefusal(name, refusal);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
refusedIsolated.delete(name);
|
|
162
|
+
admitted.push(name);
|
|
163
|
+
}
|
|
164
|
+
return admitted;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function reportIsolatedRefusal(name: string, refusal: string) {
|
|
168
|
+
if (refusedIsolated.has(name)) return;
|
|
169
|
+
refusedIsolated.add(name);
|
|
170
|
+
const error = new Error(
|
|
171
|
+
`Application '${name}' is isolated but gets no dedicated worker: ${refusal}; it is not loaded anywhere`
|
|
172
|
+
);
|
|
173
|
+
harperLogger.error(error.message);
|
|
174
|
+
componentLifecycle.failed(name, error, `Component '${name}' failed to load`);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Wait for a dedicated worker to become ready, with the pool replacement path's backstop. A worker that
|
|
179
|
+
* fails, or stays alive without ever reporting ready, is recorded as a failed component, stopped, and
|
|
180
|
+
* only then has its slot freed, so the next reconcile retries against a worker that has exited.
|
|
181
|
+
* Resolves whether it became ready.
|
|
182
|
+
*/
|
|
183
|
+
function watchDedicatedStart(application: string, slot: IsolatedSlot): Promise<boolean> {
|
|
184
|
+
return Promise.race([
|
|
185
|
+
slot.ready,
|
|
186
|
+
new Promise<never>((_, reject) =>
|
|
187
|
+
setTimeout(
|
|
188
|
+
() => reject(new Error(`Dedicated worker for '${application}' did not become ready in time`)),
|
|
189
|
+
ISOLATED_WORKER_READY_TIMEOUT_MS
|
|
190
|
+
).unref()
|
|
191
|
+
),
|
|
192
|
+
])
|
|
193
|
+
.then(() => true)
|
|
194
|
+
.catch(async (error) => {
|
|
195
|
+
harperLogger.error(`Dedicated worker for isolated application '${application}' failed to start`, error);
|
|
196
|
+
componentLifecycle.failed(application, error, `Component '${application}' failed to load`);
|
|
197
|
+
// The slot IS the lease: holding it until the failed worker has actually exited is what stops a
|
|
198
|
+
// reconcile from starting a replacement over its still-bound UDS mirror and still-open stores,
|
|
199
|
+
// and what makes a concurrent drop's `await slot.shutdown()` cover this worker too.
|
|
200
|
+
await slot.shutdown();
|
|
201
|
+
if (isolatedSlots.get(application) !== slot) return false; // a drop already withdrew this lease
|
|
202
|
+
isolatedSlots.delete(application);
|
|
203
|
+
const { cleanupApplicationSockets } = await import('../http.ts');
|
|
204
|
+
// A reconcile may have installed a replacement while that import resolved. Never unlink its mirror.
|
|
205
|
+
if (!isolatedSlots.has(application)) cleanupApplicationSockets(application);
|
|
206
|
+
return false;
|
|
207
|
+
})
|
|
208
|
+
.finally(() => slot.finishStartup());
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Bring the dedicated workers in line with the root config: start one for each isolated application
|
|
213
|
+
* that has none, stop the one of an application that is no longer isolated or no longer configured.
|
|
214
|
+
* Runs on the main thread after every root-component reload (deploy, drop, restart).
|
|
215
|
+
*/
|
|
216
|
+
let reconciling: Promise<string[]> = Promise.resolve([]);
|
|
217
|
+
export function reconcileIsolatedWorkers(): Promise<string[]> {
|
|
218
|
+
// serialized: two reloads in flight must not compute `wanted` against each other's half-done work
|
|
219
|
+
reconciling = reconciling.then(reconcileIsolatedWorkersNow, reconcileIsolatedWorkersNow);
|
|
220
|
+
return reconciling;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function reconcileIsolatedWorkersNow(): Promise<string[]> {
|
|
224
|
+
if (!isMainThread || poolSize === 0) return [];
|
|
225
|
+
const wanted = new Set(admittedIsolatedApplications([...isolatedSlots.keys()]));
|
|
226
|
+
const stopping = [];
|
|
227
|
+
for (const [application, slot] of isolatedSlots) {
|
|
228
|
+
if (wanted.has(application)) continue;
|
|
229
|
+
isolatedSlots.delete(application);
|
|
230
|
+
// awaited: a caller that goes on to remove the application's storage must see its worker gone
|
|
231
|
+
stopping.push(slot.shutdown().then(() => application));
|
|
232
|
+
}
|
|
233
|
+
const stoppedApplications = await Promise.all(stopping);
|
|
234
|
+
if (stoppedApplications.length > 0) {
|
|
235
|
+
const { cleanupApplicationSockets } = await import('../http.ts');
|
|
236
|
+
for (const application of stoppedApplications) cleanupApplicationSockets(application);
|
|
237
|
+
}
|
|
238
|
+
const started: string[] = [];
|
|
239
|
+
const heapShareCount = poolSize + wanted.size;
|
|
240
|
+
for (const slot of poolSlots) slot.setHeapShareCount(heapShareCount);
|
|
241
|
+
for (const slot of isolatedSlots.values()) slot.setHeapShareCount(heapShareCount);
|
|
242
|
+
for (const application of wanted) {
|
|
243
|
+
if (isolatedSlots.has(application)) continue;
|
|
244
|
+
const slot = startHTTPWorker(nextIsolatedIndex++, poolSize, application, heapShareCount);
|
|
245
|
+
isolatedSlots.set(application, slot);
|
|
246
|
+
started.push(application);
|
|
247
|
+
void watchDedicatedStart(application, slot);
|
|
248
|
+
}
|
|
249
|
+
return started;
|
|
250
|
+
}
|
|
251
|
+
if (isMainThread) {
|
|
252
|
+
setIsolatedWorkerReconciler(reconcileIsolatedWorkers);
|
|
253
|
+
setRunningIsolatedApplicationsGetter(() => [...isolatedSlots.keys()]);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function startHTTPWorker(index, threadCount = 1, application?: string, heapShareCount?: number) {
|
|
257
|
+
const { promise: ready, resolve: resolveReady, reject: rejectReady } = Promise.withResolvers<void>();
|
|
258
|
+
let waitingForInitialReady = true;
|
|
259
|
+
let finishCurrentStartup = () => {};
|
|
260
|
+
let startupAttempts = 0;
|
|
261
|
+
// A Worker's threadId reads back as -1 once it has exited, which is exactly when the diagnostics
|
|
262
|
+
// below run, so each attempt records its id while the worker is still alive.
|
|
263
|
+
let lastThreadId = -1;
|
|
264
|
+
let isolatedSlot: IsolatedSlot | undefined;
|
|
265
|
+
const finishStartup = () => {
|
|
266
|
+
waitingForInitialReady = false;
|
|
267
|
+
finishCurrentStartup();
|
|
268
|
+
};
|
|
269
|
+
const failStartup = (error) => {
|
|
270
|
+
if (!waitingForInitialReady) return;
|
|
271
|
+
waitingForInitialReady = false;
|
|
272
|
+
finishCurrentStartup();
|
|
273
|
+
rejectReady(error);
|
|
274
|
+
};
|
|
275
|
+
const workerOptions = {
|
|
86
276
|
name: hdbTerms.THREAD_TYPES.HTTP,
|
|
87
277
|
workerIndex: index,
|
|
88
278
|
threadCount,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
279
|
+
application,
|
|
280
|
+
heapShareCount,
|
|
281
|
+
shouldAutoRestart: application
|
|
282
|
+
? () => isolatedSlot !== undefined && isolatedSlots.get(application) === isolatedSlot
|
|
283
|
+
: undefined,
|
|
284
|
+
onStarted(worker) {
|
|
285
|
+
const attempt = ++startupAttempts;
|
|
286
|
+
const threadId = (lastThreadId = worker.threadId);
|
|
287
|
+
let startupPhase = 'starting';
|
|
288
|
+
let workerReady = false;
|
|
289
|
+
let startupDiagnostic;
|
|
290
|
+
const removeWorker = () => {
|
|
291
|
+
const workerPosition = workers.indexOf(worker);
|
|
292
|
+
if (workerPosition > -1) workers.splice(workerPosition, 1);
|
|
293
|
+
};
|
|
294
|
+
const cleanupStartup = () => {
|
|
295
|
+
clearTimeout(startupDiagnostic);
|
|
296
|
+
worker.off('message', onMessage);
|
|
297
|
+
};
|
|
298
|
+
const describeStartup = (event) =>
|
|
299
|
+
`HTTP worker slot ${index}${application ? ` (isolated application '${application}')` : ''} ${event} before ready (thread ${threadId}, attempt ${attempt}, phase ${startupPhase})`;
|
|
300
|
+
const onMessage = (message) => {
|
|
301
|
+
if (message.type === hdbTerms.ITC_EVENT_TYPES.CHILD_STARTUP_PHASE) {
|
|
302
|
+
startupPhase = message.phase;
|
|
303
|
+
return;
|
|
97
304
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
305
|
+
if (message.type !== hdbTerms.ITC_EVENT_TYPES.CHILD_STARTED) return;
|
|
306
|
+
workerReady = true;
|
|
307
|
+
cleanupStartup();
|
|
308
|
+
if (waitingForInitialReady) {
|
|
309
|
+
waitingForInitialReady = false;
|
|
310
|
+
resolveReady();
|
|
311
|
+
}
|
|
312
|
+
if (!workers.includes(worker)) workers.push(worker);
|
|
313
|
+
worker.on('shutdown', removeWorker);
|
|
314
|
+
};
|
|
315
|
+
const onExit = () => {
|
|
316
|
+
cleanupStartup();
|
|
317
|
+
if (workerReady) removeWorker();
|
|
318
|
+
// A rolling restart marks both the outgoing worker and its still-booting replacement
|
|
319
|
+
// wasShutdown, so a shutdown landing mid-boot is routine, not a startup failure.
|
|
320
|
+
else if (!worker.wasShutdown) harperLogger.error(describeStartup('exited'));
|
|
321
|
+
};
|
|
322
|
+
worker.on('message', onMessage);
|
|
323
|
+
worker.on('exit', onExit);
|
|
324
|
+
if (waitingForInitialReady) {
|
|
325
|
+
startupDiagnostic = setTimeout(() => {
|
|
326
|
+
if (workerReady || !waitingForInitialReady) return;
|
|
327
|
+
const message = describeStartup(`has not become ready after ${HTTP_WORKER_STARTUP_DIAGNOSTIC_MS}ms`);
|
|
328
|
+
harperLogger.error(message);
|
|
329
|
+
}, HTTP_WORKER_STARTUP_DIAGNOSTIC_MS).unref();
|
|
330
|
+
finishCurrentStartup = cleanupStartup;
|
|
110
331
|
}
|
|
111
332
|
},
|
|
112
|
-
|
|
333
|
+
onRestartExhausted() {
|
|
334
|
+
const error = new Error(`HTTP worker slot ${index} exhausted restarts (thread ${lastThreadId})`);
|
|
335
|
+
if (waitingForInitialReady) failStartup(error);
|
|
336
|
+
else if (application && isolatedSlot && isolatedSlots.get(application) === isolatedSlot) {
|
|
337
|
+
isolatedSlots.delete(application);
|
|
338
|
+
componentLifecycle.failed(application, error, `Component '${application}' worker failed`);
|
|
339
|
+
void import('../http.ts').then(
|
|
340
|
+
({ cleanupApplicationSockets }) => {
|
|
341
|
+
// A config reconciliation may already have installed a replacement after the
|
|
342
|
+
// exhausted slot released its lease. Never unlink that replacement's mirror.
|
|
343
|
+
if (isolatedSlots.has(application)) return;
|
|
344
|
+
cleanupApplicationSockets(application);
|
|
345
|
+
},
|
|
346
|
+
(cleanupError) => {
|
|
347
|
+
harperLogger.error(
|
|
348
|
+
`Could not clean sockets for failed isolated application '${application}'`,
|
|
349
|
+
cleanupError
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
startWorker(join(__dirname, './threadServer.js'), workerOptions);
|
|
357
|
+
// Stop of a dedicated worker whose application is gone: every worker carrying the application,
|
|
358
|
+
// a crashed one's replacement still booting included, so none is left running the removed app.
|
|
359
|
+
let shutdownPromise: Promise<void> | undefined;
|
|
360
|
+
const shutdown = (): Promise<void> => {
|
|
361
|
+
if (!application) return Promise.resolve();
|
|
362
|
+
if (shutdownPromise) return shutdownPromise;
|
|
363
|
+
shutdownPromise = Promise.all(workersForApplication(application).map((worker) => stopWorker(worker))).then(
|
|
364
|
+
() => undefined
|
|
365
|
+
);
|
|
366
|
+
failStartup(new Error(`Dedicated worker for '${application}' was stopped before it became ready`));
|
|
367
|
+
return shutdownPromise;
|
|
368
|
+
};
|
|
369
|
+
const setHeapShareCount = (count: number) => {
|
|
370
|
+
workerOptions.heapShareCount = count;
|
|
371
|
+
};
|
|
372
|
+
isolatedSlot = { ready, finishStartup, shutdown, setHeapShareCount, application };
|
|
373
|
+
return isolatedSlot;
|
|
113
374
|
}
|
|
114
375
|
|
|
115
376
|
// basically, the amount of additional idleness to expect based on previous idleness (some work will continue, some
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import harperLogger from '../../utility/logging/harper_logger.ts';
|
|
2
|
+
import { MIN_THREAD_HEAP_MEMORY_MB } from '../../utility/hdbTerms.ts';
|
|
3
|
+
|
|
4
|
+
let recoveryWarned = false;
|
|
5
|
+
|
|
6
|
+
export function isStartableThreadHeapMemory(configuredMb: unknown): boolean {
|
|
7
|
+
return Number.isFinite(configuredMb) && (configuredMb as number) >= MIN_THREAD_HEAP_MEMORY_MB;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Below the minimum, Node aborts the whole process from v8::Isolate::Initialize before any
|
|
11
|
+
// JavaScript runs, so this has to be caught ahead of startWorker — no error handler downstream can
|
|
12
|
+
// contain it. The value on disk is an untrusted boot input (replicated, env var, hand edit, older
|
|
13
|
+
// peer), so an unstartable one falls back to the caller's computed default rather than stopping the
|
|
14
|
+
// node.
|
|
15
|
+
export function resolveThreadHeapMemoryMb(configured: unknown): number | undefined {
|
|
16
|
+
if (configured == null) return undefined;
|
|
17
|
+
const configuredMb = Number(configured);
|
|
18
|
+
if (isStartableThreadHeapMemory(configuredMb)) return configuredMb;
|
|
19
|
+
if (!recoveryWarned) {
|
|
20
|
+
recoveryWarned = true;
|
|
21
|
+
harperLogger.error(
|
|
22
|
+
`Ignoring threads.maxHeapMemory: ${JSON.stringify(configured)} is below the ${MIN_THREAD_HEAP_MEMORY_MB}MB a worker thread can start on. Using the default instead; replace the configured value before downgrading.`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
@@ -26,6 +26,11 @@ const {
|
|
|
26
26
|
getShutdownDrainCeilingMs,
|
|
27
27
|
} = require('../../components/shutdownDrain.ts');
|
|
28
28
|
const { realExit } = require('./workerProcessGuard.ts');
|
|
29
|
+
const {
|
|
30
|
+
thisThreadsIsolatedApplication,
|
|
31
|
+
applicationSocketName,
|
|
32
|
+
shouldStartUwsListenerHere,
|
|
33
|
+
} = require('./isolatedApplications.ts');
|
|
29
34
|
const { isBun } = require('../serverHelpers/Request.ts');
|
|
30
35
|
const { getDomainSocketPathMaxBytes, isDomainSocketPathTooLong } = require('../../utility/domainSocket.ts');
|
|
31
36
|
const { createTLSSelector, getEffectiveTlsCiphers } = require('../../security/keys.ts');
|
|
@@ -169,6 +174,22 @@ function closeServers() {
|
|
|
169
174
|
}
|
|
170
175
|
|
|
171
176
|
function startServers() {
|
|
177
|
+
// A worker that has not yet posted child_started owns no ref'd handle: addPort()
|
|
178
|
+
// (manageThreads) unrefs parentPort, component watchers are persistent:false, and the
|
|
179
|
+
// reporting timers are unref'd. An await inside loadRootComponents whose completion
|
|
180
|
+
// arrives through a non-ref-holding source — e.g. rocksdb-js delivers cross-thread
|
|
181
|
+
// lock-release and parked-commit-retry wakes through unref'd threadsafe functions —
|
|
182
|
+
// can then drain the event loop, exiting the worker cleanly (code 0) before the ready
|
|
183
|
+
// handshake and aborting the whole node's startup. Hold a ref for the entire pre-ready
|
|
184
|
+
// window; the SHUTDOWN path unrefs it for graceful exit as before.
|
|
185
|
+
parentPort?.ref();
|
|
186
|
+
let startupPhase = 'loading components';
|
|
187
|
+
const reportStartupPhase = (phase) => {
|
|
188
|
+
startupPhase = phase;
|
|
189
|
+
try {
|
|
190
|
+
parentPort?.postMessage({ type: terms.ITC_EVENT_TYPES.CHILD_STARTUP_PHASE, phase });
|
|
191
|
+
} catch {}
|
|
192
|
+
};
|
|
172
193
|
const rootPath = env.get(terms.CONFIG_PARAMS.ROOTPATH);
|
|
173
194
|
if (rootPath) {
|
|
174
195
|
try {
|
|
@@ -177,7 +198,9 @@ function startServers() {
|
|
|
177
198
|
// ignore any errors with this; just a best effort for now
|
|
178
199
|
}
|
|
179
200
|
}
|
|
180
|
-
|
|
201
|
+
reportStartupPhase(startupPhase);
|
|
202
|
+
let listening;
|
|
203
|
+
const loaded = require('../loadRootComponents.js')
|
|
181
204
|
.loadRootComponents(true)
|
|
182
205
|
.then(() => {
|
|
183
206
|
parentPort
|
|
@@ -207,6 +230,7 @@ function startServers() {
|
|
|
207
230
|
})
|
|
208
231
|
.then(() => closeServers())
|
|
209
232
|
.then(() => whenScopesClosed())
|
|
233
|
+
.then(() => require('../../resources/databases.ts').closeBranchDatabases())
|
|
210
234
|
.then(() => {
|
|
211
235
|
realExit(0);
|
|
212
236
|
});
|
|
@@ -222,21 +246,30 @@ function startServers() {
|
|
|
222
246
|
}
|
|
223
247
|
})
|
|
224
248
|
.ref(); // use this to keep the thread running until we are ready to shutdown and clean up handles
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
// notify that we are now ready to start receiving requests
|
|
228
|
-
Promise.resolve(listening).then(() => {
|
|
229
|
-
if (getWorkerIndex() === 0) {
|
|
230
|
-
try {
|
|
231
|
-
startupLog(portServer);
|
|
232
|
-
} catch (err) {
|
|
233
|
-
console.error('Error displaying start-up log', err);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
parentPort?.postMessage({ type: terms.ITC_EVENT_TYPES.CHILD_STARTED });
|
|
237
|
-
});
|
|
249
|
+
reportStartupPhase('binding listeners');
|
|
250
|
+
listening = listenOnPorts();
|
|
238
251
|
});
|
|
239
252
|
componentsLoadedResolve(loaded);
|
|
253
|
+
const started = loaded
|
|
254
|
+
.then(() => listening)
|
|
255
|
+
.then(() => {
|
|
256
|
+
reportStartupPhase('ready');
|
|
257
|
+
if (getWorkerIndex() === 0) {
|
|
258
|
+
try {
|
|
259
|
+
startupLog(portServer);
|
|
260
|
+
} catch (err) {
|
|
261
|
+
console.error('Error displaying start-up log', err);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
parentPort?.postMessage({ type: terms.ITC_EVENT_TYPES.CHILD_STARTED });
|
|
265
|
+
})
|
|
266
|
+
.catch((error) => {
|
|
267
|
+
const failedPhase = startupPhase;
|
|
268
|
+
reportStartupPhase(`failed during ${failedPhase}`);
|
|
269
|
+
harperLogger.fatal(`HTTP worker startup failed during ${failedPhase}`, error);
|
|
270
|
+
if (isMainThread) throw error;
|
|
271
|
+
realExit(1);
|
|
272
|
+
});
|
|
240
273
|
// Clean up UDS files and force-close Bun server connections on unexpected exit.
|
|
241
274
|
// Without the stop(true) call, clients holding keep-alive connections to a dead Bun
|
|
242
275
|
// worker never receive a FIN/RST and hang indefinitely waiting for a response.
|
|
@@ -253,7 +286,7 @@ function startServers() {
|
|
|
253
286
|
}
|
|
254
287
|
httpComponent.cleanupUdsFiles();
|
|
255
288
|
});
|
|
256
|
-
return
|
|
289
|
+
return started;
|
|
257
290
|
}
|
|
258
291
|
/**
|
|
259
292
|
* An overlong path is the only condition that can skip a domain-socket listener. Check before
|
|
@@ -302,10 +335,15 @@ function listenOnPorts() {
|
|
|
302
335
|
const server = SERVERS[port];
|
|
303
336
|
|
|
304
337
|
// If server is unix domain socket
|
|
338
|
+
// A worker dedicated to an isolated application binds only its own per-thread mirrors: not the shared
|
|
339
|
+
// ports (the kernel would hand it every application's connections) and not a global domain socket
|
|
340
|
+
// such as the operations API's, which it would take from the main thread.
|
|
305
341
|
if (port.includes?.('/')) {
|
|
306
|
-
|
|
342
|
+
if (!thisThreadsIsolatedApplication() || server.isPerThreadSocket)
|
|
343
|
+
listening.push(listenOnDomainSocket(port, server));
|
|
307
344
|
continue;
|
|
308
345
|
}
|
|
346
|
+
if (thisThreadsIsolatedApplication()) continue;
|
|
309
347
|
let listen_on;
|
|
310
348
|
let ownerWorkerIndex = 0; // lowest eligible worker index for this port
|
|
311
349
|
const threadRange = env.get(terms.CONFIG_PARAMS.HTTP_THREADRANGE);
|
|
@@ -378,6 +416,7 @@ function listenOnPorts() {
|
|
|
378
416
|
if (uwsServeConfigs) {
|
|
379
417
|
for (const key in uwsServeConfigs) {
|
|
380
418
|
const cfg = uwsServeConfigs[key];
|
|
419
|
+
if (!shouldStartUwsListenerHere(cfg)) continue; // dedicated worker: its own mirrors only
|
|
381
420
|
if (cfg.socketPath && existsSync(cfg.socketPath)) unlinkSync(cfg.socketPath);
|
|
382
421
|
const { createUwsServer } = require('../serverHelpers/uwsServer.ts');
|
|
383
422
|
listening.push(
|
|
@@ -427,7 +466,7 @@ async function listenOnPortsBun() {
|
|
|
427
466
|
for (let port in bunServeConfigs) {
|
|
428
467
|
const config = bunServeConfigs[port];
|
|
429
468
|
const threadRange = env.get(terms.CONFIG_PARAMS.HTTP_THREADRANGE);
|
|
430
|
-
if (threadRange) {
|
|
469
|
+
if (threadRange && !thisThreadsIsolatedApplication()) {
|
|
431
470
|
let threadRangeArray = typeof threadRange === 'string' ? threadRange.split('-') : threadRange;
|
|
432
471
|
let threadIndex = getWorkerIndex();
|
|
433
472
|
if (threadIndex < threadRangeArray[0] || threadIndex > threadRangeArray[1]) {
|
|
@@ -504,15 +543,22 @@ async function listenOnPortsBun() {
|
|
|
504
543
|
delete serveOptions.port;
|
|
505
544
|
}
|
|
506
545
|
if (isNaN(serveOptions.port)) continue;
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
546
|
+
// Keep ownership independent of address syntax: adding a Bun UDS route later must not widen
|
|
547
|
+
// a dedicated worker's ingress beyond its application-addressed mirror below.
|
|
548
|
+
if (!thisThreadsIsolatedApplication()) {
|
|
549
|
+
const bunServer = Bun.serve(serveOptions);
|
|
550
|
+
SERVERS[port] = bunServer;
|
|
551
|
+
harperLogger.trace('Bun listening on port ' + port, threadId);
|
|
552
|
+
}
|
|
510
553
|
|
|
511
554
|
// Create a corresponding Unix Domain Socket mirror for secure ports
|
|
512
555
|
if (config.isSecure && env.get(terms.CONFIG_PARAMS.TLS_UNIXDOMAINSOCKETS)) {
|
|
513
556
|
const socketsDir = join(env.getHdbBasePath(), 'sockets');
|
|
514
557
|
mkdirSync(socketsDir, { recursive: true });
|
|
515
|
-
const
|
|
558
|
+
const isolatedApplication = thisThreadsIsolatedApplication();
|
|
559
|
+
const socketName = isolatedApplication
|
|
560
|
+
? applicationSocketName(isolatedApplication, port)
|
|
561
|
+
: `${getWorkerIndex()}-${port}`;
|
|
516
562
|
const udsPath = join(socketsDir, `${socketName}.sock`);
|
|
517
563
|
const yamlPath = join(socketsDir, `${socketName}.yaml`);
|
|
518
564
|
if (existsSync(udsPath)) unlinkSync(udsPath);
|
|
@@ -536,6 +582,7 @@ async function listenOnPortsBun() {
|
|
|
536
582
|
}
|
|
537
583
|
} catch (error) {
|
|
538
584
|
harperLogger.error(`Unable to start Bun server on port ${port}`, error);
|
|
585
|
+
if (thisThreadsIsolatedApplication()) throw error;
|
|
539
586
|
}
|
|
540
587
|
}
|
|
541
588
|
// Also start any non-HTTP servers (raw socket servers) that were registered in SERVERS
|
|
@@ -546,6 +593,7 @@ async function listenOnPortsBun() {
|
|
|
546
593
|
if (server?.stop || bunServeConfigs[port]) continue;
|
|
547
594
|
if (server?.listen) {
|
|
548
595
|
if (port.includes?.('/')) {
|
|
596
|
+
if (thisThreadsIsolatedApplication() && !server.isPerThreadSocket) continue; // as in listenOnPorts
|
|
549
597
|
listening.push(listenOnDomainSocket(port, server));
|
|
550
598
|
} else {
|
|
551
599
|
const lastColon = String(port).lastIndexOf(':');
|
|
@@ -645,7 +693,10 @@ function onSocket(listener, options) {
|
|
|
645
693
|
if (env.get(terms.CONFIG_PARAMS.TLS_UNIXDOMAINSOCKETS)) {
|
|
646
694
|
const socketsDir = join(env.getHdbBasePath(), 'sockets');
|
|
647
695
|
mkdirSync(socketsDir, { recursive: true });
|
|
648
|
-
const
|
|
696
|
+
const isolatedApplication = thisThreadsIsolatedApplication();
|
|
697
|
+
const socketName = isolatedApplication
|
|
698
|
+
? applicationSocketName(isolatedApplication, options.securePort)
|
|
699
|
+
: `${getWorkerIndex()}-${options.securePort}`;
|
|
649
700
|
const udsPath = join(socketsDir, `${socketName}.sock`);
|
|
650
701
|
const yamlPath = join(socketsDir, `${socketName}.yaml`);
|
|
651
702
|
|
package/sqlTranslator/index.ts
CHANGED
|
@@ -17,7 +17,7 @@ import * as terms from '../utility/hdbTerms.ts';
|
|
|
17
17
|
import { handleHDBError } from '../utility/errors/hdbError.ts';
|
|
18
18
|
import { HTTP_STATUS_CODES } from '../utility/errors/commonErrors.ts';
|
|
19
19
|
import * as sqlEngineRouter from '../sqlEngine/router.ts';
|
|
20
|
-
import {
|
|
20
|
+
import { getOperationAuthorizationState } from '../server/serverHelpers/operationAuthorizationState.ts';
|
|
21
21
|
|
|
22
22
|
//here we call to define and import custom functions to alasql
|
|
23
23
|
alasqlFunctionImporter(alasql);
|
|
@@ -73,21 +73,37 @@ export function evaluateSQL(jsonMessage: any, callback: any) {
|
|
|
73
73
|
* @param parsedSqlObject - The Parsed SQL statement specified in the inbound json message, of type ParsedSQLObject.
|
|
74
74
|
* @returns {Array} - False if permissions check denys the statement.
|
|
75
75
|
*/
|
|
76
|
-
export function checkASTPermissions(jsonMessage: any, parsedSqlObject: any) {
|
|
76
|
+
export function checkASTPermissions(jsonMessage: any, parsedSqlObject: any, apiOperation?: string) {
|
|
77
77
|
let verifyResult = undefined;
|
|
78
78
|
try {
|
|
79
79
|
verifyResult = opAuth.verifyPermsAST(
|
|
80
80
|
parsedSqlObject.ast.statements[0],
|
|
81
81
|
jsonMessage.hdb_user,
|
|
82
|
-
parsedSqlObject.variant
|
|
82
|
+
parsedSqlObject.variant,
|
|
83
|
+
// The top-level API operation for the token-scope check: `sql` for a direct SQL call, but
|
|
84
|
+
// `export_local`/`export_to_s3` when the SQL rides inside a job's search_operation.
|
|
85
|
+
//
|
|
86
|
+
// From the explicit argument or the dispatched operation — deliberately NEVER a field read
|
|
87
|
+
// off `jsonMessage`. On the direct-SQL path that object IS the client's request body, and
|
|
88
|
+
// this check is the ONLY gate there, since the `sql` branch of chooseOperation is mutually
|
|
89
|
+
// exclusive with its verifyPerms call. Any body field consulted here is therefore a way for
|
|
90
|
+
// a caller to name whichever operation their token scope happens to allow and run arbitrary
|
|
91
|
+
// SQL under it.
|
|
92
|
+
//
|
|
93
|
+
// A job's re-parse would otherwise land here with the nested search_operation, whose
|
|
94
|
+
// `operation` is the inner `sql`; the job worker supplies the real one out of async context
|
|
95
|
+
// instead (operationAuthorizationState), which a request cannot set.
|
|
96
|
+
apiOperation ?? jsonMessage.operation
|
|
83
97
|
);
|
|
84
|
-
parsedSqlObject.permissions_checked = true;
|
|
85
98
|
} catch (e) {
|
|
86
99
|
throw e;
|
|
87
100
|
}
|
|
88
101
|
if (verifyResult) {
|
|
89
102
|
return verifyResult;
|
|
90
103
|
}
|
|
104
|
+
// Only after a pass: this flag is what processAST trusts to skip the gate, so a denied AST
|
|
105
|
+
// carrying it would read as already authorized.
|
|
106
|
+
parsedSqlObject.permissions_checked = true;
|
|
91
107
|
return null;
|
|
92
108
|
}
|
|
93
109
|
|
|
@@ -134,10 +150,17 @@ export function processAST(jsonMessage: any, parsedSqlObject: any, callback: any
|
|
|
134
150
|
// runWithOperationAuthorizationBypass), never body state — jsonMessage.bypass_auth is
|
|
135
151
|
// caller-controlled and is stripped before operation code sees it (see
|
|
136
152
|
// server/serverHelpers/serverHandlers.js and components/mcp/tools/operations.ts).
|
|
137
|
-
if (!
|
|
138
|
-
|
|
139
|
-
if (
|
|
140
|
-
|
|
153
|
+
if (!parsedSqlObject.permissions_checked) {
|
|
154
|
+
const authorizationState = getOperationAuthorizationState();
|
|
155
|
+
if (authorizationState?.bypassAuth !== true) {
|
|
156
|
+
let permissionsCheck = checkASTPermissions(jsonMessage, parsedSqlObject, authorizationState?.apiOperation);
|
|
157
|
+
// A denial is a PermissionResponseObject, which has no `length`.
|
|
158
|
+
if (permissionsCheck) {
|
|
159
|
+
// Logged here because this is the last place the reason exists: evaluateSQL drops the
|
|
160
|
+
// second callback argument, so a job worker records only the bare status.
|
|
161
|
+
logger.warn('SQL statement refused by AST permission check:', permissionsCheck);
|
|
162
|
+
return callback(UNAUTHORIZED_RESPONSE, permissionsCheck);
|
|
163
|
+
}
|
|
141
164
|
}
|
|
142
165
|
}
|
|
143
166
|
|