@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.
Files changed (444) hide show
  1. package/bin/BinObjects.js +17 -0
  2. package/bin/cliOperations.js +157 -0
  3. package/bin/copyDb.ts +280 -0
  4. package/bin/harper.js +156 -0
  5. package/bin/install.js +15 -0
  6. package/bin/lite.js +5 -0
  7. package/bin/restart.js +201 -0
  8. package/bin/run.js +409 -0
  9. package/bin/status.js +65 -0
  10. package/bin/stop.js +22 -0
  11. package/bin/upgrade.js +134 -0
  12. package/components/Application.ts +646 -0
  13. package/components/ApplicationScope.ts +49 -0
  14. package/components/Component.ts +53 -0
  15. package/components/ComponentV1.ts +342 -0
  16. package/components/DEFAULT_CONFIG.ts +18 -0
  17. package/components/EntryHandler.ts +227 -0
  18. package/components/Logger.ts +14 -0
  19. package/components/OptionsWatcher.ts +354 -0
  20. package/components/PluginModule.ts +6 -0
  21. package/components/Scope.ts +329 -0
  22. package/components/componentLoader.ts +529 -0
  23. package/components/deriveCommonPatternBase.ts +31 -0
  24. package/components/deriveGlobOptions.ts +44 -0
  25. package/components/deriveURLPath.ts +57 -0
  26. package/components/operations.js +658 -0
  27. package/components/operationsValidation.js +246 -0
  28. package/components/packageComponent.ts +39 -0
  29. package/components/requestRestart.ts +26 -0
  30. package/components/resolveBaseURLPath.ts +38 -0
  31. package/components/status/ComponentStatus.ts +110 -0
  32. package/components/status/ComponentStatusRegistry.ts +251 -0
  33. package/components/status/api.ts +153 -0
  34. package/components/status/crossThread.ts +405 -0
  35. package/components/status/errors.ts +152 -0
  36. package/components/status/index.ts +44 -0
  37. package/components/status/internal.ts +65 -0
  38. package/components/status/registry.ts +12 -0
  39. package/components/status/types.ts +96 -0
  40. package/config/RootConfigWatcher.ts +59 -0
  41. package/config/configHelpers.ts +11 -0
  42. package/config/configUtils.js +967 -0
  43. package/config/harperConfigEnvVars.ts +641 -0
  44. package/dataLayer/CreateAttributeObject.js +25 -0
  45. package/dataLayer/CreateTableObject.js +11 -0
  46. package/dataLayer/DataLayerObjects.js +43 -0
  47. package/dataLayer/DeleteBeforeObject.js +22 -0
  48. package/dataLayer/DeleteObject.js +25 -0
  49. package/dataLayer/DropAttributeObject.js +11 -0
  50. package/dataLayer/GetBackupObject.js +22 -0
  51. package/dataLayer/InsertObject.js +24 -0
  52. package/dataLayer/ReadAuditLogObject.js +24 -0
  53. package/dataLayer/SQLSearch.js +1335 -0
  54. package/dataLayer/SearchByConditionsObject.js +61 -0
  55. package/dataLayer/SearchByHashObject.js +21 -0
  56. package/dataLayer/SearchObject.js +45 -0
  57. package/dataLayer/SqlSearchObject.js +14 -0
  58. package/dataLayer/UpdateObject.js +23 -0
  59. package/dataLayer/UpsertObject.js +23 -0
  60. package/dataLayer/bulkLoad.js +813 -0
  61. package/dataLayer/dataObjects/BulkLoadObjects.js +27 -0
  62. package/dataLayer/dataObjects/UpsertObject.js +23 -0
  63. package/dataLayer/delete.js +164 -0
  64. package/dataLayer/export.js +381 -0
  65. package/dataLayer/getBackup.js +40 -0
  66. package/dataLayer/harperBridge/BridgeMethods.js +81 -0
  67. package/dataLayer/harperBridge/ResourceBridge.ts +633 -0
  68. package/dataLayer/harperBridge/bridgeUtility/insertUpdateReturnObj.js +28 -0
  69. package/dataLayer/harperBridge/bridgeUtility/insertUpdateValidate.js +88 -0
  70. package/dataLayer/harperBridge/harperBridge.js +21 -0
  71. package/dataLayer/harperBridge/lmdbBridge/LMDBBridge.js +119 -0
  72. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +19 -0
  73. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateAttribute.js +112 -0
  74. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateRecords.js +67 -0
  75. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateSchema.js +31 -0
  76. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateTable.js +94 -0
  77. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteAuditLogsBefore.js +98 -0
  78. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteRecords.js +89 -0
  79. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropAttribute.js +109 -0
  80. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropSchema.js +107 -0
  81. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropTable.js +137 -0
  82. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbFlush.js +35 -0
  83. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetBackup.js +111 -0
  84. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByHash.js +28 -0
  85. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByValue.js +29 -0
  86. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbReadAuditLog.js +207 -0
  87. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByConditions.js +156 -0
  88. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByHash.js +21 -0
  89. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByValue.js +30 -0
  90. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbTransaction.js +19 -0
  91. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpdateRecords.js +64 -0
  92. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpsertRecords.js +70 -0
  93. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBCreateAttributeObject.js +22 -0
  94. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBDeleteTransactionObject.js +23 -0
  95. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBInsertTransactionObject.js +22 -0
  96. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBTransactionObject.js +23 -0
  97. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpdateTransactionObject.js +24 -0
  98. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpsertTransactionObject.js +24 -0
  99. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/TableSizeObject.js +25 -0
  100. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializeHashSearch.js +21 -0
  101. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js +157 -0
  102. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCheckForNewAttributes.js +94 -0
  103. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCreateTransactionsAuditEnvironment.js +39 -0
  104. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.js +34 -0
  105. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbProcessRows.js +100 -0
  106. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbSearch.js +371 -0
  107. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbWriteTransaction.js +109 -0
  108. package/dataLayer/hdbInfoController.js +254 -0
  109. package/dataLayer/insert.js +266 -0
  110. package/dataLayer/readAuditLog.js +59 -0
  111. package/dataLayer/schema.js +366 -0
  112. package/dataLayer/schemaDescribe.js +289 -0
  113. package/dataLayer/search.js +60 -0
  114. package/dataLayer/transaction.js +17 -0
  115. package/dataLayer/update.js +124 -0
  116. package/dist/components/Logger.d.ts +12 -0
  117. package/dist/components/Logger.js +3 -0
  118. package/dist/components/Logger.js.map +1 -0
  119. package/dist/components/Scope.d.ts +14 -4
  120. package/dist/components/Scope.js +18 -10
  121. package/dist/components/Scope.js.map +1 -1
  122. package/dist/components/componentLoader.js +16 -9
  123. package/dist/components/componentLoader.js.map +1 -1
  124. package/dist/components/operations.js +2 -2
  125. package/dist/components/operations.js.map +1 -1
  126. package/dist/config/configUtils.d.ts +1 -1
  127. package/dist/config/configUtils.js +1 -1
  128. package/dist/config/configUtils.js.map +1 -1
  129. package/dist/dataLayer/CreateTableObject.d.ts +2 -2
  130. package/dist/dataLayer/CreateTableObject.js +2 -2
  131. package/dist/dataLayer/CreateTableObject.js.map +1 -1
  132. package/dist/dataLayer/delete.d.ts +1 -1
  133. package/dist/dataLayer/schema.js +6 -5
  134. package/dist/dataLayer/schema.js.map +1 -1
  135. package/dist/dataLayer/schemaDescribe.js +1 -1
  136. package/dist/dataLayer/schemaDescribe.js.map +1 -1
  137. package/dist/index.d.ts +1 -1
  138. package/dist/index.js +2 -0
  139. package/dist/index.js.map +1 -1
  140. package/dist/resources/DatabaseTransaction.d.ts +1 -1
  141. package/dist/resources/IterableEventQueue.d.ts +1 -1
  142. package/dist/resources/LMDBTransaction.d.ts +5 -1
  143. package/dist/resources/Resource.d.ts +1 -1
  144. package/dist/resources/RocksIndexStore.d.ts +3 -3
  145. package/dist/resources/RocksTransactionLogStore.d.ts +6 -3
  146. package/dist/resources/Table.d.ts +15 -6
  147. package/dist/resources/Table.js +4 -1
  148. package/dist/resources/Table.js.map +1 -1
  149. package/dist/resources/analytics/read.js +32 -22
  150. package/dist/resources/analytics/read.js.map +1 -1
  151. package/dist/resources/analytics/write.js +3 -6
  152. package/dist/resources/analytics/write.js.map +1 -1
  153. package/dist/resources/auditStore.d.ts +3 -3
  154. package/dist/resources/blob.d.ts +25 -2
  155. package/dist/resources/databases.d.ts +12 -2
  156. package/dist/resources/databases.js +22 -19
  157. package/dist/resources/databases.js.map +1 -1
  158. package/dist/resources/search.js +11 -5
  159. package/dist/resources/search.js.map +1 -1
  160. package/dist/resources/transaction.d.ts +2 -1
  161. package/dist/security/auth.js +1 -1
  162. package/dist/security/auth.js.map +1 -1
  163. package/dist/security/cryptoHash.d.ts +2 -2
  164. package/dist/security/jsLoader.js +243 -66
  165. package/dist/security/jsLoader.js.map +1 -1
  166. package/dist/security/keys.js +4 -5
  167. package/dist/security/keys.js.map +1 -1
  168. package/dist/security/user.js +3 -3
  169. package/dist/security/user.js.map +1 -1
  170. package/dist/server/REST.js +16 -2
  171. package/dist/server/REST.js.map +1 -1
  172. package/dist/server/Server.d.ts +2 -1
  173. package/dist/server/Server.js.map +1 -1
  174. package/dist/server/fastifyRoutes/plugins/hdbCore.d.ts +6 -1
  175. package/dist/server/fastifyRoutes.js +2 -0
  176. package/dist/server/fastifyRoutes.js.map +1 -1
  177. package/dist/server/http.js +12 -6
  178. package/dist/server/http.js.map +1 -1
  179. package/dist/server/jobs/JobObject.d.ts +3 -3
  180. package/dist/server/loadRootComponents.js +1 -0
  181. package/dist/server/loadRootComponents.js.map +1 -1
  182. package/dist/server/operationsServer.js +3 -1
  183. package/dist/server/operationsServer.js.map +1 -1
  184. package/dist/server/serverHelpers/JSONStream.d.ts +3 -3
  185. package/dist/server/serverHelpers/Request.d.ts +5 -5
  186. package/dist/server/serverHelpers/requestTimePlugin.d.ts +1 -1
  187. package/dist/server/threads/manageThreads.d.ts +2 -2
  188. package/dist/server/threads/manageThreads.js +50 -35
  189. package/dist/server/threads/manageThreads.js.map +1 -1
  190. package/dist/server/threads/socketRouter.d.ts +1 -1
  191. package/dist/sqlTranslator/deleteTranslator.d.ts +1 -1
  192. package/dist/utility/AWS/AWSConnector.d.ts +3 -2
  193. package/dist/utility/common_utils.d.ts +3 -3
  194. package/dist/utility/environment/systemInformation.d.ts +1 -0
  195. package/dist/utility/functions/date/dateFunctions.d.ts +11 -11
  196. package/dist/utility/globalSchema.d.ts +1 -1
  197. package/dist/utility/hdbTerms.d.ts +3 -0
  198. package/dist/utility/hdbTerms.js +3 -0
  199. package/dist/utility/hdbTerms.js.map +1 -1
  200. package/dist/utility/installation.d.ts +2 -4
  201. package/dist/utility/installation.js.map +1 -1
  202. package/dist/utility/lmdb/commonUtility.d.ts +1 -0
  203. package/dist/utility/lmdb/deleteUtility.d.ts +1 -0
  204. package/dist/utility/lmdb/environmentUtility.d.ts +1 -0
  205. package/dist/utility/lmdb/searchUtility.d.ts +2 -1
  206. package/dist/utility/lmdb/writeUtility.d.ts +1 -0
  207. package/dist/utility/logging/harper_logger.d.ts +6 -6
  208. package/dist/utility/processManagement/processManagement.d.ts +1 -1
  209. package/dist/utility/processManagement/servicesConfig.d.ts +12 -6
  210. package/dist/validation/common_validators.d.ts +4 -3
  211. package/dist/validation/configValidator.d.ts +3 -2
  212. package/index.d.ts +56 -0
  213. package/index.js +41 -0
  214. package/json/systemSchema.json +373 -0
  215. package/launchServiceScripts/launchHarperDB.js +3 -0
  216. package/launchServiceScripts/utility/checkNodeVersion.js +15 -0
  217. package/package.json +21 -3
  218. package/resources/DatabaseTransaction.ts +378 -0
  219. package/resources/ErrorResource.ts +57 -0
  220. package/resources/IterableEventQueue.ts +94 -0
  221. package/resources/LMDBTransaction.ts +349 -0
  222. package/resources/RecordEncoder.ts +702 -0
  223. package/resources/RequestTarget.ts +134 -0
  224. package/resources/Resource.ts +789 -0
  225. package/resources/ResourceInterface.ts +221 -0
  226. package/resources/ResourceInterfaceV2.ts +53 -0
  227. package/resources/ResourceV2.ts +67 -0
  228. package/resources/Resources.ts +162 -0
  229. package/resources/RocksIndexStore.ts +70 -0
  230. package/resources/RocksTransactionLogStore.ts +352 -0
  231. package/resources/Table.ts +4527 -0
  232. package/resources/analytics/hostnames.ts +72 -0
  233. package/resources/analytics/metadata.ts +10 -0
  234. package/resources/analytics/read.ts +252 -0
  235. package/resources/analytics/write.ts +803 -0
  236. package/resources/auditStore.ts +556 -0
  237. package/resources/blob.ts +1268 -0
  238. package/resources/crdt.ts +125 -0
  239. package/resources/dataLoader.ts +527 -0
  240. package/resources/databases.ts +1290 -0
  241. package/resources/graphql.ts +221 -0
  242. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +638 -0
  243. package/resources/indexes/customIndexes.ts +7 -0
  244. package/resources/indexes/vector.ts +38 -0
  245. package/resources/jsResource.ts +86 -0
  246. package/resources/loadEnv.ts +22 -0
  247. package/resources/login.ts +18 -0
  248. package/resources/openApi.ts +409 -0
  249. package/resources/registrationDeprecated.ts +8 -0
  250. package/resources/replayLogs.ts +136 -0
  251. package/resources/roles.ts +98 -0
  252. package/resources/search.ts +1301 -0
  253. package/resources/tracked.ts +584 -0
  254. package/resources/transaction.ts +89 -0
  255. package/resources/transactionBroadcast.ts +258 -0
  256. package/security/auth.ts +376 -0
  257. package/security/certificateVerification/certificateVerificationSource.ts +84 -0
  258. package/security/certificateVerification/configValidation.ts +107 -0
  259. package/security/certificateVerification/crlVerification.ts +623 -0
  260. package/security/certificateVerification/index.ts +121 -0
  261. package/security/certificateVerification/ocspVerification.ts +148 -0
  262. package/security/certificateVerification/pkijs-ed25519-patch.ts +188 -0
  263. package/security/certificateVerification/types.ts +128 -0
  264. package/security/certificateVerification/verificationConfig.ts +138 -0
  265. package/security/certificateVerification/verificationUtils.ts +447 -0
  266. package/security/cryptoHash.js +42 -0
  267. package/security/data_objects/PermissionAttributeResponseObject.js +15 -0
  268. package/security/data_objects/PermissionResponseObject.js +115 -0
  269. package/security/data_objects/PermissionTableResponseObject.js +20 -0
  270. package/security/fastifyAuth.js +169 -0
  271. package/security/impersonation.ts +160 -0
  272. package/security/jsLoader.ts +716 -0
  273. package/security/keys.js +948 -0
  274. package/security/permissionsTranslator.js +300 -0
  275. package/security/role.js +218 -0
  276. package/security/tokenAuthentication.ts +228 -0
  277. package/security/user.ts +449 -0
  278. package/server/DurableSubscriptionsSession.ts +503 -0
  279. package/server/REST.ts +407 -0
  280. package/server/Server.ts +89 -0
  281. package/server/fastifyRoutes/helpers/getCORSOptions.js +36 -0
  282. package/server/fastifyRoutes/helpers/getHeaderTimeoutConfig.js +15 -0
  283. package/server/fastifyRoutes/helpers/getServerOptions.js +33 -0
  284. package/server/fastifyRoutes/plugins/hdbCore.js +39 -0
  285. package/server/fastifyRoutes.ts +205 -0
  286. package/server/graphqlQuerying.ts +700 -0
  287. package/server/http.ts +640 -0
  288. package/server/itc/serverHandlers.js +161 -0
  289. package/server/itc/utility/ITCEventObject.js +10 -0
  290. package/server/jobs/JobObject.js +24 -0
  291. package/server/jobs/jobProcess.js +69 -0
  292. package/server/jobs/jobRunner.js +162 -0
  293. package/server/jobs/jobs.js +304 -0
  294. package/server/loadRootComponents.js +44 -0
  295. package/server/mqtt.ts +485 -0
  296. package/server/nodeName.ts +75 -0
  297. package/server/operationsServer.ts +313 -0
  298. package/server/serverHelpers/Headers.ts +108 -0
  299. package/server/serverHelpers/JSONStream.ts +269 -0
  300. package/server/serverHelpers/OperationFunctionObject.ts +13 -0
  301. package/server/serverHelpers/Request.ts +158 -0
  302. package/server/serverHelpers/contentTypes.ts +637 -0
  303. package/server/serverHelpers/requestTimePlugin.js +57 -0
  304. package/server/serverHelpers/serverHandlers.js +148 -0
  305. package/server/serverHelpers/serverUtilities.ts +473 -0
  306. package/server/serverRegistry.ts +8 -0
  307. package/server/static.ts +187 -0
  308. package/server/status/definitions.ts +37 -0
  309. package/server/status/index.ts +125 -0
  310. package/server/storageReclamation.ts +93 -0
  311. package/server/threads/itc.js +89 -0
  312. package/server/threads/manageThreads.js +594 -0
  313. package/server/threads/socketRouter.ts +360 -0
  314. package/server/threads/threadServer.js +279 -0
  315. package/server/throttle.ts +73 -0
  316. package/sqlTranslator/SelectValidator.js +330 -0
  317. package/sqlTranslator/alasqlFunctionImporter.js +62 -0
  318. package/sqlTranslator/deleteTranslator.js +67 -0
  319. package/sqlTranslator/index.js +242 -0
  320. package/sqlTranslator/sql_statement_bucket.js +472 -0
  321. package/static/defaultConfig.yaml +3 -0
  322. package/studio/web/HDBDogOnly.svg +78 -0
  323. package/studio/web/assets/PPRadioGrotesk-Bold-DDaUYG8E.woff +0 -0
  324. package/studio/web/assets/fa-brands-400-CEJbCg16.woff +0 -0
  325. package/studio/web/assets/fa-brands-400-CSYNqBb_.ttf +0 -0
  326. package/studio/web/assets/fa-brands-400-DnkPfk3o.eot +0 -0
  327. package/studio/web/assets/fa-brands-400-UxlILjvJ.woff2 +0 -0
  328. package/studio/web/assets/fa-brands-400-cH1MgKbP.svg +3717 -0
  329. package/studio/web/assets/fa-regular-400-BhTwtT8w.eot +0 -0
  330. package/studio/web/assets/fa-regular-400-D1vz6WBx.ttf +0 -0
  331. package/studio/web/assets/fa-regular-400-DFnMcJPd.woff +0 -0
  332. package/studio/web/assets/fa-regular-400-DGzu1beS.woff2 +0 -0
  333. package/studio/web/assets/fa-regular-400-gwj8Pxq-.svg +801 -0
  334. package/studio/web/assets/fa-solid-900-B4ZZ7kfP.svg +5034 -0
  335. package/studio/web/assets/fa-solid-900-B6Axprfb.eot +0 -0
  336. package/studio/web/assets/fa-solid-900-BUswJgRo.woff2 +0 -0
  337. package/studio/web/assets/fa-solid-900-DOXgCApm.woff +0 -0
  338. package/studio/web/assets/fa-solid-900-mxuxnBEa.ttf +0 -0
  339. package/studio/web/assets/index-BTgXJX9d.js +235 -0
  340. package/studio/web/assets/index-BTgXJX9d.js.map +1 -0
  341. package/studio/web/assets/index-C-GXfcup.js +37 -0
  342. package/studio/web/assets/index-C-GXfcup.js.map +1 -0
  343. package/studio/web/assets/index-PFlNdimM.js +2 -0
  344. package/studio/web/assets/index-PFlNdimM.js.map +1 -0
  345. package/studio/web/assets/index-Y2g_iFpU.css +1 -0
  346. package/studio/web/assets/index-jiPwkrsB.css +1 -0
  347. package/studio/web/assets/index.lazy-C3TJZJ4o.js +266 -0
  348. package/studio/web/assets/index.lazy-C3TJZJ4o.js.map +1 -0
  349. package/studio/web/assets/profiler-DotzgiCJ.js +2 -0
  350. package/studio/web/assets/profiler-DotzgiCJ.js.map +1 -0
  351. package/studio/web/assets/react-redux-VxUEx_mU.js +6 -0
  352. package/studio/web/assets/react-redux-VxUEx_mU.js.map +1 -0
  353. package/studio/web/assets/startRecording-B_9J9Csd.js +3 -0
  354. package/studio/web/assets/startRecording-B_9J9Csd.js.map +1 -0
  355. package/studio/web/fabric-signup-background.webp +0 -0
  356. package/studio/web/fabric-signup-text.png +0 -0
  357. package/studio/web/favicon_purple.png +0 -0
  358. package/studio/web/github-icon.svg +15 -0
  359. package/studio/web/harper-fabric_black.png +0 -0
  360. package/studio/web/harper-fabric_white.png +0 -0
  361. package/studio/web/harper-studio_white.png +0 -0
  362. package/studio/web/index.html +16 -0
  363. package/studio/web/running.css +148 -0
  364. package/studio/web/running.html +147 -0
  365. package/studio/web/running.js +111 -0
  366. package/upgrade/UpgradeObjects.js +13 -0
  367. package/upgrade/directives/directivesController.js +90 -0
  368. package/upgrade/directivesManager.js +139 -0
  369. package/upgrade/upgradePrompt.js +124 -0
  370. package/upgrade/upgradeUtilities.js +28 -0
  371. package/utility/AWS/AWSConnector.js +29 -0
  372. package/utility/OperationFunctionCaller.js +63 -0
  373. package/utility/assignCmdEnvVariables.js +62 -0
  374. package/utility/common_utils.js +867 -0
  375. package/utility/environment/environmentManager.js +208 -0
  376. package/utility/environment/systemInformation.js +355 -0
  377. package/utility/errors/commonErrors.js +267 -0
  378. package/utility/errors/hdbError.js +146 -0
  379. package/utility/functions/date/dateFunctions.js +65 -0
  380. package/utility/functions/geo.js +355 -0
  381. package/utility/functions/sql/alaSQLExtension.js +104 -0
  382. package/utility/globalSchema.js +35 -0
  383. package/utility/hdbTerms.ts +819 -0
  384. package/utility/install/checkJWTTokensExist.js +62 -0
  385. package/utility/install/harperdb.conf +15 -0
  386. package/utility/install/harperdb.service +14 -0
  387. package/utility/install/installer.js +635 -0
  388. package/utility/installation.ts +30 -0
  389. package/utility/lmdb/DBIDefinition.js +20 -0
  390. package/utility/lmdb/DeleteRecordsResponseObject.js +25 -0
  391. package/utility/lmdb/InsertRecordsResponseObject.js +22 -0
  392. package/utility/lmdb/OpenDBIObject.js +31 -0
  393. package/utility/lmdb/OpenEnvironmentObject.js +41 -0
  394. package/utility/lmdb/UpdateRecordsResponseObject.js +25 -0
  395. package/utility/lmdb/UpsertRecordsResponseObject.js +22 -0
  396. package/utility/lmdb/cleanLMDBMap.js +65 -0
  397. package/utility/lmdb/commonUtility.js +119 -0
  398. package/utility/lmdb/deleteUtility.js +128 -0
  399. package/utility/lmdb/environmentUtility.js +477 -0
  400. package/utility/lmdb/searchCursorFunctions.js +187 -0
  401. package/utility/lmdb/searchUtility.js +918 -0
  402. package/utility/lmdb/terms.js +57 -0
  403. package/utility/lmdb/writeUtility.js +407 -0
  404. package/utility/logging/harper_logger.js +876 -0
  405. package/utility/logging/logRotator.js +157 -0
  406. package/utility/logging/logger.ts +24 -0
  407. package/utility/logging/readLog.js +355 -0
  408. package/utility/logging/transactionLog.js +57 -0
  409. package/utility/mount_hdb.js +59 -0
  410. package/utility/npmUtilities.js +102 -0
  411. package/utility/operationPermissions.ts +112 -0
  412. package/utility/operation_authorization.js +836 -0
  413. package/utility/packageUtils.js +55 -0
  414. package/utility/password.ts +99 -0
  415. package/utility/processManagement/processManagement.js +187 -0
  416. package/utility/processManagement/servicesConfig.js +56 -0
  417. package/utility/scripts/restartHdb.js +24 -0
  418. package/utility/scripts/user_data.sh +13 -0
  419. package/utility/signalling.js +36 -0
  420. package/utility/terms/certificates.js +81 -0
  421. package/utility/when.ts +20 -0
  422. package/v1.d.ts +39 -0
  423. package/v1.js +41 -0
  424. package/v2.d.ts +39 -0
  425. package/v2.js +41 -0
  426. package/validation/bulkDeleteValidator.js +24 -0
  427. package/validation/check_permissions.js +19 -0
  428. package/validation/common_validators.js +95 -0
  429. package/validation/configValidator.js +331 -0
  430. package/validation/deleteValidator.js +15 -0
  431. package/validation/fileLoadValidator.js +153 -0
  432. package/validation/insertValidator.js +40 -0
  433. package/validation/installValidator.js +37 -0
  434. package/validation/readLogValidator.js +64 -0
  435. package/validation/role_validation.js +320 -0
  436. package/validation/schemaMetadataValidator.js +42 -0
  437. package/validation/searchValidator.js +166 -0
  438. package/validation/statusValidator.ts +66 -0
  439. package/validation/transactionLogValidator.js +33 -0
  440. package/validation/user_validation.js +55 -0
  441. package/validation/validationWrapper.js +105 -0
  442. package/dist/resources/analytics/profile.d.ts +0 -2
  443. package/dist/resources/analytics/profile.js +0 -144
  444. package/dist/resources/analytics/profile.js.map +0 -1
@@ -0,0 +1,803 @@
1
+ import { parentPort, threadId } from 'worker_threads';
2
+ import { onMessageByType } from '../../server/threads/manageThreads.js';
3
+ import { getDatabases, table } from '../databases.ts';
4
+ import type { Databases, Table, Tables } from '../databases.ts';
5
+ import harperLogger from '../../utility/logging/harper_logger.js';
6
+ import { stat } from 'node:fs/promises';
7
+ const { getLogFilePath, forComponent } = harperLogger;
8
+ import { dirname, join } from 'path';
9
+ import { open } from 'fs/promises';
10
+ import { getNextMonotonicTime } from '../../utility/lmdb/commonUtility.js';
11
+ import { get as envGet, initSync } from '../../utility/environment/environmentManager.js';
12
+ import { CONFIG_PARAMS } from '../../utility/hdbTerms.ts';
13
+ import { server } from '../../server/Server.ts';
14
+ import * as fs from 'node:fs';
15
+ import { getAnalyticsHostnameTable, nodeIds, stableNodeId } from './hostnames.ts';
16
+ import { METRIC } from './metadata.ts';
17
+ import { RocksDatabase } from '@harperfast/rocksdb-js';
18
+
19
+ const log = forComponent('analytics').conditional;
20
+
21
+ initSync();
22
+
23
+ type ActionCallback = (action: Action) => void;
24
+ export type Value = number | boolean | ActionCallback;
25
+ interface Action {
26
+ total?: number;
27
+ values?: Float32Array;
28
+ count?: number;
29
+ callback?: ActionCallback;
30
+ description?: {
31
+ metric: string;
32
+ path: string;
33
+ method: string;
34
+ type: string;
35
+ };
36
+ }
37
+
38
+ let activeActions = new Map<string, Action>();
39
+ let analyticsEnabled = envGet(CONFIG_PARAMS.ANALYTICS_AGGREGATEPERIOD) > -1;
40
+ let sendAnalyticsTimeout: NodeJS.Timeout;
41
+
42
+ export function setAnalyticsEnabled(enabled: boolean) {
43
+ analyticsEnabled = enabled;
44
+ clearTimeout(sendAnalyticsTimeout); // reset this
45
+ sendAnalyticsTimeout = null;
46
+ }
47
+
48
+ function recordExistingAction(value: Value, action: Action) {
49
+ if (typeof value === 'number') {
50
+ let values: Float32Array = action.values;
51
+ const index = values.index++;
52
+ if (index >= values.length) {
53
+ const oldValues = values;
54
+ action.values = values = new Float32Array(index * 2);
55
+ values.set(oldValues);
56
+ values.index = index + 1;
57
+ }
58
+ values[index] = value;
59
+ action.total += value;
60
+ } else if (typeof value === 'boolean') {
61
+ if (value) action.total++;
62
+ action.count++;
63
+ } else if (typeof value === 'function') {
64
+ // nothing to do except wait for the callback
65
+ action.count++;
66
+ } else throw new TypeError('Invalid metric value type ' + typeof value);
67
+ }
68
+
69
+ function recordNewAction(key: string, value: Value, metric?: string, path?: string, method?: string, type?: string) {
70
+ const action: Action = {};
71
+ if (typeof value === 'number') {
72
+ action.total = value;
73
+ action.values = new Float32Array(4);
74
+ action.values.index = 1;
75
+ action.values[0] = value;
76
+ action.total = value;
77
+ } else if (typeof value === 'boolean') {
78
+ action.total = value ? 1 : 0;
79
+ action.count = 1;
80
+ } else if (typeof value === 'function') {
81
+ action.count = 1;
82
+ action.callback = value;
83
+ } else {
84
+ throw new TypeError('Invalid metric value type ' + typeof value);
85
+ }
86
+ action.description = {
87
+ metric,
88
+ path,
89
+ method,
90
+ type,
91
+ };
92
+ activeActions.set(key, action);
93
+ }
94
+
95
+ /**
96
+ * Record an action for analytics (like an HTTP request, replication, MQTT message)
97
+ * @param value
98
+ * @param metric
99
+ * @param path
100
+ * @param method
101
+ * @param type
102
+ */
103
+ export function recordAction(value: Value, metric: string, path?: string, method?: string, type?: string) {
104
+ if (!analyticsEnabled) return;
105
+ // TODO: May want to consider nested paths, as they may yield faster hashing of (fixed) strings that hashing concatenated strings
106
+ let key = metric + (path ? '-' + path : '');
107
+ if (method !== undefined) key += '-' + method;
108
+ if (type !== undefined) key += '-' + type;
109
+ const action = activeActions.get(key);
110
+ if (action) {
111
+ recordExistingAction(value, action);
112
+ } else {
113
+ recordNewAction(key, value, metric, path, method, type);
114
+ }
115
+ if (!sendAnalyticsTimeout) sendAnalytics();
116
+ }
117
+
118
+ server.recordAnalytics = recordAction;
119
+
120
+ export function recordActionBinary(value, metric, path?, method?, type?) {
121
+ recordAction(Boolean(value), metric, path, method, type);
122
+ }
123
+
124
+ let analyticsStart = 0;
125
+ export const analyticsDelay = 1000;
126
+ const ANALYTICS_REPORT_TYPE = 'analytics-report';
127
+ const analyticsListeners = [];
128
+ const analyticsAggregateListeners = [];
129
+
130
+ export function addAnalyticsListener(callback) {
131
+ analyticsListeners.push(callback);
132
+ }
133
+
134
+ const IDEAL_PERCENTILES = [0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99, 0.999, 1];
135
+
136
+ /**
137
+ * Periodically send analytics data back to the main thread for storage
138
+ */
139
+ function sendAnalytics() {
140
+ analyticsStart ||= performance.now();
141
+ sendAnalyticsTimeout = setTimeout(async () => {
142
+ sendAnalyticsTimeout = null;
143
+ const period = performance.now() - analyticsStart;
144
+ analyticsStart = 0;
145
+ const metrics = [];
146
+ const report = {
147
+ time: Date.now(),
148
+ period,
149
+ threadId,
150
+ metrics,
151
+ };
152
+ for (const [_name, action] of activeActions) {
153
+ if (action.values) {
154
+ const values = action.values.subarray(0, action.values.index);
155
+ values.sort();
156
+ const count = values.length;
157
+ // compute the stats
158
+ let lastUpperBound = 0;
159
+ const distribution = [];
160
+ let lastValue;
161
+ for (const percentile of IDEAL_PERCENTILES) {
162
+ const upperBound = Math.floor(count * percentile);
163
+ const value = values[upperBound - 1];
164
+ if (upperBound > lastUpperBound) {
165
+ const count = upperBound - lastUpperBound;
166
+ if (value === lastValue) {
167
+ const entry = distribution[distribution.length - 1];
168
+ if (typeof entry === 'number') distribution[distribution.length - 1] = { value: entry, count: 1 + count };
169
+ else entry.count += count;
170
+ } else {
171
+ distribution.push(count > 1 ? { value, count } : value);
172
+ lastValue = value;
173
+ }
174
+ lastUpperBound = upperBound;
175
+ }
176
+ }
177
+ metrics.push(
178
+ Object.assign(action.description, {
179
+ mean: action.total / count,
180
+ distribution,
181
+ count,
182
+ })
183
+ );
184
+ } else if (action.callback) {
185
+ metrics.push(Object.assign(action.description, action.callback(action)));
186
+ } else {
187
+ metrics.push(
188
+ Object.assign(action.description, {
189
+ total: action.total,
190
+ count: action.count,
191
+ })
192
+ );
193
+ }
194
+ await rest(); // sort's are expensive and we don't want to do two of them in the same event turn
195
+ }
196
+ const memoryUsage = process.memoryUsage();
197
+ metrics.push({
198
+ metric: 'memory',
199
+ threadId,
200
+ byThread: true,
201
+ ...memoryUsage,
202
+ });
203
+ for (const listener of analyticsListeners) {
204
+ listener(metrics);
205
+ }
206
+ activeActions = new Map();
207
+ if (parentPort)
208
+ parentPort.postMessage({
209
+ type: ANALYTICS_REPORT_TYPE,
210
+ report,
211
+ });
212
+ else recordAnalytics({ report });
213
+ }, analyticsDelay).unref();
214
+ }
215
+
216
+ export async function recordHostname() {
217
+ const hostname = server.hostname;
218
+ log.trace?.('recordHostname server.hostname:', hostname);
219
+ const nodeId = stableNodeId(hostname);
220
+ log.trace?.('recordHostname nodeId:', nodeId);
221
+ const hostnamesTable = getAnalyticsHostnameTable();
222
+ const record = await hostnamesTable.get(nodeId);
223
+ if (!record) {
224
+ const hostnameRecord = {
225
+ id: nodeId,
226
+ hostname,
227
+ };
228
+ log.trace?.(`recordHostname storing hostname: ${JSON.stringify(hostnameRecord)}`);
229
+ await hostnamesTable.put(hostnameRecord.id, hostnameRecord);
230
+ }
231
+ }
232
+
233
+ export interface Metric {
234
+ [key: string]: any;
235
+ }
236
+
237
+ function getHostNodeId(hostname: string) {
238
+ let nodeId = nodeIds.get(hostname);
239
+ if (nodeId) {
240
+ log.trace?.('storeMetric cached nodeId:', nodeId);
241
+ return nodeId;
242
+ }
243
+ nodeId = stableNodeId(hostname);
244
+ log.trace?.('storeMetric new nodeId:', nodeId);
245
+ nodeIds.set(hostname, nodeId);
246
+ return nodeId;
247
+ }
248
+
249
+ function storeMetric(table: Table, metric: Metric) {
250
+ const nodeId = getHostNodeId(server.hostname);
251
+ const metricValue = {
252
+ id: [getNextMonotonicTime(), nodeId],
253
+ ...metric,
254
+ };
255
+ log.trace?.(`storing metric ${JSON.stringify(metricValue)}`);
256
+ table.put(metricValue.id, metricValue);
257
+ }
258
+
259
+ interface ResourceUsage extends Partial<NodeJS.ResourceUsage> {
260
+ time?: number;
261
+ period?: number;
262
+ cpuUtilization?: number;
263
+ userCPUTime?: number;
264
+ systemCPUTime?: number;
265
+ }
266
+
267
+ /** calculateCPUUtilization takes a ResourceUsage with at least userCPUTime &
268
+ * systemCPUTime set with millisecond values and a time period in milliseconds
269
+ * and returns the percentage of that time the CPU was being utilized as a
270
+ * decimal value between 0 and 1. So for example, 50% utilization will be
271
+ * returned as 0.5.
272
+ */
273
+ export function calculateCPUUtilization(resourceUsage: ResourceUsage, period: number): number {
274
+ const cpuTime = resourceUsage.userCPUTime + resourceUsage.systemCPUTime;
275
+ log.trace?.(`calculateCPUUtilization cpuTime: ${cpuTime} period: ${period}`);
276
+ return Math.round((cpuTime / period) * 100) / 100;
277
+ }
278
+
279
+ /** diffResourceUsage takes a ResourceUsage representing the last time we stored them and a new
280
+ * process.resourceUsage() return value and normalizes and diffs the two values to return the
281
+ * new values for this time period.
282
+ */
283
+ export function diffResourceUsage(lastResourceUsage: ResourceUsage, resourceUsage: ResourceUsage): ResourceUsage {
284
+ return {
285
+ userCPUTime: resourceUsage.userCPUTime - (lastResourceUsage?.userCPUTime ?? 0),
286
+ systemCPUTime: resourceUsage.systemCPUTime - (lastResourceUsage?.systemCPUTime ?? 0),
287
+ minorPageFault: resourceUsage.minorPageFault - (lastResourceUsage?.minorPageFault ?? 0),
288
+ majorPageFault: resourceUsage.majorPageFault - (lastResourceUsage?.majorPageFault ?? 0),
289
+ fsRead: resourceUsage.fsRead - (lastResourceUsage?.fsRead ?? 0),
290
+ fsWrite: resourceUsage.fsWrite - (lastResourceUsage?.fsWrite ?? 0),
291
+ voluntaryContextSwitches:
292
+ resourceUsage.voluntaryContextSwitches - (lastResourceUsage?.voluntaryContextSwitches ?? 0),
293
+ involuntaryContextSwitches:
294
+ resourceUsage.involuntaryContextSwitches - (lastResourceUsage?.involuntaryContextSwitches ?? 0),
295
+ };
296
+ }
297
+
298
+ /** storeTableSizeMetrics returns the cumulative size of the tables
299
+ */
300
+ function storeTableSizeMetrics(analyticsTable: Table, dbName: string, tables: Tables): number {
301
+ let dbUsedSize = 0;
302
+ for (const [tableName, table] of Object.entries(tables)) {
303
+ const fullTableName = `${dbName}.${tableName}`;
304
+ const tableSize = table.getSize();
305
+ const metric = {
306
+ metric: METRIC.TABLE_SIZE,
307
+ database: dbName,
308
+ table: tableName,
309
+ size: tableSize,
310
+ };
311
+ log.trace?.(`table ${fullTableName} size metric: ${JSON.stringify(metric)}`);
312
+ storeMetric(analyticsTable, metric);
313
+ dbUsedSize += tableSize;
314
+ }
315
+ return dbUsedSize;
316
+ }
317
+
318
+ function storeDBSizeMetrics(analyticsTable: Table, databases: Databases) {
319
+ for (const [db, tables] of Object.entries(databases)) {
320
+ try {
321
+ const [firstTable] = Object.values(tables);
322
+ const dbAuditSize = firstTable?.getAuditSize();
323
+ if (!dbAuditSize) {
324
+ return;
325
+ }
326
+ let metric;
327
+ if (firstTable.primaryStore instanceof RocksDatabase) {
328
+ const dbPath = firstTable.primaryStore.path;
329
+ let dbSize = 0;
330
+ for (const filename of fs.readdirSync(dbPath)) {
331
+ if (filename.endsWith('.sst')) {
332
+ dbSize += fs.statSync(join(dbPath, filename)).size;
333
+ }
334
+ }
335
+ metric = {
336
+ metric: METRIC.DATABASE_SIZE,
337
+ database: db,
338
+ size: dbSize,
339
+ transactionLog: dbAuditSize,
340
+ };
341
+ storeMetric(analyticsTable, metric);
342
+ } else {
343
+ const dbTotalSize = fs.statSync(firstTable.primaryStore.path).size;
344
+ const dbUsedSize = storeTableSizeMetrics(analyticsTable, db, tables);
345
+ const dbFree = dbTotalSize - dbUsedSize;
346
+ metric = {
347
+ metric: METRIC.DATABASE_SIZE,
348
+ database: db,
349
+ size: dbTotalSize,
350
+ used: dbUsedSize,
351
+ free: dbFree,
352
+ audit: dbAuditSize,
353
+ };
354
+ storeMetric(analyticsTable, metric);
355
+ }
356
+ } catch (error) {
357
+ // a table or db was deleted, could get an error here
358
+ log.warn?.(`Error getting DB size metrics`, error);
359
+ }
360
+ }
361
+ }
362
+
363
+ function storeVolumeMetrics(analyticsTable: Table, databases: Databases) {
364
+ for (const [db, tables] of Object.entries(databases)) {
365
+ try {
366
+ const [firstTable] = Object.values(tables);
367
+ const storageStats = firstTable?.getStorageStats();
368
+ if (!storageStats) {
369
+ return;
370
+ }
371
+ const metric = {
372
+ metric: METRIC.STORAGE_VOLUME,
373
+ database: db,
374
+ ...storageStats,
375
+ };
376
+ storeMetric(analyticsTable, metric);
377
+ log.trace?.(`db ${db} storage volume metrics: ${JSON.stringify(metric)}`);
378
+ } catch (error) {
379
+ // a table or db was deleted, could get an error here
380
+ log.warn?.(`Error getting DB volume metrics`, error);
381
+ }
382
+ }
383
+ }
384
+
385
+ async function aggregation(fromPeriod, toPeriod = 60000) {
386
+ const rawAnalyticsTable = getRawAnalyticsTable();
387
+ const analyticsTable = getAnalyticsTable();
388
+ const taskQueueLatency = (async () => {
389
+ const start = performance.now();
390
+ // measure how long it takes to enqueue and get a callback from a simple/fast task:
391
+ await stat(getLogFilePath());
392
+ const delay = performance.now() - start;
393
+ if (delay > 5000) {
394
+ log.warn?.('Unusually high task queue latency on the main thread of ' + Math.round(now - start) + 'ms');
395
+ }
396
+ return delay;
397
+ })();
398
+ let lastForPeriod;
399
+ const localNodeId = getHostNodeId(server.hostname);
400
+ // find the last entry for this period for the local node only
401
+ for (const entry of analyticsTable.primaryStore.getRange({
402
+ start: Infinity,
403
+ end: false,
404
+ reverse: true,
405
+ })) {
406
+ if (!entry.value?.time || entry.value?.id[1] !== localNodeId) continue;
407
+ lastForPeriod = entry.value.time;
408
+ break;
409
+ }
410
+ // was the last aggregation too recent to calculate a whole period?
411
+ if (Date.now() - toPeriod < lastForPeriod) return;
412
+ let firstForPeriod;
413
+ const aggregateActions = new Map();
414
+ const distributions = new Map();
415
+ const threadsToAverage = [];
416
+ let lastTime: number;
417
+ for (const { key, value } of rawAnalyticsTable.primaryStore.getRange({
418
+ start: lastForPeriod || false,
419
+ exclusiveStart: true,
420
+ end: Infinity,
421
+ })) {
422
+ if (!value) continue;
423
+ if (firstForPeriod) {
424
+ if (key > firstForPeriod + toPeriod) break; // outside the period of interest
425
+ } else firstForPeriod = key;
426
+ lastTime = key;
427
+ const { metrics, threadId } = value;
428
+ for (const entry of metrics || []) {
429
+ // eslint-disable-next-line no-unused-vars
430
+ let { path, method, type, metric, count, total, distribution, threads, ...measures } = entry;
431
+ if (!count) count = 1;
432
+ let key = metric + (path ? '-' + path : '');
433
+ if (method !== undefined) key += '-' + method;
434
+ if (type !== undefined) key += '-' + type;
435
+ let action = aggregateActions.get(key);
436
+ if (action) {
437
+ if (action.threads) {
438
+ const actionForThread = action.threads[threadId];
439
+ if (actionForThread) action = actionForThread;
440
+ else {
441
+ action.threads[threadId] = { ...measures };
442
+ continue;
443
+ }
444
+ }
445
+ if (!action.count) action.count = 1;
446
+ const previousCount = action.count;
447
+ for (const measureName in measures) {
448
+ const value = measures[measureName];
449
+ if (typeof value === 'number') {
450
+ action[measureName] = (action[measureName] * previousCount + value * count) / (previousCount + count);
451
+ }
452
+ }
453
+ action.count += count;
454
+ if (total >= 0) {
455
+ action.total += total;
456
+ action.ratio = action.total / action.count;
457
+ }
458
+ } else {
459
+ action = { period: toPeriod, ...entry };
460
+ delete action.distribution;
461
+ aggregateActions.set(key, action);
462
+ if (action.byThread) {
463
+ action.threads = [];
464
+ action.threads[threadId] = { ...measures };
465
+ threadsToAverage.push(action);
466
+ }
467
+ }
468
+ if (distribution) {
469
+ distribution = distribution.map((entry) => (typeof entry === 'number' ? { value: entry, count: 1 } : entry));
470
+ const existingDistribution = distributions.get(key);
471
+ if (!existingDistribution) distributions.set(key, distribution);
472
+ else {
473
+ existingDistribution.push(...distribution);
474
+ }
475
+ }
476
+ }
477
+ await rest();
478
+ }
479
+ for (const entry of threadsToAverage) {
480
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars,prefer-const
481
+ let { path, method, type, metric, count, total, distribution, threads, ...measures } = entry;
482
+ threads = threads.filter((thread) => thread);
483
+ for (const measureName in measures) {
484
+ if (typeof entry[measureName] !== 'number') continue;
485
+ let total = 0;
486
+ for (const thread of threads) {
487
+ const value = thread[measureName];
488
+ if (typeof value === 'number') {
489
+ total += value;
490
+ }
491
+ }
492
+ entry[measureName] = total;
493
+ }
494
+ entry.count = threads.length;
495
+ delete entry.threads;
496
+ delete entry.byThread;
497
+ }
498
+ for (const [key, distribution] of distributions) {
499
+ // now iterate through the distributions finding the close bin to each percentile and interpolating the position in that bin
500
+ const action = aggregateActions.get(key);
501
+ distribution.sort((a, b) => (a.value > b.value ? 1 : -1));
502
+ const count = action.count - 1;
503
+ const percentiles = [];
504
+ let countPosition = 0;
505
+ let index = 0;
506
+ let bin;
507
+ for (const percentile of IDEAL_PERCENTILES) {
508
+ const nextTargetCount = count * percentile;
509
+ while (countPosition < nextTargetCount) {
510
+ bin = distribution[index++];
511
+ countPosition += bin.count;
512
+ // we decrement these counts so we are skipping the minimum value in our interpolation
513
+ if (index === 1) countPosition--;
514
+ }
515
+ const previousBin = distribution[index > 1 ? index - 2 : 0];
516
+ if (!bin) bin = distribution[0];
517
+ percentiles.push(bin.value - ((bin.value - previousBin.value) * (countPosition - nextTargetCount)) / bin.count);
518
+ }
519
+ const [p1, p10, p25, median, p75, p90, p95, p99, p999] = percentiles;
520
+ Object.assign(action, { p1, p10, p25, median, p75, p90, p95, p99, p999 });
521
+ }
522
+ let hasUpdates;
523
+ for (const [, value] of aggregateActions) {
524
+ value.time = lastTime;
525
+ storeMetric(analyticsTable, value);
526
+ hasUpdates = true;
527
+ }
528
+ if (hasUpdates) {
529
+ for (const listener of analyticsAggregateListeners) {
530
+ listener(aggregateActions.values());
531
+ }
532
+ }
533
+ const now = Date.now();
534
+ const { idle, active } = performance.eventLoopUtilization();
535
+ // don't record boring entries
536
+ if (hasUpdates || active * 10 > idle) {
537
+ const value = {
538
+ metric: METRIC.MAIN_THREAD_UTILIZATION,
539
+ idle: idle - lastIdle,
540
+ active: active - lastActive,
541
+ taskQueueLatency: await taskQueueLatency,
542
+ time: now,
543
+ ...process.memoryUsage(),
544
+ };
545
+ storeMetric(analyticsTable, value);
546
+ }
547
+ lastIdle = idle;
548
+ lastActive = active;
549
+
550
+ // resource-usage metrics
551
+ const resourceUsage = process.resourceUsage() as ResourceUsage;
552
+ resourceUsage.time = now;
553
+ // normalize to milliseconds
554
+ resourceUsage.userCPUTime = resourceUsage.userCPUTime / 1000;
555
+ resourceUsage.systemCPUTime = resourceUsage.systemCPUTime / 1000;
556
+ log.trace?.(`process.resourceUsage: ${JSON.stringify(resourceUsage)}`);
557
+ const currentResourceUsage = diffResourceUsage(lastResourceUsage, resourceUsage);
558
+ log.trace?.(`diffed resourceUsage: ${JSON.stringify(currentResourceUsage)}`);
559
+ currentResourceUsage.time = now;
560
+ currentResourceUsage.period = lastResourceUsage.time ? now - lastResourceUsage.time : toPeriod;
561
+ currentResourceUsage.cpuUtilization = calculateCPUUtilization(currentResourceUsage, currentResourceUsage.period);
562
+ const cruMetric = {
563
+ metric: METRIC.RESOURCE_USAGE,
564
+ ...currentResourceUsage,
565
+ };
566
+ storeMetric(analyticsTable, cruMetric);
567
+ lastResourceUsage = resourceUsage;
568
+
569
+ // database-size & table-size metrics
570
+ const databases = getDatabases();
571
+ storeDBSizeMetrics(analyticsTable, databases);
572
+ storeDBSizeMetrics(analyticsTable, { system: databases.system });
573
+
574
+ // database storage volume metrics
575
+ storeVolumeMetrics(analyticsTable, databases);
576
+ storeVolumeMetrics(analyticsTable, { system: databases.system });
577
+ }
578
+ let lastIdle = 0;
579
+ let lastActive = 0;
580
+ let lastResourceUsage: ResourceUsage = {
581
+ userCPUTime: 0,
582
+ systemCPUTime: 0,
583
+ };
584
+
585
+ const rest = () => new Promise(setImmediate);
586
+
587
+ async function cleanup(AnalyticsTable, expiration) {
588
+ const end = Date.now() - expiration;
589
+ for (const key of AnalyticsTable.primaryStore.getKeys({ start: false, end })) {
590
+ AnalyticsTable.primaryStore.remove(key);
591
+ }
592
+ }
593
+
594
+ const RAW_EXPIRATION = 3600000;
595
+ const AGGREGATE_EXPIRATION = 31536000000; // one year
596
+
597
+ let RawAnalyticsTable: Table;
598
+ function getRawAnalyticsTable() {
599
+ return (
600
+ RawAnalyticsTable ||
601
+ (RawAnalyticsTable = table({
602
+ table: 'hdb_raw_analytics',
603
+ database: 'system',
604
+ audit: false,
605
+ trackDeletes: false,
606
+ attributes: [
607
+ {
608
+ name: 'id',
609
+ isPrimaryKey: true,
610
+ },
611
+ {
612
+ name: 'action',
613
+ },
614
+ {
615
+ name: 'metrics',
616
+ },
617
+ ],
618
+ }))
619
+ );
620
+ }
621
+
622
+ let AnalyticsTable: Table;
623
+ function getAnalyticsTable() {
624
+ return (
625
+ AnalyticsTable ||
626
+ (AnalyticsTable = table({
627
+ table: 'hdb_analytics',
628
+ database: 'system',
629
+ audit: true,
630
+ trackDeletes: false,
631
+ attributes: [
632
+ {
633
+ name: 'id',
634
+ isPrimaryKey: true,
635
+ },
636
+ {
637
+ name: 'metric',
638
+ },
639
+ {
640
+ name: 'path',
641
+ },
642
+ {
643
+ name: 'method',
644
+ },
645
+ {
646
+ name: 'type',
647
+ },
648
+ ],
649
+ }))
650
+ );
651
+ }
652
+
653
+ if (!parentPort) onMessageByType(ANALYTICS_REPORT_TYPE, recordAnalytics);
654
+ let scheduledTasksRunning;
655
+ function startScheduledTasks() {
656
+ scheduledTasksRunning = true;
657
+ const AGGREGATE_PERIOD = envGet(CONFIG_PARAMS.ANALYTICS_AGGREGATEPERIOD) * 1000;
658
+ if (AGGREGATE_PERIOD) {
659
+ setInterval(
660
+ async () => {
661
+ await aggregation(analyticsDelay, AGGREGATE_PERIOD);
662
+ await cleanup(getRawAnalyticsTable(), RAW_EXPIRATION);
663
+ await cleanup(getAnalyticsTable(), AGGREGATE_EXPIRATION);
664
+ },
665
+ Math.min(AGGREGATE_PERIOD / 2, 0x7fffffff)
666
+ ).unref();
667
+ }
668
+ }
669
+
670
+ let totalBytesProcessed = 0;
671
+ const lastUtilizations = new Map();
672
+ const LOG_ANALYTICS = false; // TODO: Make this a config option if we really want this
673
+ function recordAnalytics(message, worker?) {
674
+ const report = message.report;
675
+ report.threadId = worker?.threadId || threadId;
676
+ // Add system information stats as well
677
+ for (const metric of report.metrics) {
678
+ if (metric.metric === 'bytes-sent') {
679
+ totalBytesProcessed += metric.mean * metric.count;
680
+ }
681
+ }
682
+ report.totalBytesProcessed = totalBytesProcessed;
683
+ if (worker) {
684
+ report.metrics.push({
685
+ metric: METRIC.UTILIZATION,
686
+ ...worker.performance.eventLoopUtilization(lastUtilizations.get(worker)),
687
+ });
688
+ lastUtilizations.set(worker, worker.performance.eventLoopUtilization());
689
+ }
690
+ report.id = getNextMonotonicTime();
691
+ getRawAnalyticsTable().primaryStore.put(report.id, report);
692
+ if (!scheduledTasksRunning) startScheduledTasks();
693
+ if (LOG_ANALYTICS) lastAppend = logAnalytics(report);
694
+ }
695
+ let lastAppend;
696
+ let analyticsLog;
697
+ const MAX_ANALYTICS_SIZE = 1000000;
698
+ async function logAnalytics(report) {
699
+ await lastAppend;
700
+ if (!analyticsLog) {
701
+ const logDir = dirname(getLogFilePath());
702
+ try {
703
+ analyticsLog = await open(join(logDir, 'analytics.log'), 'r+');
704
+ } catch {
705
+ analyticsLog = await open(join(logDir, 'analytics.log'), 'w+');
706
+ }
707
+ }
708
+ let position = (await analyticsLog.stat()).size;
709
+ if (position > MAX_ANALYTICS_SIZE) {
710
+ let contents = Buffer.alloc(position);
711
+ await analyticsLog.read(contents, { position: 0 });
712
+ contents = contents.subarray(contents.indexOf(10, contents.length / 2) + 1); // find a carriage return to break on after the halfway point
713
+ await analyticsLog.write(contents, { position: 0 });
714
+ await analyticsLog.truncate(contents.length);
715
+ position = contents.length;
716
+ }
717
+ await analyticsLog.write(JSON.stringify(report) + '\n', position);
718
+ }
719
+
720
+ export function onAnalyticsAggregate(callback) {
721
+ if (callback) {
722
+ analyticsAggregateListeners.push(callback);
723
+ }
724
+ }
725
+ /**
726
+ * This section contains a possible/experimental approach to bucketing values as they come instead of pushing all into an array and sorting.
727
+ *
728
+ const BUCKET_COUNT = 100;
729
+ function addToBucket(action, value) {
730
+ if (!action.buckets) {
731
+ action.buckets = newBuckets();
732
+ }
733
+ const { counts, values, totalCount } = action.buckets;
734
+ let jump = BUCKET_COUNT >> 1; // amount to jump with each iteration
735
+ let position = jump; // start at halfway point
736
+ while ((jump = jump >> 1) > 0) {
737
+ const bucketValue = values[position];
738
+ if (bucketValue === 0) {
739
+ // unused slot, immediately put our value in
740
+ counts[position] = 1;
741
+ values[position] = value;
742
+ }
743
+ if (value > bucketValue) {
744
+ position += jump;
745
+ } else {
746
+ position -= jump;
747
+ }
748
+ }
749
+ const count = counts[position] + 1;
750
+ if (position === BUCKET_COUNT) {
751
+ // if we go beyond the last item, increase the bucket (max) value
752
+ position--;
753
+ values[position] = value;
754
+ }
755
+ if (count > threshold) {
756
+ rebalance(action.buckets, false);
757
+ } else {
758
+ counts[position] = count;
759
+ }
760
+ }
761
+
762
+ function newBuckets() {
763
+ const ab = new ArrayBuffer(8 * BUCKET_COUNT);
764
+ return {
765
+ values: new Float32Array(ab, 0, BUCKET_COUNT),
766
+ counts: new Uint32Array(ab, BUCKET_COUNT * 4, BUCKET_COUNT),
767
+ totalCount: 0,
768
+ };
769
+ }
770
+
771
+ let balancingBuckets;
772
+
773
+ /**
774
+ * Rebalance the buckets, we can reset the counts at the same time, if this occurred after a delivery
775
+ * @param param
776
+ * @param resetCounts
777
+ *
778
+ function rebalance({ counts, values, totalCount }, resetCounts: boolean) {
779
+ const countPerBucket = totalCount / BUCKET_COUNT;
780
+ let targetPosition = 0;
781
+ let targetCount = 0;
782
+ let lastTargetValue = 0;
783
+ const { values: targetValues, counts: targetCounts } = balancingBuckets || (balancingBuckets = newBuckets());
784
+ for (let i = 0; i < BUCKET_COUNT; i++) {
785
+ // iterate through the existing buckets, filling up the target buckets in a balanced way
786
+ let count = counts[i];
787
+ while ((countPerBucket - targetCount) < count) {
788
+ const value = values[i];
789
+ lastTargetValue = ((countPerBucket - targetCount) / count) * (value - lastTargetValue) + lastTargetValue;
790
+ targetValues[targetPosition] = lastTargetValue;
791
+ targetCounts[targetPosition] = countPerBucket;
792
+ count -= countPerBucket;
793
+ targetPosition++;
794
+ targetCount = 0;
795
+ }
796
+ targetCount += count;
797
+ }
798
+ // now copy the balanced buckets back into the original buckets
799
+ values.set(targetValues);
800
+ if (resetCounts) counts.fill(0);
801
+ else counts.set(targetCounts);
802
+ }
803
+ */