@harperfast/harper 5.0.0-alpha.10 → 5.0.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/bin/BinObjects.js +17 -0
- package/bin/cliOperations.js +157 -0
- package/bin/copyDb.ts +280 -0
- package/bin/harper.js +156 -0
- package/bin/install.js +15 -0
- package/bin/lite.js +5 -0
- package/bin/restart.js +201 -0
- package/bin/run.js +409 -0
- package/bin/status.js +65 -0
- package/bin/stop.js +22 -0
- package/bin/upgrade.js +134 -0
- package/components/Application.ts +646 -0
- package/components/ApplicationScope.ts +49 -0
- package/components/Component.ts +53 -0
- package/components/ComponentV1.ts +342 -0
- package/components/DEFAULT_CONFIG.ts +18 -0
- package/components/EntryHandler.ts +227 -0
- package/components/Logger.ts +14 -0
- package/components/OptionsWatcher.ts +354 -0
- package/components/PluginModule.ts +6 -0
- package/components/Scope.ts +329 -0
- package/components/componentLoader.ts +529 -0
- package/components/deriveCommonPatternBase.ts +31 -0
- package/components/deriveGlobOptions.ts +44 -0
- package/components/deriveURLPath.ts +57 -0
- package/components/operations.js +658 -0
- package/components/operationsValidation.js +246 -0
- package/components/packageComponent.ts +39 -0
- package/components/requestRestart.ts +26 -0
- package/components/resolveBaseURLPath.ts +38 -0
- package/components/status/ComponentStatus.ts +110 -0
- package/components/status/ComponentStatusRegistry.ts +251 -0
- package/components/status/api.ts +153 -0
- package/components/status/crossThread.ts +405 -0
- package/components/status/errors.ts +152 -0
- package/components/status/index.ts +44 -0
- package/components/status/internal.ts +65 -0
- package/components/status/registry.ts +12 -0
- package/components/status/types.ts +96 -0
- package/config/RootConfigWatcher.ts +59 -0
- package/config/configHelpers.ts +11 -0
- package/config/configUtils.js +967 -0
- package/config/harperConfigEnvVars.ts +641 -0
- package/dataLayer/CreateAttributeObject.js +25 -0
- package/dataLayer/CreateTableObject.js +11 -0
- package/dataLayer/DataLayerObjects.js +43 -0
- package/dataLayer/DeleteBeforeObject.js +22 -0
- package/dataLayer/DeleteObject.js +25 -0
- package/dataLayer/DropAttributeObject.js +11 -0
- package/dataLayer/GetBackupObject.js +22 -0
- package/dataLayer/InsertObject.js +24 -0
- package/dataLayer/ReadAuditLogObject.js +24 -0
- package/dataLayer/SQLSearch.js +1335 -0
- package/dataLayer/SearchByConditionsObject.js +61 -0
- package/dataLayer/SearchByHashObject.js +21 -0
- package/dataLayer/SearchObject.js +45 -0
- package/dataLayer/SqlSearchObject.js +14 -0
- package/dataLayer/UpdateObject.js +23 -0
- package/dataLayer/UpsertObject.js +23 -0
- package/dataLayer/bulkLoad.js +813 -0
- package/dataLayer/dataObjects/BulkLoadObjects.js +27 -0
- package/dataLayer/dataObjects/UpsertObject.js +23 -0
- package/dataLayer/delete.js +164 -0
- package/dataLayer/export.js +381 -0
- package/dataLayer/getBackup.js +40 -0
- package/dataLayer/harperBridge/BridgeMethods.js +81 -0
- package/dataLayer/harperBridge/ResourceBridge.ts +633 -0
- package/dataLayer/harperBridge/bridgeUtility/insertUpdateReturnObj.js +28 -0
- package/dataLayer/harperBridge/bridgeUtility/insertUpdateValidate.js +88 -0
- package/dataLayer/harperBridge/harperBridge.js +21 -0
- package/dataLayer/harperBridge/lmdbBridge/LMDBBridge.js +119 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +19 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateAttribute.js +112 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateRecords.js +67 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateSchema.js +31 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateTable.js +94 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteAuditLogsBefore.js +98 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteRecords.js +89 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropAttribute.js +109 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropSchema.js +107 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropTable.js +137 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbFlush.js +35 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetBackup.js +111 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByHash.js +28 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByValue.js +29 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbReadAuditLog.js +207 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByConditions.js +156 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByHash.js +21 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByValue.js +30 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbTransaction.js +19 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpdateRecords.js +64 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpsertRecords.js +70 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBCreateAttributeObject.js +22 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBDeleteTransactionObject.js +23 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBInsertTransactionObject.js +22 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBTransactionObject.js +23 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpdateTransactionObject.js +24 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpsertTransactionObject.js +24 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/TableSizeObject.js +25 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializeHashSearch.js +21 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js +157 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCheckForNewAttributes.js +94 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCreateTransactionsAuditEnvironment.js +39 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.js +34 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbProcessRows.js +100 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbSearch.js +371 -0
- package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbWriteTransaction.js +109 -0
- package/dataLayer/hdbInfoController.js +254 -0
- package/dataLayer/insert.js +266 -0
- package/dataLayer/readAuditLog.js +59 -0
- package/dataLayer/schema.js +366 -0
- package/dataLayer/schemaDescribe.js +289 -0
- package/dataLayer/search.js +60 -0
- package/dataLayer/transaction.js +17 -0
- package/dataLayer/update.js +124 -0
- package/dist/components/Logger.d.ts +12 -0
- package/dist/components/Logger.js +3 -0
- package/dist/components/Logger.js.map +1 -0
- package/dist/components/Scope.d.ts +14 -4
- package/dist/components/Scope.js +18 -10
- package/dist/components/Scope.js.map +1 -1
- package/dist/components/componentLoader.js +16 -9
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/operations.js +2 -2
- package/dist/components/operations.js.map +1 -1
- package/dist/config/configUtils.d.ts +1 -1
- package/dist/config/configUtils.js +1 -1
- package/dist/config/configUtils.js.map +1 -1
- package/dist/dataLayer/CreateTableObject.d.ts +2 -2
- package/dist/dataLayer/CreateTableObject.js +2 -2
- package/dist/dataLayer/CreateTableObject.js.map +1 -1
- package/dist/dataLayer/delete.d.ts +1 -1
- package/dist/dataLayer/schema.js +6 -5
- package/dist/dataLayer/schema.js.map +1 -1
- package/dist/dataLayer/schemaDescribe.js +1 -1
- package/dist/dataLayer/schemaDescribe.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/DatabaseTransaction.d.ts +1 -1
- package/dist/resources/IterableEventQueue.d.ts +1 -1
- package/dist/resources/LMDBTransaction.d.ts +5 -1
- package/dist/resources/Resource.d.ts +1 -1
- package/dist/resources/RocksIndexStore.d.ts +3 -3
- package/dist/resources/RocksTransactionLogStore.d.ts +6 -3
- package/dist/resources/Table.d.ts +15 -6
- package/dist/resources/Table.js +4 -1
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/read.js +32 -22
- package/dist/resources/analytics/read.js.map +1 -1
- package/dist/resources/analytics/write.js +3 -6
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/auditStore.d.ts +3 -3
- package/dist/resources/blob.d.ts +25 -2
- package/dist/resources/databases.d.ts +12 -2
- package/dist/resources/databases.js +22 -19
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/search.js +11 -5
- package/dist/resources/search.js.map +1 -1
- package/dist/resources/transaction.d.ts +2 -1
- package/dist/security/auth.js +1 -1
- package/dist/security/auth.js.map +1 -1
- package/dist/security/cryptoHash.d.ts +2 -2
- package/dist/security/jsLoader.js +243 -66
- package/dist/security/jsLoader.js.map +1 -1
- package/dist/security/keys.js +4 -5
- package/dist/security/keys.js.map +1 -1
- package/dist/security/user.js +3 -3
- package/dist/security/user.js.map +1 -1
- package/dist/server/REST.js +16 -2
- package/dist/server/REST.js.map +1 -1
- package/dist/server/Server.d.ts +2 -1
- package/dist/server/Server.js.map +1 -1
- package/dist/server/fastifyRoutes/plugins/hdbCore.d.ts +6 -1
- package/dist/server/fastifyRoutes.js +2 -0
- package/dist/server/fastifyRoutes.js.map +1 -1
- package/dist/server/http.js +12 -6
- package/dist/server/http.js.map +1 -1
- package/dist/server/jobs/JobObject.d.ts +3 -3
- package/dist/server/loadRootComponents.js +1 -0
- package/dist/server/loadRootComponents.js.map +1 -1
- package/dist/server/operationsServer.js +3 -1
- package/dist/server/operationsServer.js.map +1 -1
- package/dist/server/serverHelpers/JSONStream.d.ts +3 -3
- package/dist/server/serverHelpers/Request.d.ts +5 -5
- package/dist/server/serverHelpers/requestTimePlugin.d.ts +1 -1
- package/dist/server/threads/manageThreads.d.ts +2 -2
- package/dist/server/threads/manageThreads.js +50 -35
- package/dist/server/threads/manageThreads.js.map +1 -1
- package/dist/server/threads/socketRouter.d.ts +1 -1
- package/dist/sqlTranslator/deleteTranslator.d.ts +1 -1
- package/dist/utility/AWS/AWSConnector.d.ts +3 -2
- package/dist/utility/common_utils.d.ts +3 -3
- package/dist/utility/environment/systemInformation.d.ts +1 -0
- package/dist/utility/functions/date/dateFunctions.d.ts +11 -11
- package/dist/utility/globalSchema.d.ts +1 -1
- package/dist/utility/hdbTerms.d.ts +3 -0
- package/dist/utility/hdbTerms.js +3 -0
- package/dist/utility/hdbTerms.js.map +1 -1
- package/dist/utility/installation.d.ts +2 -4
- package/dist/utility/installation.js.map +1 -1
- package/dist/utility/lmdb/commonUtility.d.ts +1 -0
- package/dist/utility/lmdb/deleteUtility.d.ts +1 -0
- package/dist/utility/lmdb/environmentUtility.d.ts +1 -0
- package/dist/utility/lmdb/searchUtility.d.ts +2 -1
- package/dist/utility/lmdb/writeUtility.d.ts +1 -0
- package/dist/utility/logging/harper_logger.d.ts +6 -6
- package/dist/utility/processManagement/processManagement.d.ts +1 -1
- package/dist/utility/processManagement/servicesConfig.d.ts +12 -6
- package/dist/validation/common_validators.d.ts +4 -3
- package/dist/validation/configValidator.d.ts +3 -2
- package/index.d.ts +56 -0
- package/index.js +41 -0
- package/json/systemSchema.json +373 -0
- package/launchServiceScripts/launchHarperDB.js +3 -0
- package/launchServiceScripts/utility/checkNodeVersion.js +15 -0
- package/package.json +21 -3
- package/resources/DatabaseTransaction.ts +378 -0
- package/resources/ErrorResource.ts +57 -0
- package/resources/IterableEventQueue.ts +94 -0
- package/resources/LMDBTransaction.ts +349 -0
- package/resources/RecordEncoder.ts +702 -0
- package/resources/RequestTarget.ts +134 -0
- package/resources/Resource.ts +789 -0
- package/resources/ResourceInterface.ts +221 -0
- package/resources/ResourceInterfaceV2.ts +53 -0
- package/resources/ResourceV2.ts +67 -0
- package/resources/Resources.ts +162 -0
- package/resources/RocksIndexStore.ts +70 -0
- package/resources/RocksTransactionLogStore.ts +352 -0
- package/resources/Table.ts +4527 -0
- package/resources/analytics/hostnames.ts +72 -0
- package/resources/analytics/metadata.ts +10 -0
- package/resources/analytics/read.ts +252 -0
- package/resources/analytics/write.ts +803 -0
- package/resources/auditStore.ts +556 -0
- package/resources/blob.ts +1268 -0
- package/resources/crdt.ts +125 -0
- package/resources/dataLoader.ts +527 -0
- package/resources/databases.ts +1290 -0
- package/resources/graphql.ts +221 -0
- package/resources/indexes/HierarchicalNavigableSmallWorld.ts +638 -0
- package/resources/indexes/customIndexes.ts +7 -0
- package/resources/indexes/vector.ts +38 -0
- package/resources/jsResource.ts +86 -0
- package/resources/loadEnv.ts +22 -0
- package/resources/login.ts +18 -0
- package/resources/openApi.ts +409 -0
- package/resources/registrationDeprecated.ts +8 -0
- package/resources/replayLogs.ts +136 -0
- package/resources/roles.ts +98 -0
- package/resources/search.ts +1301 -0
- package/resources/tracked.ts +584 -0
- package/resources/transaction.ts +89 -0
- package/resources/transactionBroadcast.ts +258 -0
- package/security/auth.ts +376 -0
- package/security/certificateVerification/certificateVerificationSource.ts +84 -0
- package/security/certificateVerification/configValidation.ts +107 -0
- package/security/certificateVerification/crlVerification.ts +623 -0
- package/security/certificateVerification/index.ts +121 -0
- package/security/certificateVerification/ocspVerification.ts +148 -0
- package/security/certificateVerification/pkijs-ed25519-patch.ts +188 -0
- package/security/certificateVerification/types.ts +128 -0
- package/security/certificateVerification/verificationConfig.ts +138 -0
- package/security/certificateVerification/verificationUtils.ts +447 -0
- package/security/cryptoHash.js +42 -0
- package/security/data_objects/PermissionAttributeResponseObject.js +15 -0
- package/security/data_objects/PermissionResponseObject.js +115 -0
- package/security/data_objects/PermissionTableResponseObject.js +20 -0
- package/security/fastifyAuth.js +169 -0
- package/security/impersonation.ts +160 -0
- package/security/jsLoader.ts +716 -0
- package/security/keys.js +948 -0
- package/security/permissionsTranslator.js +300 -0
- package/security/role.js +218 -0
- package/security/tokenAuthentication.ts +228 -0
- package/security/user.ts +449 -0
- package/server/DurableSubscriptionsSession.ts +503 -0
- package/server/REST.ts +407 -0
- package/server/Server.ts +89 -0
- package/server/fastifyRoutes/helpers/getCORSOptions.js +36 -0
- package/server/fastifyRoutes/helpers/getHeaderTimeoutConfig.js +15 -0
- package/server/fastifyRoutes/helpers/getServerOptions.js +33 -0
- package/server/fastifyRoutes/plugins/hdbCore.js +39 -0
- package/server/fastifyRoutes.ts +205 -0
- package/server/graphqlQuerying.ts +700 -0
- package/server/http.ts +640 -0
- package/server/itc/serverHandlers.js +161 -0
- package/server/itc/utility/ITCEventObject.js +10 -0
- package/server/jobs/JobObject.js +24 -0
- package/server/jobs/jobProcess.js +69 -0
- package/server/jobs/jobRunner.js +162 -0
- package/server/jobs/jobs.js +304 -0
- package/server/loadRootComponents.js +44 -0
- package/server/mqtt.ts +485 -0
- package/server/nodeName.ts +75 -0
- package/server/operationsServer.ts +313 -0
- package/server/serverHelpers/Headers.ts +108 -0
- package/server/serverHelpers/JSONStream.ts +269 -0
- package/server/serverHelpers/OperationFunctionObject.ts +13 -0
- package/server/serverHelpers/Request.ts +158 -0
- package/server/serverHelpers/contentTypes.ts +637 -0
- package/server/serverHelpers/requestTimePlugin.js +57 -0
- package/server/serverHelpers/serverHandlers.js +148 -0
- package/server/serverHelpers/serverUtilities.ts +473 -0
- package/server/serverRegistry.ts +8 -0
- package/server/static.ts +187 -0
- package/server/status/definitions.ts +37 -0
- package/server/status/index.ts +125 -0
- package/server/storageReclamation.ts +93 -0
- package/server/threads/itc.js +89 -0
- package/server/threads/manageThreads.js +594 -0
- package/server/threads/socketRouter.ts +360 -0
- package/server/threads/threadServer.js +279 -0
- package/server/throttle.ts +73 -0
- package/sqlTranslator/SelectValidator.js +330 -0
- package/sqlTranslator/alasqlFunctionImporter.js +62 -0
- package/sqlTranslator/deleteTranslator.js +67 -0
- package/sqlTranslator/index.js +242 -0
- package/sqlTranslator/sql_statement_bucket.js +472 -0
- package/static/defaultConfig.yaml +3 -0
- package/studio/web/HDBDogOnly.svg +78 -0
- package/studio/web/assets/PPRadioGrotesk-Bold-DDaUYG8E.woff +0 -0
- package/studio/web/assets/fa-brands-400-CEJbCg16.woff +0 -0
- package/studio/web/assets/fa-brands-400-CSYNqBb_.ttf +0 -0
- package/studio/web/assets/fa-brands-400-DnkPfk3o.eot +0 -0
- package/studio/web/assets/fa-brands-400-UxlILjvJ.woff2 +0 -0
- package/studio/web/assets/fa-brands-400-cH1MgKbP.svg +3717 -0
- package/studio/web/assets/fa-regular-400-BhTwtT8w.eot +0 -0
- package/studio/web/assets/fa-regular-400-D1vz6WBx.ttf +0 -0
- package/studio/web/assets/fa-regular-400-DFnMcJPd.woff +0 -0
- package/studio/web/assets/fa-regular-400-DGzu1beS.woff2 +0 -0
- package/studio/web/assets/fa-regular-400-gwj8Pxq-.svg +801 -0
- package/studio/web/assets/fa-solid-900-B4ZZ7kfP.svg +5034 -0
- package/studio/web/assets/fa-solid-900-B6Axprfb.eot +0 -0
- package/studio/web/assets/fa-solid-900-BUswJgRo.woff2 +0 -0
- package/studio/web/assets/fa-solid-900-DOXgCApm.woff +0 -0
- package/studio/web/assets/fa-solid-900-mxuxnBEa.ttf +0 -0
- package/studio/web/assets/index-BTgXJX9d.js +235 -0
- package/studio/web/assets/index-BTgXJX9d.js.map +1 -0
- package/studio/web/assets/index-C-GXfcup.js +37 -0
- package/studio/web/assets/index-C-GXfcup.js.map +1 -0
- package/studio/web/assets/index-PFlNdimM.js +2 -0
- package/studio/web/assets/index-PFlNdimM.js.map +1 -0
- package/studio/web/assets/index-Y2g_iFpU.css +1 -0
- package/studio/web/assets/index-jiPwkrsB.css +1 -0
- package/studio/web/assets/index.lazy-C3TJZJ4o.js +266 -0
- package/studio/web/assets/index.lazy-C3TJZJ4o.js.map +1 -0
- package/studio/web/assets/profiler-DotzgiCJ.js +2 -0
- package/studio/web/assets/profiler-DotzgiCJ.js.map +1 -0
- package/studio/web/assets/react-redux-VxUEx_mU.js +6 -0
- package/studio/web/assets/react-redux-VxUEx_mU.js.map +1 -0
- package/studio/web/assets/startRecording-B_9J9Csd.js +3 -0
- package/studio/web/assets/startRecording-B_9J9Csd.js.map +1 -0
- package/studio/web/fabric-signup-background.webp +0 -0
- package/studio/web/fabric-signup-text.png +0 -0
- package/studio/web/favicon_purple.png +0 -0
- package/studio/web/github-icon.svg +15 -0
- package/studio/web/harper-fabric_black.png +0 -0
- package/studio/web/harper-fabric_white.png +0 -0
- package/studio/web/harper-studio_white.png +0 -0
- package/studio/web/index.html +16 -0
- package/studio/web/running.css +148 -0
- package/studio/web/running.html +147 -0
- package/studio/web/running.js +111 -0
- package/upgrade/UpgradeObjects.js +13 -0
- package/upgrade/directives/directivesController.js +90 -0
- package/upgrade/directivesManager.js +139 -0
- package/upgrade/upgradePrompt.js +124 -0
- package/upgrade/upgradeUtilities.js +28 -0
- package/utility/AWS/AWSConnector.js +29 -0
- package/utility/OperationFunctionCaller.js +63 -0
- package/utility/assignCmdEnvVariables.js +62 -0
- package/utility/common_utils.js +867 -0
- package/utility/environment/environmentManager.js +208 -0
- package/utility/environment/systemInformation.js +355 -0
- package/utility/errors/commonErrors.js +267 -0
- package/utility/errors/hdbError.js +146 -0
- package/utility/functions/date/dateFunctions.js +65 -0
- package/utility/functions/geo.js +355 -0
- package/utility/functions/sql/alaSQLExtension.js +104 -0
- package/utility/globalSchema.js +35 -0
- package/utility/hdbTerms.ts +819 -0
- package/utility/install/checkJWTTokensExist.js +62 -0
- package/utility/install/harperdb.conf +15 -0
- package/utility/install/harperdb.service +14 -0
- package/utility/install/installer.js +635 -0
- package/utility/installation.ts +30 -0
- package/utility/lmdb/DBIDefinition.js +20 -0
- package/utility/lmdb/DeleteRecordsResponseObject.js +25 -0
- package/utility/lmdb/InsertRecordsResponseObject.js +22 -0
- package/utility/lmdb/OpenDBIObject.js +31 -0
- package/utility/lmdb/OpenEnvironmentObject.js +41 -0
- package/utility/lmdb/UpdateRecordsResponseObject.js +25 -0
- package/utility/lmdb/UpsertRecordsResponseObject.js +22 -0
- package/utility/lmdb/cleanLMDBMap.js +65 -0
- package/utility/lmdb/commonUtility.js +119 -0
- package/utility/lmdb/deleteUtility.js +128 -0
- package/utility/lmdb/environmentUtility.js +477 -0
- package/utility/lmdb/searchCursorFunctions.js +187 -0
- package/utility/lmdb/searchUtility.js +918 -0
- package/utility/lmdb/terms.js +57 -0
- package/utility/lmdb/writeUtility.js +407 -0
- package/utility/logging/harper_logger.js +876 -0
- package/utility/logging/logRotator.js +157 -0
- package/utility/logging/logger.ts +24 -0
- package/utility/logging/readLog.js +355 -0
- package/utility/logging/transactionLog.js +57 -0
- package/utility/mount_hdb.js +59 -0
- package/utility/npmUtilities.js +102 -0
- package/utility/operationPermissions.ts +112 -0
- package/utility/operation_authorization.js +836 -0
- package/utility/packageUtils.js +55 -0
- package/utility/password.ts +99 -0
- package/utility/processManagement/processManagement.js +187 -0
- package/utility/processManagement/servicesConfig.js +56 -0
- package/utility/scripts/restartHdb.js +24 -0
- package/utility/scripts/user_data.sh +13 -0
- package/utility/signalling.js +36 -0
- package/utility/terms/certificates.js +81 -0
- package/utility/when.ts +20 -0
- package/v1.d.ts +39 -0
- package/v1.js +41 -0
- package/v2.d.ts +39 -0
- package/v2.js +41 -0
- package/validation/bulkDeleteValidator.js +24 -0
- package/validation/check_permissions.js +19 -0
- package/validation/common_validators.js +95 -0
- package/validation/configValidator.js +331 -0
- package/validation/deleteValidator.js +15 -0
- package/validation/fileLoadValidator.js +153 -0
- package/validation/insertValidator.js +40 -0
- package/validation/installValidator.js +37 -0
- package/validation/readLogValidator.js +64 -0
- package/validation/role_validation.js +320 -0
- package/validation/schemaMetadataValidator.js +42 -0
- package/validation/searchValidator.js +166 -0
- package/validation/statusValidator.ts +66 -0
- package/validation/transactionLogValidator.js +33 -0
- package/validation/user_validation.js +55 -0
- package/validation/validationWrapper.js +105 -0
- package/dist/resources/analytics/profile.d.ts +0 -2
- package/dist/resources/analytics/profile.js +0 -144
- package/dist/resources/analytics/profile.js.map +0 -1
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { Worker, MessageChannel, parentPort, isMainThread, threadId, workerData } = require('worker_threads');
|
|
4
|
+
const { join, isAbsolute, extname } = require('path');
|
|
5
|
+
const { server } = require('../Server.ts');
|
|
6
|
+
const { totalmem } = require('os');
|
|
7
|
+
const { setHeapSnapshotNearHeapLimit } = require('v8');
|
|
8
|
+
const hdbTerms = require('../../utility/hdbTerms.ts');
|
|
9
|
+
const envMgr = require('../../utility/environment/environmentManager.js');
|
|
10
|
+
const harperLogger = require('../../utility/logging/harper_logger.js');
|
|
11
|
+
const { randomBytes } = require('crypto');
|
|
12
|
+
const { _assignPackageExport } = require('../../globals.js');
|
|
13
|
+
const { PACKAGE_ROOT } = require('../../utility/packageUtils.js');
|
|
14
|
+
const chokidar = require('chokidar');
|
|
15
|
+
const MB = 1024 * 1024;
|
|
16
|
+
const workers = []; // these are our child workers that we are managing
|
|
17
|
+
const connectedPorts = []; // these are all known connected worker ports (siblings, children, parents)
|
|
18
|
+
const MAX_UNEXPECTED_RESTARTS = 50;
|
|
19
|
+
let threadTerminationTimeout = 10000; // threads, you got 10 seconds to die
|
|
20
|
+
const RESTART_TYPE = 'restart';
|
|
21
|
+
const REQUEST_THREAD_INFO = 'request_thread_info';
|
|
22
|
+
const RESOURCE_REPORT = 'resource_report';
|
|
23
|
+
const THREAD_INFO = 'thread_info';
|
|
24
|
+
const ADDED_PORT = 'added-port';
|
|
25
|
+
const ACKNOWLEDGEMENT = 'ack';
|
|
26
|
+
let getThreadInfo;
|
|
27
|
+
_assignPackageExport('threads', connectedPorts);
|
|
28
|
+
|
|
29
|
+
const listenersByType = new Map();
|
|
30
|
+
const messagesQueuedByType = new Map();
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
startWorker,
|
|
34
|
+
restartWorkers,
|
|
35
|
+
shutdownWorkers,
|
|
36
|
+
shutdownWorkersNow,
|
|
37
|
+
workers,
|
|
38
|
+
setMonitorListener,
|
|
39
|
+
onMessageFromWorkers,
|
|
40
|
+
onMessageByType,
|
|
41
|
+
broadcast,
|
|
42
|
+
broadcastWithAcknowledgement,
|
|
43
|
+
getWorkerIndex,
|
|
44
|
+
getWorkerCount,
|
|
45
|
+
getTicketKeys,
|
|
46
|
+
setMainIsWorker,
|
|
47
|
+
setTerminateTimeout,
|
|
48
|
+
restartNumber: workerData?.restartNumber || 1,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
connectedPorts.onMessageByType = onMessageByType;
|
|
52
|
+
connectedPorts.sendToThread = function (threadId, message) {
|
|
53
|
+
if (!message?.type) throw new Error('A message with a type must be provided');
|
|
54
|
+
const port = connectedPorts.find((port) => port.threadId === threadId);
|
|
55
|
+
if (port) {
|
|
56
|
+
port.postMessage(message);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
module.exports.whenThreadsStarted = new Promise((resolve) => {
|
|
61
|
+
module.exports.threadsHaveStarted = resolve;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// make sure this is set on all threads, including the main thread (this is no-op
|
|
65
|
+
// if it was already with the execArgv below)
|
|
66
|
+
if (envMgr.get(hdbTerms.CONFIG_PARAMS.THREADS_HEAPSNAPSHOTNEARLIMIT)) setHeapSnapshotNearHeapLimit(1);
|
|
67
|
+
|
|
68
|
+
let isMainWorker;
|
|
69
|
+
function setTerminateTimeout(newTimeout) {
|
|
70
|
+
threadTerminationTimeout = newTimeout;
|
|
71
|
+
}
|
|
72
|
+
function getWorkerIndex() {
|
|
73
|
+
return workerData ? workerData.workerIndex : isMainWorker ? 0 : undefined;
|
|
74
|
+
}
|
|
75
|
+
function getWorkerCount() {
|
|
76
|
+
return workerData ? workerData.workerCount : isMainWorker ? 1 : undefined;
|
|
77
|
+
}
|
|
78
|
+
function setMainIsWorker(isWorker) {
|
|
79
|
+
isMainWorker = isWorker;
|
|
80
|
+
module.exports.threadsHaveStarted();
|
|
81
|
+
}
|
|
82
|
+
let workerCount = 1; // should be assigned when workers are created
|
|
83
|
+
let ticketKeys;
|
|
84
|
+
function getTicketKeys() {
|
|
85
|
+
if (ticketKeys) return ticketKeys;
|
|
86
|
+
ticketKeys = isMainThread ? randomBytes(48) : workerData.ticketKeys;
|
|
87
|
+
return ticketKeys;
|
|
88
|
+
}
|
|
89
|
+
Object.defineProperty(server, 'workerIndex', {
|
|
90
|
+
get() {
|
|
91
|
+
return getWorkerIndex();
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
Object.defineProperty(server, 'workerCount', {
|
|
95
|
+
get() {
|
|
96
|
+
return getWorkerCount();
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
if (!parentPort) {
|
|
100
|
+
onMessageByType(REQUEST_THREAD_INFO, (message, worker) => {
|
|
101
|
+
if (worker) sendThreadInfo(worker);
|
|
102
|
+
});
|
|
103
|
+
onMessageByType(RESOURCE_REPORT, (message, worker) => {
|
|
104
|
+
if (worker) recordResourceReport(worker, message);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// postMessage type listeners that are registered in other ways or can be registered later
|
|
108
|
+
listenersByType.set(hdbTerms.ITC_EVENT_TYPES.CHILD_STARTED, null);
|
|
109
|
+
listenersByType.set(hdbTerms.ITC_EVENT_TYPES.SCHEMA, null);
|
|
110
|
+
listenersByType.set(hdbTerms.ITC_EVENT_TYPES.USER, null);
|
|
111
|
+
listenersByType.set(hdbTerms.ITC_EVENT_TYPES.COMPONENT_STATUS_REQUEST, null);
|
|
112
|
+
|
|
113
|
+
function startWorker(path, options = {}) {
|
|
114
|
+
// Take a percentage of total memory to determine the max memory for each thread. The percentage is based
|
|
115
|
+
// on the thread count. Generally, it is unrealistic to efficiently use the majority of total memory for a single
|
|
116
|
+
// NodeJS worker since it would lead to massive swap space usage with other processes and there is significant
|
|
117
|
+
// amount of total memory that is and must be used for disk (heavily used by LMDB).
|
|
118
|
+
// Examples of how much we specify as the maximum memory (for old space):
|
|
119
|
+
// 1 thread: 80% of total memory
|
|
120
|
+
// 4 threads: 50% of total memory per thread
|
|
121
|
+
// 16 threads: 20% of total memory per thread
|
|
122
|
+
// 64 threads: 11% of total memory per thread
|
|
123
|
+
// (and then limit to their license limit, if they have one)
|
|
124
|
+
let availableMemory = process.constrainedMemory?.() || totalmem(); // used constrained memory if it is available
|
|
125
|
+
// and lower than total memory
|
|
126
|
+
availableMemory = Math.min(availableMemory, totalmem(), 20000 * MB);
|
|
127
|
+
const maxOldMemory =
|
|
128
|
+
envMgr.get(hdbTerms.CONFIG_PARAMS.THREADS_MAXHEAPMEMORY) ??
|
|
129
|
+
Math.max(Math.floor(availableMemory / MB / (10 + (options.threadCount || 1) / 4)), 512);
|
|
130
|
+
// Max young memory space (semi-space for scavenger) is 1/128 of max memory (limited to 16-64). For most of our m5
|
|
131
|
+
// machines this will be 64MB (less for t3's). This is based on recommendations from:
|
|
132
|
+
// https://www.alibabacloud.com/blog/node-js-application-troubleshooting-manual---comprehensive-gc-problems-and-optimization594965
|
|
133
|
+
// https://github.com/nodejs/node/issues/42511
|
|
134
|
+
// https://plaid.com/blog/how-we-parallelized-our-node-service-by-30x/
|
|
135
|
+
const maxYoungMemory = Math.min(Math.max(maxOldMemory >> 6, 16), 64);
|
|
136
|
+
|
|
137
|
+
const channelsToConnect = [];
|
|
138
|
+
const portsToSend = [];
|
|
139
|
+
for (let existingPort of connectedPorts) {
|
|
140
|
+
const channel = new MessageChannel();
|
|
141
|
+
channel.existingPort = existingPort;
|
|
142
|
+
channelsToConnect.push(channel);
|
|
143
|
+
portsToSend.push(channel.port2);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!extname(path)) path += '.js';
|
|
147
|
+
|
|
148
|
+
const execArgv = [
|
|
149
|
+
'--enable-source-maps',
|
|
150
|
+
'--experimental-vm-modules', // used for giving applications their own top level scope
|
|
151
|
+
'--disable-warning=ExperimentalWarning', // yeah, yeah, we know it is experimental
|
|
152
|
+
'--expose-internals', // expose Node.js internal utils so jsLoader can use `decorateErrorStack()`
|
|
153
|
+
];
|
|
154
|
+
if (envMgr.get(hdbTerms.CONFIG_PARAMS.THREADS_HEAPSNAPSHOTNEARLIMIT))
|
|
155
|
+
execArgv.push('--heapsnapshot-near-heap-limit=1');
|
|
156
|
+
|
|
157
|
+
const worker = new Worker(isAbsolute(path) ? path : join(PACKAGE_ROOT, path), {
|
|
158
|
+
resourceLimits: {
|
|
159
|
+
maxOldGenerationSizeMb: maxOldMemory,
|
|
160
|
+
maxYoungGenerationSizeMb: maxYoungMemory,
|
|
161
|
+
},
|
|
162
|
+
execArgv,
|
|
163
|
+
argv: process.argv.slice(2),
|
|
164
|
+
// pass these in synchronously to the worker so it has them on startup:
|
|
165
|
+
workerData: {
|
|
166
|
+
addPorts: portsToSend,
|
|
167
|
+
addThreadIds: channelsToConnect.map((channel) => channel.existingPort.threadId),
|
|
168
|
+
workerIndex: options.workerIndex,
|
|
169
|
+
workerCount: (workerCount = options.threadCount),
|
|
170
|
+
name: options.name,
|
|
171
|
+
restartNumber: module.exports.restartNumber,
|
|
172
|
+
ticketKeys: getTicketKeys(),
|
|
173
|
+
},
|
|
174
|
+
transferList: portsToSend,
|
|
175
|
+
...options,
|
|
176
|
+
});
|
|
177
|
+
// now that we have the new thread ids, we can finishing connecting the channel and notify the existing
|
|
178
|
+
// worker of the new port with thread id.
|
|
179
|
+
for (let { port1, existingPort } of channelsToConnect) {
|
|
180
|
+
existingPort.postMessage(
|
|
181
|
+
{
|
|
182
|
+
type: ADDED_PORT,
|
|
183
|
+
port: port1,
|
|
184
|
+
threadId: worker.threadId,
|
|
185
|
+
},
|
|
186
|
+
[port1]
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
addPort(worker, true);
|
|
190
|
+
worker.unexpectedRestarts = options.unexpectedRestarts || 0;
|
|
191
|
+
worker.startCopy = () => {
|
|
192
|
+
// in a shutdown sequence we use overlapping restarts, starting the new thread while waiting for the old thread
|
|
193
|
+
// to die, to ensure there is no loss of service and maximum availability.
|
|
194
|
+
return startWorker(path, options);
|
|
195
|
+
};
|
|
196
|
+
worker.on('error', (error) => {
|
|
197
|
+
// log errors, and it also important that we catch errors so we can recover if a thread dies (in a recoverable
|
|
198
|
+
// way)
|
|
199
|
+
harperLogger.error(`Worker index ${options.workerIndex} error:`, error);
|
|
200
|
+
});
|
|
201
|
+
worker.on('exit', (_code) => {
|
|
202
|
+
workers.splice(workers.indexOf(worker), 1);
|
|
203
|
+
if (!worker.wasShutdown && options.autoRestart !== false) {
|
|
204
|
+
// if this wasn't an intentional shutdown, restart now (unless we have tried too many times)
|
|
205
|
+
if (worker.unexpectedRestarts < MAX_UNEXPECTED_RESTARTS) {
|
|
206
|
+
options.unexpectedRestarts = worker.unexpectedRestarts + 1;
|
|
207
|
+
startWorker(path, options);
|
|
208
|
+
} else harperLogger.error(`Thread has been restarted ${worker.restarts} times and will not be restarted`);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
workers.push(worker);
|
|
212
|
+
startMonitoring();
|
|
213
|
+
if (options.onStarted) options.onStarted(worker); // notify that it is ready
|
|
214
|
+
worker.name = options.name;
|
|
215
|
+
return worker;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const OVERLAPPING_RESTART_TYPES = [hdbTerms.THREAD_TYPES.HTTP];
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Restart all the worker threads
|
|
222
|
+
* @param name If there is a specific set of threads that need to be restarted, they can be specified with this
|
|
223
|
+
* parameter
|
|
224
|
+
* @param maxWorkersDown The maximum number of worker threads to restart at once. In restarts, we start new
|
|
225
|
+
* threads at the same time we shutdown new ones. However, we usually want to limit how many we do at once to avoid
|
|
226
|
+
* excessive load and to keep things responsive. This parameter throttles the restarts to minimize load from
|
|
227
|
+
* thread startups.
|
|
228
|
+
* @returns {Promise<void>}
|
|
229
|
+
*/
|
|
230
|
+
|
|
231
|
+
async function restartWorkers(
|
|
232
|
+
name = null,
|
|
233
|
+
maxWorkersDown = Math.max(Math.floor(workerCount / 8), 1), // restart 1/8 of the threads at a time, but at least 1
|
|
234
|
+
startReplacementThreads = true
|
|
235
|
+
) {
|
|
236
|
+
if (isMainThread) {
|
|
237
|
+
try {
|
|
238
|
+
// we do this because it is possible for a component to chdir to itself, get re-deployed and then the cwd
|
|
239
|
+
// inode link is invalid and it can cause a lot of problems. But process.cwd() still returns the path, for
|
|
240
|
+
// some reason, so we need to reset it to the correct path.
|
|
241
|
+
process.chdir(process.cwd());
|
|
242
|
+
} catch (e) {
|
|
243
|
+
harperLogger.error('Unable to reestablish current working directory', e);
|
|
244
|
+
}
|
|
245
|
+
// problematic cyclic dependency, bind late
|
|
246
|
+
const { resetRestartNeeded } = require('../../components/requestRestart.ts');
|
|
247
|
+
resetRestartNeeded();
|
|
248
|
+
// This is here to prevent circular dependencies
|
|
249
|
+
if (startReplacementThreads) {
|
|
250
|
+
const { loadRootComponents } = require('../loadRootComponents.js');
|
|
251
|
+
await loadRootComponents();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
module.exports.restartNumber++;
|
|
255
|
+
if (maxWorkersDown < 1) {
|
|
256
|
+
// we accept a ratio of workers, and compute absolute maximum being down at a time from the total number of
|
|
257
|
+
// threads
|
|
258
|
+
maxWorkersDown = maxWorkersDown * workers.length;
|
|
259
|
+
}
|
|
260
|
+
let waitingToFinish = []; // array of workers that we are waiting to restart
|
|
261
|
+
// make a copy of the workers before iterating them, as the workers
|
|
262
|
+
// array will be mutating a lot during this
|
|
263
|
+
let waitingToStart = [];
|
|
264
|
+
for (let worker of workers.slice(0)) {
|
|
265
|
+
if ((name && worker.name !== name) || worker.wasShutdown) continue; // filter by type, if specified
|
|
266
|
+
harperLogger.trace('sending shutdown request to ', worker.threadId);
|
|
267
|
+
worker.postMessage({
|
|
268
|
+
restartNumber: module.exports.restartNumber,
|
|
269
|
+
type: hdbTerms.ITC_EVENT_TYPES.SHUTDOWN,
|
|
270
|
+
});
|
|
271
|
+
worker.wasShutdown = true;
|
|
272
|
+
worker.emit('shutdown', {});
|
|
273
|
+
const overlapping = OVERLAPPING_RESTART_TYPES.indexOf(worker.name) > -1;
|
|
274
|
+
let whenDone = new Promise((resolve) => {
|
|
275
|
+
// in case the exit inside the thread doesn't timeout, call terminate if necessary
|
|
276
|
+
let timeout = setTimeout(() => {
|
|
277
|
+
harperLogger.warn('Thread did not voluntarily terminate, terminating from the outside', worker.threadId);
|
|
278
|
+
worker.terminate();
|
|
279
|
+
}, threadTerminationTimeout * 2).unref();
|
|
280
|
+
worker.on('exit', () => {
|
|
281
|
+
clearTimeout(timeout);
|
|
282
|
+
waitingToFinish.splice(waitingToFinish.indexOf(whenDone));
|
|
283
|
+
if (!overlapping && startReplacementThreads) worker.startCopy();
|
|
284
|
+
resolve();
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
waitingToFinish.push(whenDone);
|
|
288
|
+
if (overlapping && startReplacementThreads) {
|
|
289
|
+
let newWorker = worker.startCopy();
|
|
290
|
+
let whenStarted = new Promise((resolve) => {
|
|
291
|
+
const startListener = (message) => {
|
|
292
|
+
if (message.type === hdbTerms.ITC_EVENT_TYPES.CHILD_STARTED) {
|
|
293
|
+
harperLogger.trace('Worker has started', newWorker.threadId);
|
|
294
|
+
resolve();
|
|
295
|
+
waitingToStart.splice(waitingToStart.indexOf(whenStarted));
|
|
296
|
+
newWorker.off('message', startListener);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
harperLogger.trace('Waiting for worker to start', newWorker.threadId);
|
|
300
|
+
newWorker.on('message', startListener);
|
|
301
|
+
});
|
|
302
|
+
waitingToStart.push(whenStarted);
|
|
303
|
+
if (waitingToFinish.length >= maxWorkersDown) {
|
|
304
|
+
// wait for one to finish before terminating to restart more
|
|
305
|
+
await Promise.race(waitingToFinish);
|
|
306
|
+
}
|
|
307
|
+
if (waitingToStart.length >= maxWorkersDown) {
|
|
308
|
+
// wait for one to finish before starting to restart more
|
|
309
|
+
await Promise.race(waitingToStart);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// seems appropriate to wait for this to finish, but the API doesn't actually wait for this function
|
|
314
|
+
// to finish, so not that important
|
|
315
|
+
await Promise.all(waitingToFinish);
|
|
316
|
+
await Promise.all(waitingToStart);
|
|
317
|
+
} else {
|
|
318
|
+
parentPort.postMessage({
|
|
319
|
+
type: RESTART_TYPE,
|
|
320
|
+
workerType: name,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function shutdownWorkers(name) {
|
|
325
|
+
return restartWorkers(name, Infinity, false);
|
|
326
|
+
}
|
|
327
|
+
function shutdownWorkersNow(name) {
|
|
328
|
+
shutdownWorkers(name); // set the state of all the workers to shut down. this should finish the important stuff synchronously
|
|
329
|
+
return Promise.all(workers.map((worker) => worker.terminate()));
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const messageListeners = [];
|
|
333
|
+
function onMessageFromWorkers(listener) {
|
|
334
|
+
messageListeners.push(listener);
|
|
335
|
+
}
|
|
336
|
+
function onMessageByType(type, listener) {
|
|
337
|
+
let listeners = listenersByType.get(type);
|
|
338
|
+
if (!listeners) listenersByType.set(type, (listeners = []));
|
|
339
|
+
listeners.push(listener);
|
|
340
|
+
if (messagesQueuedByType.has(type)) {
|
|
341
|
+
for (let message of messagesQueuedByType.get(type)) {
|
|
342
|
+
listener(message);
|
|
343
|
+
}
|
|
344
|
+
messagesQueuedByType.delete(type);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const MAX_SYNC_BROADCAST = 10;
|
|
349
|
+
async function broadcast(message, includeSelf) {
|
|
350
|
+
let count = 0;
|
|
351
|
+
for (let port of connectedPorts) {
|
|
352
|
+
try {
|
|
353
|
+
port.postMessage(message);
|
|
354
|
+
if (count++ > MAX_SYNC_BROADCAST) {
|
|
355
|
+
// posting messages can be somewhat expensive, so we yield the event turn occassionally to not cause any delays.
|
|
356
|
+
count = 0;
|
|
357
|
+
await new Promise(setImmediate);
|
|
358
|
+
}
|
|
359
|
+
} catch (error) {
|
|
360
|
+
harperLogger.error(`Unable to send message to worker`, error);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (includeSelf) {
|
|
364
|
+
notifyMessageListeners(message, null);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const awaitingResponses = new Map();
|
|
369
|
+
let nextId = 1;
|
|
370
|
+
function broadcastWithAcknowledgement(message) {
|
|
371
|
+
return new Promise((resolve) => {
|
|
372
|
+
let waitingCount = 0;
|
|
373
|
+
for (let port of connectedPorts) {
|
|
374
|
+
try {
|
|
375
|
+
let requestId = nextId++;
|
|
376
|
+
const ackHandler = () => {
|
|
377
|
+
awaitingResponses.delete(requestId);
|
|
378
|
+
if (--waitingCount === 0) {
|
|
379
|
+
resolve();
|
|
380
|
+
}
|
|
381
|
+
if (port !== parentPort && --port.refCount === 0) {
|
|
382
|
+
port.unref();
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
ackHandler.port = port;
|
|
386
|
+
port.ref();
|
|
387
|
+
port.refCount = (port.refCount || 0) + 1;
|
|
388
|
+
awaitingResponses.set((message.requestId = requestId), ackHandler);
|
|
389
|
+
if (!port.hasAckCloseListener) {
|
|
390
|
+
// just set a single close listener that can clean up all the ack handlers for a port that is closed
|
|
391
|
+
port.hasAckCloseListener = true;
|
|
392
|
+
port.on(port.close ? 'close' : 'exit', () => {
|
|
393
|
+
for (let [, ackHandler] of awaitingResponses) {
|
|
394
|
+
if (ackHandler.port === port) {
|
|
395
|
+
ackHandler();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
port.postMessage(message);
|
|
401
|
+
waitingCount++;
|
|
402
|
+
} catch (error) {
|
|
403
|
+
harperLogger.error(`Unable to send message to worker`, error);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
if (waitingCount === 0) resolve();
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function sendThreadInfo(targetWorker) {
|
|
411
|
+
targetWorker.postMessage({
|
|
412
|
+
type: THREAD_INFO,
|
|
413
|
+
workers: getChildWorkerInfo(),
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function getChildWorkerInfo() {
|
|
418
|
+
let now = Date.now();
|
|
419
|
+
return workers.map((worker) => ({
|
|
420
|
+
threadId: worker.threadId,
|
|
421
|
+
name: worker.name,
|
|
422
|
+
heapTotal: worker.resources?.heapTotal,
|
|
423
|
+
heapUsed: worker.resources?.heapUsed,
|
|
424
|
+
externalMemory: worker.resources?.external,
|
|
425
|
+
arrayBuffers: worker.resources?.arrayBuffers,
|
|
426
|
+
sinceLastUpdate: now - worker.resources?.updated,
|
|
427
|
+
...worker.recentELU,
|
|
428
|
+
}));
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** Record update from worker on stats that it self-reports
|
|
432
|
+
*
|
|
433
|
+
* @param worker
|
|
434
|
+
* @param message
|
|
435
|
+
*/
|
|
436
|
+
function recordResourceReport(worker, message) {
|
|
437
|
+
worker.resources = message;
|
|
438
|
+
// we want to record when this happens so we know if it has reported recently
|
|
439
|
+
worker.resources.updated = Date.now();
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
let monitorListener;
|
|
443
|
+
function setMonitorListener(listener) {
|
|
444
|
+
monitorListener = listener;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const MONITORING_INTERVAL = 1000;
|
|
448
|
+
let monitoring = false;
|
|
449
|
+
function startMonitoring() {
|
|
450
|
+
if (monitoring) return;
|
|
451
|
+
monitoring = true;
|
|
452
|
+
// we periodically get the event loop utilitization so we have a reasonable time frame to check the recent
|
|
453
|
+
// utilization levels (last second) and so we don't have to make these calls to frequently
|
|
454
|
+
setInterval(() => {
|
|
455
|
+
for (let worker of workers) {
|
|
456
|
+
let current_ELU = worker.performance.eventLoopUtilization();
|
|
457
|
+
let recent_ELU;
|
|
458
|
+
if (worker.lastTotalELU) {
|
|
459
|
+
// get the difference between current and last to determine the last second of utilization
|
|
460
|
+
recent_ELU = worker.performance.eventLoopUtilization(current_ELU, worker.lastTotalELU);
|
|
461
|
+
} else {
|
|
462
|
+
recent_ELU = current_ELU;
|
|
463
|
+
}
|
|
464
|
+
worker.lastTotalELU = current_ELU;
|
|
465
|
+
worker.recentELU = recent_ELU;
|
|
466
|
+
}
|
|
467
|
+
if (monitorListener) monitorListener();
|
|
468
|
+
}, MONITORING_INTERVAL).unref();
|
|
469
|
+
}
|
|
470
|
+
const REPORTING_INTERVAL = 1000;
|
|
471
|
+
|
|
472
|
+
if (parentPort && workerData?.addPorts) {
|
|
473
|
+
addPort(parentPort);
|
|
474
|
+
for (let i = 0, l = workerData.addPorts.length; i < l; i++) {
|
|
475
|
+
let port = workerData.addPorts[i];
|
|
476
|
+
port.threadId = workerData.addThreadIds[i];
|
|
477
|
+
addPort(port);
|
|
478
|
+
}
|
|
479
|
+
setInterval(() => {
|
|
480
|
+
// post our memory usage as a resource report, reporting our memory usage
|
|
481
|
+
let memoryUsage = process.memoryUsage();
|
|
482
|
+
parentPort.postMessage({
|
|
483
|
+
type: RESOURCE_REPORT,
|
|
484
|
+
heapTotal: memoryUsage.heapTotal,
|
|
485
|
+
heapUsed: memoryUsage.heapUsed,
|
|
486
|
+
external: memoryUsage.external,
|
|
487
|
+
arrayBuffers: memoryUsage.arrayBuffers,
|
|
488
|
+
});
|
|
489
|
+
}, REPORTING_INTERVAL).unref();
|
|
490
|
+
getThreadInfo = () =>
|
|
491
|
+
new Promise((resolve) => {
|
|
492
|
+
// request thread info from the parent thread and wait for it to response with info on all the threads
|
|
493
|
+
parentPort.on('message', receiveThreadInfo);
|
|
494
|
+
parentPort.postMessage({ type: REQUEST_THREAD_INFO });
|
|
495
|
+
function receiveThreadInfo(message) {
|
|
496
|
+
if (message.type === THREAD_INFO) {
|
|
497
|
+
parentPort.off('message', receiveThreadInfo);
|
|
498
|
+
resolve(message.workers);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
} else {
|
|
503
|
+
getThreadInfo = getChildWorkerInfo;
|
|
504
|
+
}
|
|
505
|
+
module.exports.getThreadInfo = getThreadInfo;
|
|
506
|
+
|
|
507
|
+
function addPort(port, keepRef) {
|
|
508
|
+
connectedPorts.push(port);
|
|
509
|
+
port
|
|
510
|
+
.on('message', (message) => {
|
|
511
|
+
if (message.type === ADDED_PORT) {
|
|
512
|
+
message.port.threadId = message.threadId;
|
|
513
|
+
addPort(message.port);
|
|
514
|
+
} else if (message.type === ACKNOWLEDGEMENT) {
|
|
515
|
+
let completion = awaitingResponses.get(message.id);
|
|
516
|
+
if (completion) {
|
|
517
|
+
completion();
|
|
518
|
+
}
|
|
519
|
+
} else {
|
|
520
|
+
notifyMessageListeners(message, port);
|
|
521
|
+
}
|
|
522
|
+
})
|
|
523
|
+
.on('close', () => {
|
|
524
|
+
connectedPorts.splice(connectedPorts.indexOf(port), 1);
|
|
525
|
+
})
|
|
526
|
+
.on('exit', () => {
|
|
527
|
+
connectedPorts.splice(connectedPorts.indexOf(port), 1);
|
|
528
|
+
});
|
|
529
|
+
if (keepRef) port.refCount = 100;
|
|
530
|
+
else port.unref();
|
|
531
|
+
}
|
|
532
|
+
function notifyMessageListeners(message, port) {
|
|
533
|
+
for (let listener of messageListeners) {
|
|
534
|
+
listener(message, port);
|
|
535
|
+
}
|
|
536
|
+
if (message.type) {
|
|
537
|
+
let listeners = listenersByType.get(message.type);
|
|
538
|
+
if (listeners) {
|
|
539
|
+
for (let listener of listeners) {
|
|
540
|
+
try {
|
|
541
|
+
listener(message, port);
|
|
542
|
+
} catch (error) {
|
|
543
|
+
harperLogger.error(error);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
} else if (listeners !== null) {
|
|
547
|
+
// null means it is registered for a later listener
|
|
548
|
+
harperLogger.warn?.(`No listener registered for worker message type ${message.type}, queuing message`);
|
|
549
|
+
let messages = messagesQueuedByType.get(message.type);
|
|
550
|
+
if (!messages) {
|
|
551
|
+
messagesQueuedByType.set(message.type, (messages = []));
|
|
552
|
+
}
|
|
553
|
+
messages.push(message);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
if (isMainThread) {
|
|
558
|
+
let beforeRestart, queuedRestart;
|
|
559
|
+
let changedFiles = new Set();
|
|
560
|
+
const ignoredPaths = ['node_modules', '.git'];
|
|
561
|
+
const watchDir = async (dir, beforeRestartCallback) => {
|
|
562
|
+
if (beforeRestartCallback) beforeRestart = beforeRestartCallback;
|
|
563
|
+
chokidar
|
|
564
|
+
.watch(dir, {
|
|
565
|
+
persistent: false,
|
|
566
|
+
ignored: (path) => {
|
|
567
|
+
return ignoredPaths.some((ignoredPath) => path.includes(ignoredPath));
|
|
568
|
+
},
|
|
569
|
+
})
|
|
570
|
+
.on('change', (path) => {
|
|
571
|
+
changedFiles.add(path);
|
|
572
|
+
if (queuedRestart) clearTimeout(queuedRestart);
|
|
573
|
+
queuedRestart = setTimeout(async () => {
|
|
574
|
+
if (beforeRestart) await beforeRestart();
|
|
575
|
+
await restartWorkers();
|
|
576
|
+
console.log('Reloaded Harper components, changed files:', Array.from(changedFiles));
|
|
577
|
+
changedFiles.clear();
|
|
578
|
+
}, 100);
|
|
579
|
+
});
|
|
580
|
+
};
|
|
581
|
+
module.exports.watchDir = watchDir;
|
|
582
|
+
if (process.env.WATCH_DIR) watchDir(process.env.WATCH_DIR);
|
|
583
|
+
} else {
|
|
584
|
+
onMessageByType(hdbTerms.ITC_EVENT_TYPES.SHUTDOWN, async (message) => {
|
|
585
|
+
module.exports.restartNumber = message.restartNumber;
|
|
586
|
+
parentPort.unref(); // remove this handle
|
|
587
|
+
setTimeout(() => {
|
|
588
|
+
harperLogger.warn('Thread did not voluntarily terminate', threadId);
|
|
589
|
+
// Note that if this occurs, you may want to use this to debug what is currently running:
|
|
590
|
+
// require('why-is-node-running')();
|
|
591
|
+
process.exit(0);
|
|
592
|
+
}, threadTerminationTimeout).unref(); // don't block the shutdown
|
|
593
|
+
});
|
|
594
|
+
}
|