@harperfast/harper 5.3.0-alpha.1 → 5.3.0-beta.2

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 (347) hide show
  1. package/bin/cliOperations.ts +12 -0
  2. package/bin/restart.ts +66 -6
  3. package/components/Application.ts +1134 -112
  4. package/components/DESIGN.md +421 -0
  5. package/components/OptionsWatcher.ts +368 -102
  6. package/components/Scope.ts +20 -1
  7. package/components/componentLoader.ts +43 -4
  8. package/components/deploymentOperations.ts +4 -1
  9. package/components/deploymentRecorder.ts +9 -2
  10. package/components/mcp/DESIGN.md +109 -0
  11. package/components/mcp/audit.ts +21 -17
  12. package/components/operations.js +284 -52
  13. package/components/operationsValidation.js +49 -2
  14. package/components/packageComponent.ts +25 -1
  15. package/components/requestRestart.ts +11 -0
  16. package/config/DESIGN.md +306 -0
  17. package/config/RootConfigWatcher.ts +191 -37
  18. package/config/configReadRetry.ts +62 -0
  19. package/config/configUtils.ts +78 -26
  20. package/config/parseConfigFile.ts +34 -0
  21. package/config/readConfigFileSync.ts +44 -0
  22. package/config/watcherArming.ts +59 -0
  23. package/config-root.schema.json +4 -0
  24. package/dataLayer/DESIGN.md +179 -0
  25. package/dataLayer/harperBridge/ResourceBridge.ts +28 -2
  26. package/dataLayer/restoreMarker.ts +92 -25
  27. package/dist/bin/cliOperations.js +13 -0
  28. package/dist/bin/cliOperations.js.map +1 -1
  29. package/dist/bin/restart.js +42 -6
  30. package/dist/bin/restart.js.map +1 -1
  31. package/dist/components/Application.d.ts +104 -9
  32. package/dist/components/Application.js +954 -102
  33. package/dist/components/Application.js.map +1 -1
  34. package/dist/components/OptionsWatcher.d.ts +4 -1
  35. package/dist/components/OptionsWatcher.js +378 -104
  36. package/dist/components/OptionsWatcher.js.map +1 -1
  37. package/dist/components/Scope.js +15 -1
  38. package/dist/components/Scope.js.map +1 -1
  39. package/dist/components/componentLoader.js +35 -3
  40. package/dist/components/componentLoader.js.map +1 -1
  41. package/dist/components/deploymentOperations.js +4 -1
  42. package/dist/components/deploymentOperations.js.map +1 -1
  43. package/dist/components/deploymentRecorder.d.ts +4 -2
  44. package/dist/components/deploymentRecorder.js +1 -0
  45. package/dist/components/deploymentRecorder.js.map +1 -1
  46. package/dist/components/mcp/audit.d.ts +2 -1
  47. package/dist/components/mcp/audit.js +21 -17
  48. package/dist/components/mcp/audit.js.map +1 -1
  49. package/dist/components/operations.d.ts +28 -0
  50. package/dist/components/operations.js +263 -54
  51. package/dist/components/operations.js.map +1 -1
  52. package/dist/components/operationsValidation.js +48 -2
  53. package/dist/components/operationsValidation.js.map +1 -1
  54. package/dist/components/packageComponent.js +24 -0
  55. package/dist/components/packageComponent.js.map +1 -1
  56. package/dist/components/requestRestart.d.ts +1 -0
  57. package/dist/components/requestRestart.js +7 -0
  58. package/dist/components/requestRestart.js.map +1 -1
  59. package/dist/config/RootConfigWatcher.d.ts +2 -0
  60. package/dist/config/RootConfigWatcher.js +189 -35
  61. package/dist/config/RootConfigWatcher.js.map +1 -1
  62. package/dist/config/configReadRetry.d.ts +8 -0
  63. package/dist/config/configReadRetry.js +62 -0
  64. package/dist/config/configReadRetry.js.map +1 -0
  65. package/dist/config/configUtils.d.ts +10 -9
  66. package/dist/config/configUtils.js +63 -27
  67. package/dist/config/configUtils.js.map +1 -1
  68. package/dist/config/parseConfigFile.d.ts +4 -0
  69. package/dist/config/parseConfigFile.js +35 -0
  70. package/dist/config/parseConfigFile.js.map +1 -0
  71. package/dist/config/readConfigFileSync.d.ts +1 -0
  72. package/dist/config/readConfigFileSync.js +47 -0
  73. package/dist/config/readConfigFileSync.js.map +1 -0
  74. package/dist/config/watcherArming.d.ts +15 -0
  75. package/dist/config/watcherArming.js +59 -0
  76. package/dist/config/watcherArming.js.map +1 -0
  77. package/dist/dataLayer/harperBridge/ResourceBridge.js +21 -2
  78. package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
  79. package/dist/dataLayer/restoreMarker.d.ts +21 -8
  80. package/dist/dataLayer/restoreMarker.js +94 -27
  81. package/dist/dataLayer/restoreMarker.js.map +1 -1
  82. package/dist/index.d.ts +2 -0
  83. package/dist/index.js +9 -1
  84. package/dist/index.js.map +1 -1
  85. package/dist/json/systemSchema.json +3 -0
  86. package/dist/resources/DatabaseTransaction.d.ts +25 -0
  87. package/dist/resources/DatabaseTransaction.js +224 -18
  88. package/dist/resources/DatabaseTransaction.js.map +1 -1
  89. package/dist/resources/LMDBTransaction.d.ts +2 -1
  90. package/dist/resources/LMDBTransaction.js +22 -3
  91. package/dist/resources/LMDBTransaction.js.map +1 -1
  92. package/dist/resources/PrimaryRocksDatabase.js +22 -6
  93. package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
  94. package/dist/resources/RecordEncoder.d.ts +1 -1
  95. package/dist/resources/RecordEncoder.js +46 -10
  96. package/dist/resources/RecordEncoder.js.map +1 -1
  97. package/dist/resources/Resource.js +97 -13
  98. package/dist/resources/Resource.js.map +1 -1
  99. package/dist/resources/ResourceInterface.d.ts +8 -0
  100. package/dist/resources/RocksIndexStore.js +2 -1
  101. package/dist/resources/RocksIndexStore.js.map +1 -1
  102. package/dist/resources/RocksTransactionLogStore.d.ts +10 -0
  103. package/dist/resources/RocksTransactionLogStore.js +104 -33
  104. package/dist/resources/RocksTransactionLogStore.js.map +1 -1
  105. package/dist/resources/Table.d.ts +58 -7
  106. package/dist/resources/Table.js +1143 -348
  107. package/dist/resources/Table.js.map +1 -1
  108. package/dist/resources/analytics/write.d.ts +3 -0
  109. package/dist/resources/analytics/write.js +49 -16
  110. package/dist/resources/analytics/write.js.map +1 -1
  111. package/dist/resources/auditStore.d.ts +170 -0
  112. package/dist/resources/auditStore.js +457 -11
  113. package/dist/resources/auditStore.js.map +1 -1
  114. package/dist/resources/crdt.d.ts +10 -0
  115. package/dist/resources/crdt.js +22 -0
  116. package/dist/resources/crdt.js.map +1 -1
  117. package/dist/resources/dataLoader.js +3 -4
  118. package/dist/resources/dataLoader.js.map +1 -1
  119. package/dist/resources/databases.d.ts +16 -13
  120. package/dist/resources/databases.js +625 -177
  121. package/dist/resources/databases.js.map +1 -1
  122. package/dist/resources/derivedIndexRegistry.d.ts +5 -0
  123. package/dist/resources/derivedIndexRegistry.js +68 -0
  124. package/dist/resources/derivedIndexRegistry.js.map +1 -0
  125. package/dist/resources/derivedIndexRuntime.d.ts +215 -0
  126. package/dist/resources/derivedIndexRuntime.js +2027 -0
  127. package/dist/resources/derivedIndexRuntime.js.map +1 -0
  128. package/dist/resources/graphql.js +3 -2
  129. package/dist/resources/graphql.js.map +1 -1
  130. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +102 -9
  131. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +867 -39
  132. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
  133. package/dist/resources/indexes/fullTextDerivedIndex.d.ts +81 -0
  134. package/dist/resources/indexes/fullTextDerivedIndex.js +1004 -0
  135. package/dist/resources/indexes/fullTextDerivedIndex.js.map +1 -0
  136. package/dist/resources/indexes/fullTextNativeBinding.d.ts +78 -0
  137. package/dist/resources/indexes/fullTextNativeBinding.js +85 -0
  138. package/dist/resources/indexes/fullTextNativeBinding.js.map +1 -0
  139. package/dist/resources/indexes/hnswDerivedIndex.d.ts +67 -0
  140. package/dist/resources/indexes/hnswDerivedIndex.js +464 -0
  141. package/dist/resources/indexes/hnswDerivedIndex.js.map +1 -0
  142. package/dist/resources/indexes/hnswPlaneBinding.d.ts +65 -0
  143. package/dist/resources/indexes/hnswPlaneBinding.js +91 -0
  144. package/dist/resources/indexes/hnswPlaneBinding.js.map +1 -0
  145. package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.d.ts +24 -0
  146. package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js +149 -0
  147. package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js.map +1 -0
  148. package/dist/resources/nodeIdMapping.d.ts +5 -0
  149. package/dist/resources/nodeIdMapping.js +49 -0
  150. package/dist/resources/nodeIdMapping.js.map +1 -1
  151. package/dist/resources/recordLock.d.ts +47 -4
  152. package/dist/resources/recordLock.js +138 -7
  153. package/dist/resources/recordLock.js.map +1 -1
  154. package/dist/resources/recordLockCoordinator.d.ts +557 -0
  155. package/dist/resources/recordLockCoordinator.js +2597 -0
  156. package/dist/resources/recordLockCoordinator.js.map +1 -0
  157. package/dist/resources/replayLogs.js +5 -0
  158. package/dist/resources/replayLogs.js.map +1 -1
  159. package/dist/resources/replicatedApplyFailure.d.ts +16 -0
  160. package/dist/resources/replicatedApplyFailure.js +63 -0
  161. package/dist/resources/replicatedApplyFailure.js.map +1 -0
  162. package/dist/resources/scheduler/scheduler.js +3 -3
  163. package/dist/resources/scheduler/scheduler.js.map +1 -1
  164. package/dist/resources/search.d.ts +10 -4
  165. package/dist/resources/search.js +160 -40
  166. package/dist/resources/search.js.map +1 -1
  167. package/dist/resources/tracked.d.ts +5 -1
  168. package/dist/resources/tracked.js +74 -23
  169. package/dist/resources/tracked.js.map +1 -1
  170. package/dist/resources/transactionBroadcast.js +4 -6
  171. package/dist/resources/transactionBroadcast.js.map +1 -1
  172. package/dist/security/auth.js +59 -23
  173. package/dist/security/auth.js.map +1 -1
  174. package/dist/security/deferredAuthentication.d.ts +11 -0
  175. package/dist/security/deferredAuthentication.js +25 -3
  176. package/dist/security/deferredAuthentication.js.map +1 -1
  177. package/dist/security/jsLoader.js +9 -4
  178. package/dist/security/jsLoader.js.map +1 -1
  179. package/dist/server/REST.js +39 -5
  180. package/dist/server/REST.js.map +1 -1
  181. package/dist/server/http.d.ts +5 -1
  182. package/dist/server/http.js +34 -2
  183. package/dist/server/http.js.map +1 -1
  184. package/dist/server/mqtt.js +5 -1
  185. package/dist/server/mqtt.js.map +1 -1
  186. package/dist/server/serverHelpers/Headers.d.ts +2 -0
  187. package/dist/server/serverHelpers/Headers.js +6 -0
  188. package/dist/server/serverHelpers/Headers.js.map +1 -1
  189. package/dist/server/serverHelpers/NodeAdapterResponse.d.ts +48 -0
  190. package/dist/server/serverHelpers/NodeAdapterResponse.js +220 -0
  191. package/dist/server/serverHelpers/NodeAdapterResponse.js.map +1 -0
  192. package/dist/server/serverHelpers/Request.d.ts +5 -10
  193. package/dist/server/serverHelpers/Request.js +38 -136
  194. package/dist/server/serverHelpers/Request.js.map +1 -1
  195. package/dist/server/serverHelpers/contentTypes.d.ts +2 -0
  196. package/dist/server/serverHelpers/contentTypes.js +189 -15
  197. package/dist/server/serverHelpers/contentTypes.js.map +1 -1
  198. package/dist/server/serverHelpers/serverUtilities.d.ts +3 -3
  199. package/dist/server/serverHelpers/serverUtilities.js +110 -20
  200. package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
  201. package/dist/server/serverHelpers/uwsServer.js +4 -1
  202. package/dist/server/serverHelpers/uwsServer.js.map +1 -1
  203. package/dist/server/serverHelpers/webSocketCloseReason.d.ts +2 -0
  204. package/dist/server/serverHelpers/webSocketCloseReason.js +29 -0
  205. package/dist/server/serverHelpers/webSocketCloseReason.js.map +1 -0
  206. package/dist/server/storageReclamation.js +1 -1
  207. package/dist/server/storageReclamation.js.map +1 -1
  208. package/dist/server/threads/isolatedApplications.d.ts +47 -0
  209. package/dist/server/threads/isolatedApplications.js +171 -0
  210. package/dist/server/threads/isolatedApplications.js.map +1 -0
  211. package/dist/server/threads/logRotationTransport.d.ts +1 -0
  212. package/dist/server/threads/logRotationTransport.js +33 -0
  213. package/dist/server/threads/logRotationTransport.js.map +1 -0
  214. package/dist/server/threads/manageThreads.d.ts +64 -6
  215. package/dist/server/threads/manageThreads.js +261 -12
  216. package/dist/server/threads/manageThreads.js.map +1 -1
  217. package/dist/server/threads/socketRouter.d.ts +1 -0
  218. package/dist/server/threads/socketRouter.js +196 -13
  219. package/dist/server/threads/socketRouter.js.map +1 -1
  220. package/dist/server/threads/threadServer.js +30 -7
  221. package/dist/server/threads/threadServer.js.map +1 -1
  222. package/dist/utility/errors/hdbError.d.ts +24 -0
  223. package/dist/utility/errors/hdbError.js +58 -1
  224. package/dist/utility/errors/hdbError.js.map +1 -1
  225. package/dist/utility/hdbTerms.d.ts +2 -0
  226. package/dist/utility/hdbTerms.js +2 -0
  227. package/dist/utility/hdbTerms.js.map +1 -1
  228. package/dist/utility/logging/harper_logger.js +218 -38
  229. package/dist/utility/logging/harper_logger.js.map +1 -1
  230. package/dist/utility/logging/logGenerationCoordinator.d.ts +35 -0
  231. package/dist/utility/logging/logGenerationCoordinator.js +184 -0
  232. package/dist/utility/logging/logGenerationCoordinator.js.map +1 -0
  233. package/dist/utility/logging/logRotation.d.ts +46 -0
  234. package/dist/utility/logging/logRotation.js +365 -0
  235. package/dist/utility/logging/logRotation.js.map +1 -0
  236. package/dist/utility/logging/logRotator.d.ts +1 -1
  237. package/dist/utility/logging/logRotator.js +172 -92
  238. package/dist/utility/logging/logRotator.js.map +1 -1
  239. package/dist/utility/npmUtilities.js +6 -4
  240. package/dist/utility/npmUtilities.js.map +1 -1
  241. package/dist/utility/watcherFallback.d.ts +0 -45
  242. package/dist/utility/watcherFallback.js +1 -125
  243. package/dist/utility/watcherFallback.js.map +1 -1
  244. package/dist/validation/configValidator.js +6 -3
  245. package/dist/validation/configValidator.js.map +1 -1
  246. package/index.ts +9 -0
  247. package/json/systemSchema.json +3 -0
  248. package/npm-shrinkwrap.json +177 -87
  249. package/package.json +13 -5
  250. package/resources/DESIGN.md +689 -19
  251. package/resources/DatabaseTransaction.ts +230 -17
  252. package/resources/LMDBTransaction.ts +21 -3
  253. package/resources/PrimaryRocksDatabase.ts +20 -7
  254. package/resources/RecordEncoder.ts +52 -10
  255. package/resources/Resource.ts +97 -13
  256. package/resources/ResourceInterface.ts +8 -0
  257. package/resources/RocksIndexStore.ts +2 -1
  258. package/resources/RocksTransactionLogStore.ts +111 -31
  259. package/resources/Table.ts +1273 -396
  260. package/resources/analytics/DESIGN.md +38 -0
  261. package/resources/analytics/write.ts +50 -17
  262. package/resources/auditStore.ts +460 -11
  263. package/resources/crdt.ts +22 -0
  264. package/resources/dataLoader.ts +3 -4
  265. package/resources/databases.ts +611 -147
  266. package/resources/derivedIndexRegistry.ts +56 -0
  267. package/resources/derivedIndexRuntime.ts +2292 -0
  268. package/resources/graphql.ts +3 -2
  269. package/resources/indexes/DESIGN.md +833 -0
  270. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +924 -46
  271. package/resources/indexes/fullTextDerivedIndex.ts +1165 -0
  272. package/resources/indexes/fullTextNativeBinding.ts +146 -0
  273. package/resources/indexes/hnswDerivedIndex.ts +531 -0
  274. package/resources/indexes/hnswPlaneBinding.ts +174 -0
  275. package/resources/indexes/nativeFullTextDerivedIndexLifecycle.ts +181 -0
  276. package/resources/nodeIdMapping.ts +50 -0
  277. package/resources/record-locks.md +1407 -0
  278. package/resources/recordLock.ts +173 -7
  279. package/resources/recordLockCoordinator.ts +3082 -0
  280. package/resources/replayLogs.ts +5 -0
  281. package/resources/replicatedApplyFailure.ts +77 -0
  282. package/resources/scheduler/DESIGN.md +40 -0
  283. package/resources/scheduler/scheduler.ts +4 -4
  284. package/resources/search.ts +169 -49
  285. package/resources/tracked.ts +73 -22
  286. package/resources/transactionBroadcast.ts +4 -4
  287. package/security/DESIGN.md +175 -0
  288. package/security/auth.ts +53 -24
  289. package/security/deferredAuthentication.ts +24 -2
  290. package/security/jsLoader.ts +9 -4
  291. package/server/DESIGN.md +275 -0
  292. package/server/REST.ts +42 -6
  293. package/server/http.ts +34 -2
  294. package/server/mqtt.ts +6 -4
  295. package/server/serverHelpers/Headers.ts +5 -1
  296. package/server/serverHelpers/NodeAdapterResponse.ts +221 -0
  297. package/server/serverHelpers/Request.ts +33 -131
  298. package/server/serverHelpers/contentTypes.ts +188 -15
  299. package/server/serverHelpers/serverUtilities.ts +157 -27
  300. package/server/serverHelpers/uwsServer.ts +4 -1
  301. package/server/serverHelpers/webSocketCloseReason.ts +25 -0
  302. package/server/storageReclamation.ts +2 -2
  303. package/server/threads/isolatedApplications.ts +157 -0
  304. package/server/threads/logRotationTransport.ts +40 -0
  305. package/server/threads/manageThreads.js +254 -12
  306. package/server/threads/socketRouter.ts +217 -11
  307. package/server/threads/threadServer.js +30 -7
  308. package/studio/web/assets/{Chat-BnCBegQz.js → Chat-DADFFGe_.js} +1 -1
  309. package/studio/web/assets/{FloatingChat-CoDW1ySS.js → FloatingChat-D_mI-rZ7.js} +3 -3
  310. package/studio/web/assets/{apiToken-Bwk5BLXW.js → apiToken-c2NiSDHa.js} +1 -1
  311. package/studio/web/assets/{applications-DHxGi7JH.js → applications-DktUqh7G.js} +1 -1
  312. package/studio/web/assets/{cssMode-s0cWI-_M.js → cssMode-Cs_75Xhw.js} +1 -1
  313. package/studio/web/assets/{editor-DNcRHK54.js → editor-19b-Y1IN.js} +1 -1
  314. package/studio/web/assets/{html-Bdssedlg.js → html-DiYEQMpB.js} +1 -1
  315. package/studio/web/assets/{htmlMode-CoDlJ3fw.js → htmlMode-CmR0y7P_.js} +1 -1
  316. package/studio/web/assets/{index-D6sxmFLR.js → index-Dm0rfkJ7.js} +5 -5
  317. package/studio/web/assets/{index.lazy-tmU5BS8s.js → index.lazy-7vqt2CC3.js} +1 -1
  318. package/studio/web/assets/{javascript-B8meVSTH.js → javascript-BWtCFuOt.js} +1 -1
  319. package/studio/web/assets/{jsonMode-DpIPd35T.js → jsonMode-Buzzbv9y.js} +1 -1
  320. package/studio/web/assets/{languageServices-C_5FMJzQ.js → languageServices-SqsFWfTM.js} +1 -1
  321. package/studio/web/assets/{lspLanguageFeatures-BIzNBzPK.js → lspLanguageFeatures-EMV5cmjo.js} +1 -1
  322. package/studio/web/assets/{notifications-CvZivSbh.js → notifications-CAB-LZWT.js} +1 -1
  323. package/studio/web/assets/{notifications-CQf18QKb.js → notifications-DRzmSRxM.js} +1 -1
  324. package/studio/web/assets/{profile-DdOwtntb.js → profile-BNKAl79n.js} +1 -1
  325. package/studio/web/assets/{regions-n69fwagr.js → regions-CUow_Zw2.js} +1 -1
  326. package/studio/web/assets/{register-PfWTCXWB.js → register-Dkt3WUMp.js} +2 -2
  327. package/studio/web/assets/{setComponentFile-Bg6O7X0S.js → setComponentFile-BZRfMD0N.js} +1 -1
  328. package/studio/web/assets/{setup-CUx_aUDl.js → setup-D_yiEPO2.js} +2 -2
  329. package/studio/web/assets/{status-D7BVKqX9.js → status-DhHh1Ge-.js} +1 -1
  330. package/studio/web/assets/{toggleHighContrast-DBSyXzMr.js → toggleHighContrast-D7L1PDtV.js} +1 -1
  331. package/studio/web/assets/{tsMode-BByKCjBS.js → tsMode-CCwLk1YS.js} +1 -1
  332. package/studio/web/assets/{typescript-DDLnLpw9.js → typescript-BP1j1mjn.js} +1 -1
  333. package/studio/web/assets/{useEntityRestURL-31CHGaHk.js → useEntityRestURL-D7bnYxLw.js} +1 -1
  334. package/studio/web/assets/{workers-pR3jRY9D.js → workers-tOuCNT17.js} +1 -1
  335. package/studio/web/assets/{xml-2iRnMhQO.js → xml-BSG_3mQT.js} +1 -1
  336. package/studio/web/assets/{yaml-Bf92gJpd.js → yaml-DxiLprBB.js} +1 -1
  337. package/studio/web/index.html +1 -1
  338. package/utility/DESIGN.md +55 -0
  339. package/utility/errors/hdbError.ts +54 -0
  340. package/utility/hdbTerms.ts +2 -0
  341. package/utility/logging/harper_logger.ts +210 -30
  342. package/utility/logging/logGenerationCoordinator.ts +196 -0
  343. package/utility/logging/logRotation.ts +367 -0
  344. package/utility/logging/logRotator.ts +196 -91
  345. package/utility/npmUtilities.ts +6 -4
  346. package/utility/watcherFallback.ts +0 -122
  347. package/validation/configValidator.ts +6 -3
@@ -64,10 +64,12 @@ let threadTerminationTimeout = process.env.DEV_MODE === 'true' || process.env.DE
64
64
  const RESTART_TYPE = 'restart';
65
65
  const RESTART_PROGRESS_HEARTBEAT_MS = 15000;
66
66
  const REQUEST_THREAD_INFO = 'request_thread_info';
67
+ const REQUEST_RUNNING_ISOLATED_APPLICATIONS = 'request-running-isolated-applications';
67
68
  const RESOURCE_REPORT = 'resource_report';
68
69
  const OS_THREAD_ID = 'os-thread-id';
69
70
  const STUCK_WORKER_REPORT = 'stuck-worker-report';
70
71
  const THREAD_INFO = 'thread_info';
72
+ const RUNNING_ISOLATED_APPLICATIONS = 'running-isolated-applications';
71
73
  const ADDED_PORT = 'added-port';
72
74
  const ACKNOWLEDGEMENT = 'ack';
73
75
  const REMOVE_PORT = 'remove-port';
@@ -85,6 +87,7 @@ const AWAIT_PROCESS_GROUP_TERMINATION = 'await-process-group-termination';
85
87
  const PROCESS_GROUP_TERMINATION_CONFIRMED = 'process-group-termination-confirmed';
86
88
  const THREAD_INFO_REQUEST_TIMEOUT_MS = 1000;
87
89
  let getThreadInfo;
90
+ let getRunningIsolatedApplications;
88
91
  let awaitProcessGroupTermination;
89
92
  // Worker-side backstop that force-exits if the graceful shutdown sequence doesn't finish in time.
90
93
  let selfExitTimer;
@@ -151,6 +154,19 @@ module.exports = {
151
154
  workers,
152
155
  setMonitorListener,
153
156
  onMessageFromWorkers,
157
+ setIsolatedWorkerReconciler,
158
+ setRunningIsolatedApplicationsGetter,
159
+ isApplicationPrimaryWorker,
160
+ applicationWorkerIndex,
161
+ runsApplicationCodeSingletons,
162
+ isDedicatedWorker,
163
+ markBranchStorePath,
164
+ ownsStoreMaintenance,
165
+ ownsStoreExpiration,
166
+ workersForApplication,
167
+ stopWorker,
168
+ encodeRestartScope,
169
+ decodeRestartScope,
154
170
  onMessageByType,
155
171
  broadcast,
156
172
  broadcastWithAcknowledgement,
@@ -173,6 +189,11 @@ module.exports = {
173
189
  isThreadRunning,
174
190
  waitUntilConfirmedGone,
175
191
  restartNumber: workerData?.restartNumber || 1,
192
+ // Identifies this process incarnation, where the PID cannot: a container reuses PID 1. Minted once
193
+ // on the main thread and carried to workers, so live siblings agree on it — one derived per thread
194
+ // would not. `undefined` on a worker started without it; consumers must fall back, not treat that
195
+ // as a mismatch.
196
+ processIncarnation: workerData ? workerData.processIncarnation : randomBytes(8).toString('hex'),
176
197
  };
177
198
 
178
199
  connectedPorts.onMessageByType = onMessageByType;
@@ -191,6 +212,9 @@ connectedPorts.sendToThread = function (threadId, message) {
191
212
  throw err;
192
213
  }
193
214
  };
215
+ // Direct thread-to-thread send, so a worker can reach a sibling (e.g. the record lock owner worker)
216
+ // without a hop through main. Returns false when no port for the thread is connected.
217
+ module.exports.sendToThread = connectedPorts.sendToThread;
194
218
  module.exports.whenThreadsStarted = new Promise((resolve) => {
195
219
  module.exports.threadsHaveStarted = resolve;
196
220
  });
@@ -206,6 +230,101 @@ function setTerminateTimeout(newTimeout) {
206
230
  function getWorkerIndex() {
207
231
  return workerData ? workerData.workerIndex : isMainWorker ? 0 : undefined;
208
232
  }
233
+ /**
234
+ * The worker that owns `applicationName`'s per-application singletons (its scheduled jobs, its data
235
+ * files): pool worker 0 for a shared application and for root-level plugins (which pass no name), the
236
+ * dedicated worker for an isolated one -- never index 0, so node-wide duties stay on the pool, and
237
+ * never a dedicated worker for anything but its own application.
238
+ */
239
+ function isApplicationPrimaryWorker(applicationName) {
240
+ if (workerData?.isolatedApplication !== undefined) return applicationName === workerData.isolatedApplication;
241
+ return getWorkerIndex() === 0;
242
+ }
243
+ /**
244
+ * Stores that exist only on this thread: the branch stores an isolated application opened in its
245
+ * dedicated worker. Registered by openBranchDatabase, so the ownership predicates below can tell them
246
+ * from the shared stores every thread has open.
247
+ */
248
+ const branchStorePaths = new Set();
249
+ function markBranchStorePath(path, isBranch = true) {
250
+ if (isBranch) branchStorePaths.add(path);
251
+ else branchStorePaths.delete(path);
252
+ }
253
+ /**
254
+ * Whether this thread runs the "last worker" per-store maintenance for `storePath` (TTL scans, storage
255
+ * reclamation, audit cleanup). Shared stores belong to the last pool worker; a dedicated worker
256
+ * maintains only its own branch stores, which no other thread has open.
257
+ */
258
+ function ownsStoreMaintenance(storePath) {
259
+ if (workerData?.isolatedApplication !== undefined) return branchStorePaths.has(storePath);
260
+ return getWorkerIndex() === getWorkerCount() - 1;
261
+ }
262
+ /** The "worker 0" counterpart: expiration eviction for `storePath`. */
263
+ function ownsStoreExpiration(storePath) {
264
+ if (workerData?.isolatedApplication !== undefined) return branchStorePaths.has(storePath);
265
+ return getWorkerIndex() === 0;
266
+ }
267
+ /**
268
+ * Whether a singleton set up by APPLICATION CODE runs here (a caching table's `sourcedFrom`
269
+ * subscription): pool worker 0, or a dedicated worker -- the only code that runs on one is its own
270
+ * application's, so whatever it sets up is that application's to run. Not for root-level plugins,
271
+ * which load on every thread and must use isApplicationPrimaryWorker(name).
272
+ */
273
+ function runsApplicationCodeSingletons() {
274
+ return getWorkerIndex() === 0 || workerData?.isolatedApplication !== undefined;
275
+ }
276
+ /** Whether this thread is a worker dedicated to one isolated application. */
277
+ function isDedicatedWorker() {
278
+ return workerData?.isolatedApplication !== undefined;
279
+ }
280
+ /** The worker index as the application sees it: a dedicated worker is its application's worker 0. */
281
+ function applicationWorkerIndex() {
282
+ return workerData?.isolatedApplication !== undefined ? 0 : getWorkerIndex();
283
+ }
284
+ /** Every started worker dedicated to `application`, including a replacement still booting. */
285
+ function workersForApplication(application) {
286
+ return workers.filter((worker) => worker.application === application);
287
+ }
288
+ /**
289
+ * Stop one worker for good: shut it down, honour the drain extension it may ask for, force it after
290
+ * the same backstop the rolling restart uses (FORCE_EXIT on Bun, where terminate() segfaults), and
291
+ * resolve once it has exited. Marked as shut down first so its exit does not start a replacement.
292
+ */
293
+ function stopWorker(worker) {
294
+ worker.wasShutdown = true;
295
+ return new Promise((resolve) => {
296
+ const armTerminate = (delay) =>
297
+ setTimeout(() => {
298
+ harperLogger.warn('Thread did not voluntarily terminate, terminating from the outside', worker.threadId);
299
+ if (isBun) {
300
+ try {
301
+ worker.postMessage({ type: FORCE_EXIT });
302
+ } catch {}
303
+ } else {
304
+ worker.terminate();
305
+ }
306
+ }, delay).unref();
307
+ let timeout = armTerminate(threadTerminationTimeout * 2);
308
+ worker.extendTerminateDeadline = (deadlineMs) => {
309
+ clearTimeout(timeout);
310
+ const { boundedTerminateDelay, getShutdownDrainCeilingMs } = require('../../components/shutdownDrain.ts');
311
+ timeout = armTerminate(
312
+ boundedTerminateDelay(deadlineMs, Date.now(), threadTerminationTimeout * 2, getShutdownDrainCeilingMs())
313
+ );
314
+ };
315
+ worker.on('exit', () => {
316
+ clearTimeout(timeout);
317
+ worker.extendTerminateDeadline = undefined;
318
+ resolve();
319
+ });
320
+ try {
321
+ worker.postMessage({ restartNumber: module.exports.restartNumber, type: hdbTerms.ITC_EVENT_TYPES.SHUTDOWN });
322
+ } catch {
323
+ clearTimeout(timeout);
324
+ resolve(); // already gone
325
+ }
326
+ });
327
+ }
209
328
  function getWorkerCount() {
210
329
  return workerData ? workerData.workerCount : isMainWorker ? 1 : undefined;
211
330
  }
@@ -239,8 +358,10 @@ const RESERVED_WORKER_DATA_KEYS = [
239
358
  'workerCount',
240
359
  'name',
241
360
  'restartNumber',
361
+ 'processIncarnation',
242
362
  'ticketKeys',
243
363
  'noServerStart',
364
+ 'isolatedApplication',
244
365
  '__proto__', // never a legitimate payload name; spread would define it as an own property
245
366
  ];
246
367
  const workerDataProviders = new Map();
@@ -294,20 +415,31 @@ function getTicketKeys() {
294
415
  ticketKeys = isMainThread ? randomBytes(48) : workerData.ticketKeys;
295
416
  return ticketKeys;
296
417
  }
418
+ // What application code sees: a dedicated worker is its application's only worker, index 0 of 1, so
419
+ // the documented partitioning idiom (`hash % server.workerCount === server.workerIndex`) covers
420
+ // everything there. Node-wide duties keep using the raw getWorkerIndex/getWorkerCount.
297
421
  Object.defineProperty(server, 'workerIndex', {
298
422
  get() {
299
- return getWorkerIndex();
423
+ return applicationWorkerIndex();
300
424
  },
301
425
  });
302
426
  Object.defineProperty(server, 'workerCount', {
303
427
  get() {
304
- return getWorkerCount();
428
+ return workerData?.isolatedApplication !== undefined ? 1 : getWorkerCount();
305
429
  },
306
430
  });
307
431
  if (!parentPort) {
308
432
  onMessageByType(REQUEST_THREAD_INFO, (message, worker) => {
309
433
  if (worker) sendThreadInfo(worker);
310
434
  });
435
+ onMessageByType(REQUEST_RUNNING_ISOLATED_APPLICATIONS, (message, worker) => {
436
+ if (worker)
437
+ worker.postMessage({
438
+ type: RUNNING_ISOLATED_APPLICATIONS,
439
+ requestId: message.requestId,
440
+ applications: runningIsolatedApplicationsGetter(),
441
+ });
442
+ });
311
443
  onMessageByType(RESOURCE_REPORT, (message, worker) => {
312
444
  if (worker) recordResourceReport(worker, message);
313
445
  });
@@ -342,11 +474,12 @@ listenersByType.set(hdbTerms.ITC_EVENT_TYPES.MIDDLEWARE_CHAINS_RESPONSE, null);
342
474
  listenersByType.set(hdbTerms.ITC_EVENT_TYPES.OPERATION_REGISTERED, null);
343
475
  listenersByType.set(hdbTerms.ITC_EVENT_TYPES.OPERATION_EXECUTE_REQUEST, null);
344
476
  listenersByType.set(hdbTerms.ITC_EVENT_TYPES.OPERATION_EXECUTE_RESPONSE, null);
345
- // getThreadInfo/awaitProcessGroupTermination register their own one-shot parentPort listener per
477
+ // These request/response functions register their own one-shot parentPort listener per
346
478
  // call rather than going through onMessageByType, so without this, every reply would also reach
347
479
  // addPort's permanent dispatcher as an "unregistered" type: notifyMessageListeners would warn and
348
480
  // queue each one in messagesQueuedByType forever, and a lock-wait polls every 50ms.
349
481
  listenersByType.set(THREAD_INFO, null);
482
+ listenersByType.set(RUNNING_ISOLATED_APPLICATIONS, null);
350
483
  listenersByType.set(PROCESS_GROUP_TERMINATION_CONFIRMED, null);
351
484
 
352
485
  function startWorker(path, options = {}) {
@@ -370,7 +503,7 @@ function startWorker(path, options = {}) {
370
503
  availableMemory = Math.min(availableMemory, totalmem(), 20000 * MB);
371
504
  const maxOldMemory =
372
505
  resolveThreadHeapMemoryMb(envMgr.get(hdbTerms.CONFIG_PARAMS.THREADS_MAXHEAPMEMORY)) ??
373
- Math.max(Math.floor(availableMemory / MB / (10 + (options.threadCount || 1) / 4)), 512);
506
+ Math.max(Math.floor(availableMemory / MB / (10 + (options.heapShareCount || options.threadCount || 1) / 4)), 512);
374
507
  // Max young memory space (semi-space for scavenger) is 1/128 of max memory (limited to 16-64). For most of our m5
375
508
  // machines this will be 64MB (less for t3's). This is based on recommendations from:
376
509
  // https://www.alibabacloud.com/blog/node-js-application-troubleshooting-manual---comprehensive-gc-problems-and-optimization594965
@@ -416,6 +549,9 @@ function startWorker(path, options = {}) {
416
549
  for (const requirePath of getRequireModules()) execArgv.push('--require', requirePath);
417
550
  }
418
551
 
552
+ // Only a start that declares the serving topology may write it; see DESIGN.md on the two workerCounts.
553
+ if (typeof options.threadCount === 'number') workerCount = options.threadCount;
554
+
419
555
  const worker = new Worker(isAbsolute(path) ? path : join(PACKAGE_ROOT, path), {
420
556
  resourceLimits: {
421
557
  maxOldGenerationSizeMb: maxOldMemory,
@@ -430,9 +566,11 @@ function startWorker(path, options = {}) {
430
566
  addThreadIds: channelsToConnect.map((channel) => channel.existingPort.threadId),
431
567
  addPortIsJobWorkers: channelsToConnect.map((channel) => channel.existingPort.isJobWorker === true),
432
568
  workerIndex: options.workerIndex,
433
- workerCount: (workerCount = options.threadCount),
569
+ workerCount: options.threadCount,
434
570
  name: options.name,
571
+ isolatedApplication: options.application,
435
572
  restartNumber: module.exports.restartNumber,
573
+ processIncarnation: module.exports.processIncarnation,
436
574
  ticketKeys: getTicketKeys(),
437
575
  },
438
576
  transferList: portsToSend,
@@ -466,7 +604,12 @@ function startWorker(path, options = {}) {
466
604
  });
467
605
  worker.on('exit', (_code) => {
468
606
  workers.splice(workers.indexOf(worker), 1);
469
- if (!processShuttingDown && !worker.wasShutdown && options.autoRestart !== false) {
607
+ if (
608
+ !processShuttingDown &&
609
+ !worker.wasShutdown &&
610
+ options.autoRestart !== false &&
611
+ options.shouldAutoRestart?.(worker) !== false
612
+ ) {
470
613
  // if this wasn't an intentional shutdown, restart now (unless we have tried too many times)
471
614
  if (worker.unexpectedRestarts < MAX_UNEXPECTED_RESTARTS) {
472
615
  options.unexpectedRestarts = worker.unexpectedRestarts + 1;
@@ -481,6 +624,7 @@ function startWorker(path, options = {}) {
481
624
  startMonitoring();
482
625
  if (options.onStarted) options.onStarted(worker); // notify that it is ready
483
626
  worker.name = options.name;
627
+ worker.application = options.application; // the isolated application this worker is dedicated to, if any
484
628
  return worker;
485
629
  }
486
630
 
@@ -502,12 +646,19 @@ const OVERLAPPING_RESTART_TYPES = [hdbTerms.THREAD_TYPES.HTTP];
502
646
  * from a worker, nothing — the restart is handed to the main thread.
503
647
  */
504
648
 
649
+ /**
650
+ * `application` selects which workers of the type restart: omitted preserves the historic all-worker
651
+ * behavior, explicit undefined restarts the shared pool only, a name restarts only that application's
652
+ * dedicated worker, and '*' restarts all.
653
+ */
505
654
  async function restartWorkers(
506
655
  name = null,
507
656
  maxWorkersDown = Math.max(Math.floor(workerCount / 8), 1), // restart 1/8 of the threads at a time, but at least 1
508
657
  startReplacementThreads = true,
509
- onProgress = null
658
+ onProgress = null,
659
+ application = undefined
510
660
  ) {
661
+ if (arguments.length < 5) application = '*';
511
662
  if (isMainThread) {
512
663
  // Declining is not the same as delegating: a caller reporting on the restart must not read this
513
664
  // as "another thread is completing it".
@@ -520,9 +671,19 @@ async function restartWorkers(
520
671
  } catch (e) {
521
672
  harperLogger.error('Unable to reestablish current working directory', e);
522
673
  }
674
+ const freshlyStarted = new Set(); // dedicated workers the reconcile just started: already on the new code
523
675
  // problematic cyclic dependency, bind late
524
676
  const { resetRestartNeeded } = require('../../components/requestRestart.ts');
525
- resetRestartNeeded();
677
+ // One process-wide bit cannot say WHICH application is pending, so it may only be cleared by a
678
+ // restart that demonstrably covers every worker the bit could stand for. A restart scoped to one
679
+ // application leaves the whole pool on its old code; a pool restart replaces every pool worker and
680
+ // reconciles dedicated slots, but leaves an already-running dedicated worker on its old modules.
681
+ // Clearing from either would report restartRequired: false while a deployed component is still
682
+ // loaded nowhere. So: all workers always, the pool only while no dedicated worker is running --
683
+ // which is every node that uses no isolated application, i.e. the historic behavior unchanged.
684
+ const coversEveryWorker =
685
+ application === '*' || (application === undefined && !workers.some((worker) => worker.application));
686
+ if (coversEveryWorker) resetRestartNeeded();
526
687
  // This is here to prevent circular dependencies
527
688
  if (startReplacementThreads) {
528
689
  const { loadRootComponents } = require('../loadRootComponents.js');
@@ -532,6 +693,13 @@ async function restartWorkers(
532
693
  const loading = setInterval(() => onProgress?.(), RESTART_PROGRESS_HEARTBEAT_MS).unref();
533
694
  try {
534
695
  await loadRootComponents();
696
+ // isolated applications added or removed by the reload get their dedicated worker started or
697
+ // stopped; a crash-looping newcomer can take a while, so the heartbeat runs through this too
698
+ try {
699
+ for (const application of (await isolatedWorkerReconciler?.()) ?? []) freshlyStarted.add(application);
700
+ } catch (error) {
701
+ harperLogger.error('Could not reconcile isolated application workers', error);
702
+ }
535
703
  } finally {
536
704
  clearInterval(loading);
537
705
  }
@@ -539,7 +707,10 @@ async function restartWorkers(
539
707
  }
540
708
 
541
709
  module.exports.restartNumber++;
542
- if (maxWorkersDown < 1) {
710
+ // `Infinity` is shutdownWorkers' "all at once" sentinel and must survive.
711
+ if (typeof maxWorkersDown !== 'number' || Number.isNaN(maxWorkersDown)) {
712
+ maxWorkersDown = 1;
713
+ } else if (maxWorkersDown < 1) {
543
714
  // we accept a ratio of workers, and compute absolute maximum being down at a time from the total number of
544
715
  // threads
545
716
  maxWorkersDown = maxWorkersDown * workers.length;
@@ -566,14 +737,17 @@ async function restartWorkers(
566
737
  // replacement — an unavoidable brief gap, but only for worker-owned listeners, since the main
567
738
  // thread keeps serving the HTTP ports throughout. This ordering is also what lets
568
739
  // listenOnPorts() treat a dedicated listener's EADDRINUSE as an external conflict.
569
- const canPreStartReplacement = process.platform !== 'win32' && process.platform !== 'darwin' && !isBun;
740
+ const platformCanPreStartReplacement = process.platform !== 'win32' && process.platform !== 'darwin' && !isBun;
570
741
  const restarting = workers.slice(0);
571
742
  for (let index = 0; index < restarting.length; index++) {
572
743
  const worker = restarting[index];
573
744
  // Terminal shutdown: stop replacing workers mid-loop — the guard for every replacement start below.
574
745
  if (processShuttingDown && startReplacementThreads) break;
575
746
  if ((name && worker.name !== name) || worker.wasShutdown) continue; // filter by type, if specified
747
+ if (application !== '*' && worker.application !== application) continue; // and by isolated application
748
+ if (worker.application && freshlyStarted.has(worker.application)) continue;
576
749
  const overlapping = OVERLAPPING_RESTART_TYPES.indexOf(worker.name) > -1;
750
+ const canPreStartReplacement = platformCanPreStartReplacement && !worker.application;
577
751
  if (overlapping && startReplacementThreads && canPreStartReplacement) {
578
752
  // Overlapping restart: start the replacement and wait until it is accepting connections
579
753
  // *before* shutting down the worker it replaces. The replacement joins the (SO_REUSEPORT)
@@ -754,6 +928,7 @@ async function restartWorkers(
754
928
  parentPort.postMessage({
755
929
  type: RESTART_TYPE,
756
930
  workerType: name,
931
+ scope: encodeRestartScope(application),
757
932
  });
758
933
  }
759
934
  }
@@ -803,7 +978,7 @@ function whenWorkerStarted(newWorker) {
803
978
  });
804
979
  }
805
980
  function shutdownWorkers(name) {
806
- return restartWorkers(name, Infinity, false);
981
+ return restartWorkers(name, Infinity, false, null, '*');
807
982
  }
808
983
  function beginProcessShutdown() {
809
984
  processShuttingDown = true;
@@ -823,6 +998,28 @@ async function shutdownWorkersNow(name) {
823
998
  }
824
999
  }
825
1000
 
1001
+ /**
1002
+ * The restart scope on the wire: a worker cannot post `undefined` and have it mean "the pool" (a
1003
+ * message with no scope at all means "everything", as every pre-existing sender intends).
1004
+ */
1005
+ function encodeRestartScope(application) {
1006
+ return application === undefined ? '' : application; // '' is not a legal application name
1007
+ }
1008
+ function decodeRestartScope(message) {
1009
+ if (message.scope === undefined) return '*';
1010
+ return message.scope === '' ? undefined : message.scope;
1011
+ }
1012
+
1013
+ let isolatedWorkerReconciler = null;
1014
+ let runningIsolatedApplicationsGetter = () => [];
1015
+ /** Registered by socketRouter: starts and stops dedicated workers to match the root config's isolated applications. */
1016
+ function setIsolatedWorkerReconciler(reconcile) {
1017
+ isolatedWorkerReconciler = reconcile;
1018
+ }
1019
+ function setRunningIsolatedApplicationsGetter(getter) {
1020
+ runningIsolatedApplicationsGetter = getter;
1021
+ }
1022
+
826
1023
  const messageListeners = [];
827
1024
  function onMessageFromWorkers(listener) {
828
1025
  messageListeners.push(listener);
@@ -1089,6 +1286,7 @@ function getChildWorkerInfo() {
1089
1286
  return workers.map((worker) => ({
1090
1287
  threadId: worker.threadId,
1091
1288
  name: worker.name,
1289
+ application: worker.application,
1092
1290
  heapTotal: worker.resources?.heapTotal,
1093
1291
  heapUsed: worker.resources?.heapUsed,
1094
1292
  externalMemory: worker.resources?.external,
@@ -1198,6 +1396,38 @@ if (parentPort && workerData?.addPorts) {
1198
1396
  }, timeoutMs);
1199
1397
  }
1200
1398
  });
1399
+ let nextRunningIsolatedApplicationsRequestId = 0;
1400
+ getRunningIsolatedApplications = (timeoutMs) =>
1401
+ new Promise((resolve, reject) => {
1402
+ const requestId = ++nextRunningIsolatedApplicationsRequestId;
1403
+ let timeout;
1404
+ parentPort.on('message', receiveApplications);
1405
+ try {
1406
+ parentPort.postMessage({ type: REQUEST_RUNNING_ISOLATED_APPLICATIONS, requestId });
1407
+ } catch (error) {
1408
+ cleanup();
1409
+ reject(error);
1410
+ return;
1411
+ }
1412
+ function receiveApplications(message) {
1413
+ if (message.type === RUNNING_ISOLATED_APPLICATIONS && message.requestId === requestId) {
1414
+ cleanup();
1415
+ resolve(message.applications);
1416
+ }
1417
+ }
1418
+ function cleanup() {
1419
+ if (timeout) clearTimeout(timeout);
1420
+ parentPort.off('message', receiveApplications);
1421
+ }
1422
+ if (timeoutMs != null) {
1423
+ timeout = setTimeout(() => {
1424
+ cleanup();
1425
+ const error = new Error(`Timed out waiting for isolated application topology after ${timeoutMs}ms`);
1426
+ error.code = 'ERR_ISOLATED_APPLICATIONS_TIMEOUT';
1427
+ reject(error);
1428
+ }, timeoutMs);
1429
+ }
1430
+ });
1201
1431
  let awaitTerminationRequestId = 0;
1202
1432
  awaitProcessGroupTermination = (ownerThreadId, signal) =>
1203
1433
  new Promise((resolve) => {
@@ -1222,10 +1452,18 @@ if (parentPort && workerData?.addPorts) {
1222
1452
  });
1223
1453
  } else {
1224
1454
  getThreadInfo = getChildWorkerInfo;
1455
+ getRunningIsolatedApplications = isMainThread
1456
+ ? () => runningIsolatedApplicationsGetter()
1457
+ : () => {
1458
+ const error = new Error('No channel to the main thread for isolated application topology');
1459
+ error.code = 'ERR_ISOLATED_APPLICATIONS_UNAVAILABLE';
1460
+ return Promise.reject(error);
1461
+ };
1225
1462
  awaitProcessGroupTermination = (ownerThreadId) =>
1226
1463
  pendingProcessGroupTerminations.get(ownerThreadId) ?? Promise.resolve();
1227
1464
  }
1228
1465
  module.exports.getThreadInfo = getThreadInfo;
1466
+ module.exports.getRunningIsolatedApplications = getRunningIsolatedApplications;
1229
1467
 
1230
1468
  // Listeners notified when a connected thread's port closes (worker exit/restart), so
1231
1469
  // modules holding per-thread state (e.g. registeredOperations' registry and in-flight
@@ -1720,7 +1958,7 @@ if (isMainThread) {
1720
1958
  if (queuedRestart) clearTimeout(queuedRestart);
1721
1959
  queuedRestart = setTimeout(async () => {
1722
1960
  if (beforeRestart) await beforeRestart();
1723
- await restartWorkers();
1961
+ await restartWorkers(undefined, undefined, true, null, '*');
1724
1962
  console.log('Reloaded Harper components, changed files:', Array.from(changedFiles));
1725
1963
  changedFiles.clear();
1726
1964
  }, 100);
@@ -1742,3 +1980,7 @@ if (isMainThread) {
1742
1980
  realExit(0);
1743
1981
  });
1744
1982
  }
1983
+
1984
+ // Required here, not from logging, which must never import this module; last in the file because it
1985
+ // calls onThreadExit.
1986
+ require('./logRotationTransport.ts');