@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
@@ -0,0 +1,24 @@
1
+ import { FullTextDerivedIndexBackend, type FullTextDerivedIndexBackendOptions, type FullTextDerivedIndexEngine, type FullTextDerivedIndexInspection } from './fullTextDerivedIndex.ts';
2
+ import { type NativeFullTextIndexConfiguration, type NativeFullTextModule } from './fullTextNativeBinding.ts';
3
+ export type NativeFullTextDerivedIndexLifecycleOptions = NativeFullTextIndexConfiguration & {
4
+ storePath: string;
5
+ storeName: string;
6
+ indexId: string;
7
+ sourceGeneration: string;
8
+ binding?: NativeFullTextModule | (() => Promise<NativeFullTextModule>);
9
+ };
10
+ export type NativeFullTextDerivedIndexBackendOptions = Omit<FullTextDerivedIndexBackendOptions, 'lifecycle'> & Omit<NativeFullTextDerivedIndexLifecycleOptions, 'indexId'>;
11
+ export declare class NativeFullTextDerivedIndexLifecycle {
12
+ #private;
13
+ constructor(options: NativeFullTextDerivedIndexLifecycleOptions);
14
+ get path(): string;
15
+ initialize(options?: {
16
+ reclaimRetired?: boolean;
17
+ }): Promise<void>;
18
+ startRetiredStorageReclamation(): void;
19
+ get maxCommitPayloadBytes(): number;
20
+ inspect(): FullTextDerivedIndexInspection;
21
+ open(): Promise<FullTextDerivedIndexEngine>;
22
+ reset(): Promise<void>;
23
+ }
24
+ export declare function createNativeFullTextDerivedIndexBackend(options: NativeFullTextDerivedIndexBackendOptions): Promise<FullTextDerivedIndexBackend>;
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NativeFullTextDerivedIndexLifecycle = void 0;
4
+ exports.createNativeFullTextDerivedIndexBackend = createNativeFullTextDerivedIndexBackend;
5
+ const node_crypto_1 = require("node:crypto");
6
+ const node_path_1 = require("node:path");
7
+ const logger_ts_1 = require("../../utility/logging/logger.js");
8
+ const fullTextDerivedIndex_ts_1 = require("./fullTextDerivedIndex.js");
9
+ const fullTextNativeBinding_ts_1 = require("./fullTextNativeBinding.js");
10
+ const logger = (0, logger_ts_1.loggerWithTag)('fulltext-derived-index');
11
+ class NativeFullTextDerivedIndexLifecycle {
12
+ #options;
13
+ #path;
14
+ #generation;
15
+ #binding;
16
+ #maxCommitPayloadBytes;
17
+ #reclaimOperation = Promise.resolve();
18
+ constructor(options) {
19
+ if (!(0, node_path_1.isAbsolute)(options.storePath))
20
+ throw new TypeError('Full-text storePath must be absolute');
21
+ if (!options.storeName)
22
+ throw new TypeError('Full-text storeName is required');
23
+ if (!options.indexId)
24
+ throw new TypeError('Full-text indexId is required');
25
+ if (!options.sourceGeneration)
26
+ throw new TypeError('Full-text sourceGeneration is required');
27
+ this.#options = {
28
+ ...options,
29
+ fields: options.fields.map((field) => ({ ...field })),
30
+ limits: { ...options.limits },
31
+ };
32
+ // Hashing bounds filenames for arbitrary store names; the index id remains in native metadata and logs.
33
+ this.#path = (0, node_path_1.join)((0, node_path_1.resolve)(options.storePath), `${digest(options.storeName)}.fulltext`);
34
+ this.#generation = digest(options.sourceGeneration);
35
+ }
36
+ get path() {
37
+ return this.#path;
38
+ }
39
+ async initialize(options = {}) {
40
+ const binding = await this.#getBinding();
41
+ binding.validateNativeFullTextIndexOptions({
42
+ ...this.#nativeOptions(),
43
+ limits: this.#options.limits,
44
+ });
45
+ this.#maxCommitPayloadBytes = (0, fullTextNativeBinding_ts_1.getValidatedFullTextRuntimeInfo)(binding).limits.maxCommitPayloadBytes;
46
+ if (options.reclaimRetired !== false)
47
+ this.#queueReclaimRetired();
48
+ }
49
+ startRetiredStorageReclamation() {
50
+ this.#requireBinding();
51
+ // Fulltext publishes unique retired paths and removes them with force, so workers may sweep concurrently.
52
+ this.#queueReclaimRetired();
53
+ }
54
+ get maxCommitPayloadBytes() {
55
+ if (this.#maxCommitPayloadBytes === undefined)
56
+ throw new Error('Full-text lifecycle has not been initialized');
57
+ return this.#maxCommitPayloadBytes;
58
+ }
59
+ inspect() {
60
+ return this.#requireBinding().inspectNativeFullTextIndex(this.#nativeOptions());
61
+ }
62
+ async open() {
63
+ return this.#requireBinding().openNativeFullTextIndex({
64
+ ...this.#nativeOptions(),
65
+ limits: this.#options.limits,
66
+ });
67
+ }
68
+ async reset() {
69
+ const result = await this.#requireBinding().resetNativeFullTextIndex({
70
+ path: this.#path,
71
+ indexId: this.#options.indexId,
72
+ });
73
+ this.#queueReclaimRetired(result.state === 'reset' ? result.retiredPath : undefined);
74
+ }
75
+ #queueReclaimRetired(retiredPath) {
76
+ const reclaim = () => this.#reclaimRetired(retiredPath);
77
+ this.#reclaimOperation = this.#reclaimOperation.then(reclaim, reclaim).catch((error) => {
78
+ logWarning(`Could not complete reclamation for full-text index '${this.#options.indexId}'`, error);
79
+ });
80
+ }
81
+ async #reclaimRetired(retiredPath) {
82
+ try {
83
+ const result = await this.#requireBinding().reclaimRetiredNativeFullTextIndexes({
84
+ path: this.#path,
85
+ retiredPath,
86
+ });
87
+ if (result.failed > 0)
88
+ logWarning(`Could not remove ${result.failed} retired paths for full-text index '${this.#options.indexId}'`);
89
+ }
90
+ catch (error) {
91
+ logWarning(`Could not reclaim retired paths for full-text index '${this.#options.indexId}'`, error);
92
+ }
93
+ }
94
+ #nativeOptions() {
95
+ return {
96
+ path: this.#path,
97
+ indexId: this.#options.indexId,
98
+ generation: this.#generation,
99
+ fields: this.#options.fields,
100
+ analyzer: this.#options.analyzer,
101
+ stopWords: this.#options.stopWords,
102
+ positions: this.#options.positions,
103
+ surfaceTerms: this.#options.surfaceTerms,
104
+ };
105
+ }
106
+ async #getBinding() {
107
+ if (this.#binding)
108
+ return this.#binding;
109
+ const configured = this.#options.binding;
110
+ this.#binding = configured
111
+ ? await (0, fullTextNativeBinding_ts_1.validateFullTextNativeBinding)(typeof configured === 'function' ? await configured() : configured)
112
+ : await (0, fullTextNativeBinding_ts_1.loadFullTextNativeBinding)();
113
+ return this.#binding;
114
+ }
115
+ #requireBinding() {
116
+ if (!this.#binding)
117
+ throw new Error('Full-text native binding has not been initialized');
118
+ return this.#binding;
119
+ }
120
+ }
121
+ exports.NativeFullTextDerivedIndexLifecycle = NativeFullTextDerivedIndexLifecycle;
122
+ async function createNativeFullTextDerivedIndexBackend(options) {
123
+ const maxCursorPayloadBytes = options.maxCursorPayloadBytes ?? fullTextDerivedIndex_ts_1.HARPER_FULLTEXT_MAX_CURSOR_PAYLOAD_BYTES;
124
+ if (maxCursorPayloadBytes > fullTextDerivedIndex_ts_1.HARPER_FULLTEXT_MAX_CURSOR_PAYLOAD_BYTES)
125
+ throw new RangeError(`Full-text maxCursorPayloadBytes must not exceed ${fullTextDerivedIndex_ts_1.HARPER_FULLTEXT_MAX_CURSOR_PAYLOAD_BYTES}`);
126
+ const lifecycle = new NativeFullTextDerivedIndexLifecycle({ ...options, indexId: options.id });
127
+ await lifecycle.initialize({ reclaimRetired: false });
128
+ if (maxCursorPayloadBytes > lifecycle.maxCommitPayloadBytes)
129
+ throw new RangeError('Full-text maxCursorPayloadBytes exceeds the native commit payload capacity');
130
+ const backend = new fullTextDerivedIndex_ts_1.FullTextDerivedIndexBackend({
131
+ ...options,
132
+ id: options.id,
133
+ lifecycle,
134
+ maxCursorPayloadBytes,
135
+ });
136
+ lifecycle.startRetiredStorageReclamation();
137
+ return backend;
138
+ }
139
+ function digest(value) {
140
+ return (0, node_crypto_1.createHash)('sha256').update(value).digest('hex');
141
+ }
142
+ function logWarning(message, error) {
143
+ const code = error && typeof error === 'object' && 'code' in error && typeof error.code === 'string' ? error.code : undefined;
144
+ try {
145
+ logger.warn?.(`${message}${code ? ` (${code})` : ''}`);
146
+ }
147
+ catch { }
148
+ }
149
+ //# sourceMappingURL=nativeFullTextDerivedIndexLifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeFullTextDerivedIndexLifecycle.js","sourceRoot":"","sources":["../../../resources/indexes/nativeFullTextDerivedIndexLifecycle.ts"],"names":[],"mappings":"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"}
@@ -11,3 +11,8 @@ export declare function getIdOfRemoteNode(remoteNodeName: any, auditStore: any):
11
11
  */
12
12
  export declare function lastTimeInAuditStore(auditStore: Database): import("lmdb").Key;
13
13
  export declare function getThisNodeId(auditStore: any): any;
14
+ /**
15
+ * The node name a local short id refers to. Callers that must attribute a replicated entry to its
16
+ * origin node need the globally stable name, not the id, which is assigned per node.
17
+ */
18
+ export declare function getNodeNameForId(auditStore: any, nodeId: number | undefined, rebuildOnMiss?: boolean): string | undefined;
@@ -5,6 +5,7 @@ exports.remoteToLocalNodeId = remoteToLocalNodeId;
5
5
  exports.getIdOfRemoteNode = getIdOfRemoteNode;
6
6
  exports.lastTimeInAuditStore = lastTimeInAuditStore;
7
7
  exports.getThisNodeId = getThisNodeId;
8
+ exports.getNodeNameForId = getNodeNameForId;
8
9
  /**
9
10
  * This module is responsible for managing the mapping of node/host names to node ids.
10
11
  */
@@ -56,6 +57,7 @@ function getIdMappingRecord(auditStore) {
56
57
  // now we can take over the local node id
57
58
  nameToId[node_name] = 0;
58
59
  auditStore.putSync(REMOTE_NODE_IDS, (0, msgpackr_1.pack)(idMappingRecord));
60
+ invalidateNodeNames(auditStore);
59
61
  }
60
62
  return idMappingRecord;
61
63
  }
@@ -89,6 +91,7 @@ function remoteToLocalNodeId(remoteMapping, auditStore) {
89
91
  }
90
92
  if (hasChanges) {
91
93
  auditStore.putSync(REMOTE_NODE_IDS, (0, msgpackr_1.pack)(idMappingRecord));
94
+ invalidateNodeNames(auditStore);
92
95
  }
93
96
  return remoteToLocalId;
94
97
  }
@@ -107,6 +110,7 @@ function getIdOfRemoteNode(remoteNodeName, auditStore) {
107
110
  id = lastId + 1;
108
111
  nameToId[remoteNodeName] = id;
109
112
  auditStore.putSync(REMOTE_NODE_IDS, (0, msgpackr_1.pack)(idMappingRecord));
113
+ invalidateNodeNames(auditStore);
110
114
  }
111
115
  logger_ts_1.logger.trace?.('The remote node name map', remoteNodeName, nameToId, id);
112
116
  return id;
@@ -126,4 +130,49 @@ function lastTimeInAuditStore(auditStore) {
126
130
  function getThisNodeId(auditStore) {
127
131
  return exportIdMapping(auditStore)?.[Server_ts_1.server.hostname];
128
132
  }
133
+ // Inverted id -> name map. exportIdMapping() re-reads and unpacks the mapping record on every call,
134
+ // which is far too much per replicated entry on the apply thread; ids are stable once minted, so the
135
+ // inversion is cached and dropped wherever nameToId is written. Keyed per audit store because short
136
+ // ids are minted per database in first-seen order — id 1 names a different node in each one.
137
+ // Refresh window for a MISS. A hit is always trusted, but a miss cannot be: ids are minted by
138
+ // whichever worker first talks to a peer, and invalidation only reaches that worker's own copy — so
139
+ // a newly admitted node is absent from every other worker's map until it is rebuilt. Rebuilding on
140
+ // every miss would put a store read and unpack back on the apply thread for each unmapped entry, so
141
+ // misses re-read at most this often — short enough that a joining node loses at most a stray entry,
142
+ // long enough that a burst of unmapped ids cannot drive the store. `onMiss` records whether the
143
+ // cached map was built by a `rebuildOnMiss` caller, which is what bounds that caller to one read per
144
+ // window too rather than exempting it from the interval entirely.
145
+ const NODE_NAME_REFRESH_MS = 50;
146
+ const idToNodeName = new WeakMap();
147
+ function invalidateNodeNames(auditStore) {
148
+ idToNodeName.delete(auditStore);
149
+ }
150
+ /**
151
+ * The node name a local short id refers to. Callers that must attribute a replicated entry to its
152
+ * origin node need the globally stable name, not the id, which is assigned per node.
153
+ */
154
+ function getNodeNameForId(auditStore, nodeId, rebuildOnMiss = false) {
155
+ if (typeof nodeId !== 'number' || !auditStore)
156
+ return undefined;
157
+ const cached = idToNodeName.get(auditStore);
158
+ const hit = cached?.names.get(nodeId);
159
+ if (hit !== undefined)
160
+ return hit;
161
+ const now = Date.now();
162
+ // `rebuildOnMiss` is for entry classes whose loss costs more than the read: a dropped record lock
163
+ // release leaves the home holding a grant until its own deadline, so a just-minted id is worth one
164
+ // store read rather than up to `NODE_NAME_REFRESH_MS` of dropped entries. ONE read, though, not one
165
+ // per entry — an id this map will never resolve (a node whose mapping was purged, an origin
166
+ // relayed from a database that never minted one) is exactly the burst the interval exists to keep
167
+ // off the apply thread, and a rebuild inside the window is not stale: a write to the mapping drops
168
+ // this entry outright (`invalidateNodeNames`).
169
+ if (cached && now - cached.refreshedAt < NODE_NAME_REFRESH_MS && (!rebuildOnMiss || cached.onMiss))
170
+ return undefined;
171
+ const nameToId = exportIdMapping(auditStore);
172
+ const names = new Map();
173
+ for (const name in nameToId)
174
+ names.set(nameToId[name], name);
175
+ idToNodeName.set(auditStore, { names, refreshedAt: now, onMiss: rebuildOnMiss });
176
+ return names.get(nodeId);
177
+ }
129
178
  //# sourceMappingURL=nodeIdMapping.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nodeIdMapping.js","sourceRoot":"","sources":["../../resources/nodeIdMapping.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nodeIdMapping.js","sourceRoot":"","sources":["../../resources/nodeIdMapping.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,16 @@
1
1
  import { ClientError } from '../utility/errors/hdbError.ts';
2
2
  /**
3
- * Exclusive per-record locks (harper#483, Phase 0: one node, every worker thread).
3
+ * Exclusive per-record locks (harper#483).
4
4
  *
5
- * The sole authority is the rocksdb-js process-wide key lock: one `locks` map per DBDescriptor
6
- * shared by every worker thread's handle. Nothing is written to the store or audit log. Lock and
7
- * unlock are pure in-memory operations; the record's version and bytes are unchanged.
5
+ * The intra-node authority is the rocksdb-js process-wide key lock: one `locks` map per DBDescriptor
6
+ * shared by every worker thread's handle. Acquiring and releasing it write nothing to the store, and
7
+ * the record's version and bytes are unchanged.
8
+ *
9
+ * Phase 1 layers cluster-wide exclusion on top without changing that: once the native key is held,
10
+ * `Table.lock()` obtains a delegation for the key from its home node (see `recordLockCoordinator.ts`)
11
+ * and calls `joinClusterRound()` on the handle. A live delegation serves repeat locks with no cluster
12
+ * message at all. A node-scoped lock (`{ scope: 'node' }`), or any lock on a database with no
13
+ * transport registered, skips the cluster step entirely and behaves exactly as it did in Phase 0.
8
14
  */
9
15
  export declare const DEFAULT_LOCK_LEASE_MS = 30000;
10
16
  /** Below this a generation can expire before the caller's work completes, handing back a lock already lost. */
@@ -19,11 +25,19 @@ export interface RecordLockOptions {
19
25
  timeout?: number;
20
26
  /** A held lock outlives the acquiring transaction; it is released by `unlock()` or by its lease */
21
27
  hold?: boolean;
28
+ /**
29
+ * `'cluster'` (default) is exclusive across every participating node; `'node'` keeps Phase 0
30
+ * semantics and is exclusive only across this node's worker threads.
31
+ */
32
+ scope?: 'cluster' | 'node';
22
33
  }
23
34
  export interface ResolvedRecordLockOptions {
24
35
  lease: number;
25
36
  timeout: number;
26
37
  hold: boolean;
38
+ scope: 'cluster' | 'node';
39
+ /** True when the caller named `scope` explicitly, which makes `'cluster'` fail-closed. */
40
+ scopeRequested: boolean;
27
41
  }
28
42
  /**
29
43
  * The handle returned by `lock()` and held by each gated write until its transaction completes.
@@ -48,6 +62,35 @@ export interface RecordLockHandle {
48
62
  noteCandidateFloor(version: number): void;
49
63
  /** Compute a holder-write version without advancing the floor until that write commits. */
50
64
  holderVersionCandidate(floor?: number): number;
65
+ /** `ts_R` of the granted cluster round; undefined while the hold is node-scoped (Phase 0). */
66
+ clusterTsR?: number;
67
+ /**
68
+ * Whether this handle may still authorize a write, evaluated NOW rather than trusting the lease
69
+ * timer to have run. A holder whose event loop stalled past its deadline would otherwise commit
70
+ * between the deadline and its own timer callback, while peers had already expired the hold.
71
+ * Expiry is detected on a monotonic clock, so a wall-clock jump cannot extend a lease.
72
+ */
73
+ isExpired(): boolean;
74
+ /**
75
+ * Whether the LEASE elapsed. Distinct from `isExpired()` in that a deliberate release does NOT
76
+ * make it true on its own: a write staged while the lock was held stays valid at commit if the
77
+ * caller merely unlocked. Once the deadline passes it is true either way, because by then peers
78
+ * have passed their own bound and the key may already belong to someone else.
79
+ */
80
+ isLeaseExpired(): boolean;
81
+ /** Revoke authority ahead of the lease, so a staged-but-uncommitted write is fenced at commit. */
82
+ revokeLease(): void;
83
+ /**
84
+ * Re-anchor a granted cluster round: the hold now runs from `tsR` (no margin, so this node
85
+ * always expires before any participant does) and `onRelease` emits the durable LOCK_RELEASE.
86
+ * Returns false when the round completed after the lease had already elapsed.
87
+ *
88
+ * `mintedMono` is `performance.now()` at the instant `tsR` was minted. The remaining lease is
89
+ * measured from it rather than from `tsR - Date.now()`: `tsR` comes from a never-decreasing
90
+ * monotonic source, so after a backward wall-clock step that subtraction would hand back MORE
91
+ * lease than the round was granted, past what every peer bounded from its own observation.
92
+ */
93
+ joinClusterRound(tsR: number, leaseMs: number, mintedMono: number, onRelease: () => void): boolean;
51
94
  /**
52
95
  * Return the next version to stamp a holder write with. Starts at acquiredAt when no transaction
53
96
  * version has been noted; otherwise advances by the minimum monotonic step from the recorded floor.
@@ -9,14 +9,21 @@ exports.lockNotHeldError = lockNotHeldError;
9
9
  exports.lockAttemptKey = lockAttemptKey;
10
10
  exports.makeKeyLockHandle = makeKeyLockHandle;
11
11
  exports.acquireRecordKey = acquireRecordKey;
12
+ const node_perf_hooks_1 = require("node:perf_hooks");
12
13
  const harper_logger_ts_1 = __importDefault(require("../utility/logging/harper_logger.js"));
13
14
  const hdbError_ts_1 = require("../utility/errors/hdbError.js");
14
15
  /**
15
- * Exclusive per-record locks (harper#483, Phase 0: one node, every worker thread).
16
+ * Exclusive per-record locks (harper#483).
16
17
  *
17
- * The sole authority is the rocksdb-js process-wide key lock: one `locks` map per DBDescriptor
18
- * shared by every worker thread's handle. Nothing is written to the store or audit log. Lock and
19
- * unlock are pure in-memory operations; the record's version and bytes are unchanged.
18
+ * The intra-node authority is the rocksdb-js process-wide key lock: one `locks` map per DBDescriptor
19
+ * shared by every worker thread's handle. Acquiring and releasing it write nothing to the store, and
20
+ * the record's version and bytes are unchanged.
21
+ *
22
+ * Phase 1 layers cluster-wide exclusion on top without changing that: once the native key is held,
23
+ * `Table.lock()` obtains a delegation for the key from its home node (see `recordLockCoordinator.ts`)
24
+ * and calls `joinClusterRound()` on the handle. A live delegation serves repeat locks with no cluster
25
+ * message at all. A node-scoped lock (`{ scope: 'node' }`), or any lock on a database with no
26
+ * transport registered, skips the cluster step entirely and behaves exactly as it did in Phase 0.
20
27
  */
21
28
  exports.DEFAULT_LOCK_LEASE_MS = 30_000;
22
29
  /** Below this a generation can expire before the caller's work completes, handing back a lock already lost. */
@@ -40,10 +47,15 @@ function resolveLockOptions(options) {
40
47
  const hold = options?.hold ?? false;
41
48
  if (typeof hold !== 'boolean')
42
49
  throw new hdbError_ts_1.ClientError(`Lock option hold must be a boolean, but received ${hold}`);
50
+ const scope = options?.scope ?? 'cluster';
51
+ if (scope !== 'cluster' && scope !== 'node')
52
+ throw new hdbError_ts_1.ClientError(`Lock option scope must be 'cluster' or 'node', but received ${scope}`);
43
53
  return {
44
54
  lease: requireDuration('lease', options?.lease, exports.DEFAULT_LOCK_LEASE_MS, exports.MIN_LOCK_LEASE_MS, exports.MAX_LOCK_LEASE_MS),
45
55
  timeout: requireDuration('timeout', options?.timeout, exports.DEFAULT_LOCK_TIMEOUT_MS, 1, exports.MAX_LOCK_TIMEOUT_MS),
46
56
  hold,
57
+ scope,
58
+ scopeRequested: options?.scope !== undefined,
47
59
  };
48
60
  }
49
61
  /**
@@ -59,6 +71,20 @@ function lockAttemptKey(tableId, id) {
59
71
  return Array.isArray(id) ? [LOCK_KEY_PREFIX, tableId, ...id] : [LOCK_KEY_PREFIX, tableId, id];
60
72
  }
61
73
  const warnedLeaseTimerStores = new WeakSet();
74
+ /**
75
+ * Rate-limited rather than latched, for the reason `warnOnce` in the coordinator gives: a release
76
+ * that cannot be written leaves peers waiting out the lease, and a latch would show an operator the
77
+ * first occurrence and then hide the condition for as long as it lasts.
78
+ */
79
+ const CLUSTER_RELEASE_WARN_INTERVAL_MS = 60_000;
80
+ let lastClusterReleaseWarn = -Infinity;
81
+ function warnClusterReleaseFailure(err) {
82
+ const now = node_perf_hooks_1.performance.now();
83
+ if (now - lastClusterReleaseWarn < CLUSTER_RELEASE_WARN_INTERVAL_MS)
84
+ return;
85
+ lastClusterReleaseWarn = now;
86
+ harper_logger_ts_1.default.warn?.('cluster record lock release could not be written; peers will expire the hold', err);
87
+ }
62
88
  class KeyLockHandle {
63
89
  store;
64
90
  key;
@@ -68,9 +94,15 @@ class KeyLockHandle {
68
94
  released = false;
69
95
  expired = false;
70
96
  acquiredAt;
97
+ clusterTsR;
71
98
  #lastHolderVersion;
72
99
  #candidateFloor;
73
100
  #timer;
101
+ // Monotonic mirror of expiresAt. The wall-clock field stays public (callers and the cluster
102
+ // protocol both speak in timestamps) but the enforcement compares monotonic readings, so neither
103
+ // an NTP step nor a manual clock change can extend a lease past what peers assumed.
104
+ #deadlineMono;
105
+ #onRelease;
74
106
  constructor(store, key, keyId, lease, hold = false, acquiredAt) {
75
107
  this.store = store;
76
108
  this.key = key;
@@ -79,6 +111,7 @@ class KeyLockHandle {
79
111
  this.hold = hold;
80
112
  this.acquiredAt = acquiredAt ?? store.getMonotonicTimestamp();
81
113
  if (lease != null) {
114
+ this.#deadlineMono = node_perf_hooks_1.performance.now() + lease;
82
115
  this.#timer = setTimeout(() => this.#onLeaseExpire(), lease).unref();
83
116
  }
84
117
  }
@@ -93,7 +126,70 @@ class KeyLockHandle {
93
126
  const MIN_STEP = 0.000488;
94
127
  return Math.max(this.#lastHolderVersion != null ? this.#lastHolderVersion + MIN_STEP : this.acquiredAt, this.acquiredAt, this.#candidateFloor ?? -Infinity, floor ?? -Infinity);
95
128
  }
129
+ isExpired() {
130
+ return this.released || this.expired || this.#leaseLapsed();
131
+ }
132
+ isLeaseExpired() {
133
+ return this.expired || this.#leaseLapsed();
134
+ }
135
+ // The single place the deadline is evaluated, so the two predicates cannot disagree about it. A
136
+ // deliberate release does not make a lapsed lease valid again: by then peers have passed their own
137
+ // bound and the key may belong to someone else.
138
+ #leaseLapsed() {
139
+ if (this.#deadlineMono === undefined || node_perf_hooks_1.performance.now() < this.#deadlineMono)
140
+ return false;
141
+ // Finish the expiry rather than only reporting it: the native key must actually go back so a
142
+ // stalled holder does not keep a key every participant has already written off.
143
+ if (!this.released)
144
+ this.#onLeaseExpire();
145
+ return true;
146
+ }
147
+ /**
148
+ * Revoke this handle's authority immediately, ahead of its lease. A recall must stop a delegate
149
+ * from COMMITTING, not merely from admitting: a caller that already staged a write and then called
150
+ * `unlock()` has nothing outstanding for a drain to wait on, but its write is still in the
151
+ * transaction and would land after the successor was admitted. Expiring the handle is what makes
152
+ * the commit-time fence reject it (§6).
153
+ */
154
+ revokeLease() {
155
+ if (this.expired)
156
+ return;
157
+ // `expired` is what the commit-time fence reads, and it must be set even when the caller has
158
+ // ALREADY unlocked: a write staged before `unlock()` is still in its transaction, and that is
159
+ // precisely the handoff §6 exists to fence. Gating this on `released` made the revocation a
160
+ // no-op in the one state it was written for.
161
+ this.expired = true;
162
+ if (this.released) {
163
+ // The native key is already back and `onRelease` already fired; only the fence flag and the
164
+ // lease timer are left to settle.
165
+ clearTimeout(this.#timer);
166
+ return;
167
+ }
168
+ this.#onLeaseExpire();
169
+ }
170
+ joinClusterRound(tsR, leaseMs, mintedMono, onRelease) {
171
+ // A round that completed after the native lease already fired yields no usable hold: the key
172
+ // has gone back and another worker may hold it, so every write through this handle would 409.
173
+ if (this.isLeaseExpired())
174
+ return false;
175
+ const remaining = leaseMs - (node_perf_hooks_1.performance.now() - mintedMono);
176
+ if (remaining <= 0)
177
+ return false;
178
+ this.clusterTsR = tsR;
179
+ this.acquiredAt = tsR;
180
+ this.#lastHolderVersion = undefined;
181
+ this.#onRelease = onRelease;
182
+ this.expiresAt = tsR + leaseMs;
183
+ // From the mint origin, not a second clock read: the design says this bound has no margin.
184
+ this.#deadlineMono = mintedMono + leaseMs;
185
+ clearTimeout(this.#timer);
186
+ this.#timer = setTimeout(() => this.#onLeaseExpire(), remaining).unref();
187
+ return true;
188
+ }
96
189
  nextHolderVersion() {
190
+ // TODO(harper#2412): under the settled dual-clock model the lock-ordered stamp belongs in the
191
+ // distinct-version second word (HAS_DISTINCT_VERSION_FLAG), not the transaction timestamp.
192
+ // Until that lands, Phase 1 keeps this Phase 0 mechanism, anchored at ts_R in cluster mode.
97
193
  const next = this.holderVersionCandidate();
98
194
  this.#lastHolderVersion = next;
99
195
  return next;
@@ -103,6 +199,7 @@ class KeyLockHandle {
103
199
  return;
104
200
  this.released = true;
105
201
  this.expired = true;
202
+ clearTimeout(this.#timer);
106
203
  try {
107
204
  this.store.unlock(this.key);
108
205
  }
@@ -112,6 +209,25 @@ class KeyLockHandle {
112
209
  harper_logger_ts_1.default.warn?.('record lock lease timer failed (store may have been dropped)', err);
113
210
  }
114
211
  }
212
+ this.#emitRelease();
213
+ }
214
+ // The cluster release is a durability optimization, not the safety mechanism — peers expire the
215
+ // hold on their own lease bound — so neither a throw nor a rejected promise may escape here. This
216
+ // runs from a lease timer and from post-commit cleanup, where an escaping rejection would take
217
+ // down the worker or turn a committed transaction into a 500.
218
+ #emitRelease() {
219
+ const onRelease = this.#onRelease;
220
+ if (!onRelease)
221
+ return;
222
+ this.#onRelease = undefined;
223
+ try {
224
+ const result = onRelease();
225
+ if (result && typeof result.then === 'function')
226
+ result.then(undefined, warnClusterReleaseFailure);
227
+ }
228
+ catch (err) {
229
+ warnClusterReleaseFailure(err);
230
+ }
115
231
  }
116
232
  release() {
117
233
  if (this.released)
@@ -127,13 +243,28 @@ class KeyLockHandle {
127
243
  harper_logger_ts_1.default.warn?.('record lock release failed (store may have been dropped)', err);
128
244
  }
129
245
  }
246
+ this.#emitRelease();
130
247
  return true;
131
248
  }
132
249
  upgradeToHold(lease) {
133
250
  this.hold = true;
134
251
  clearTimeout(this.#timer);
135
- this.expiresAt = Date.now() + lease;
136
- this.#timer = setTimeout(() => this.#onLeaseExpire(), lease).unref();
252
+ // A granted cluster round may not be extended locally: peers bound the hold from the request
253
+ // they saw, and a longer local lease is exactly the two-holder window this protocol removes.
254
+ // Clamped on the monotonic deadline, not on expiresAt, so a backward wall-clock step cannot
255
+ // turn the upgrade into the extension this is here to refuse.
256
+ const now = node_perf_hooks_1.performance.now();
257
+ const extended = now + lease;
258
+ const deadline = this.clusterTsR === undefined ? extended : Math.min(extended, this.#deadlineMono ?? extended);
259
+ const remaining = deadline - now;
260
+ this.#deadlineMono = deadline;
261
+ this.expiresAt = Date.now() + remaining;
262
+ this.#timer = setTimeout(() => this.#onLeaseExpire(), remaining).unref();
263
+ // Prime the nextHolderVersion counter so a later CLOSED-path save (e.g. after the
264
+ // enclosing transaction commits) gets acquiredAt+MIN_STEP rather than acquiredAt again
265
+ // — the same priming the fresh-hold path performs. Without this, a post-commit save
266
+ // and any in-transaction save both get acquiredAt, causing a LWW tie that drops the write.
267
+ this.nextHolderVersion();
137
268
  }
138
269
  }
139
270
  function makeKeyLockHandle(store, key, keyId, lease, hold = false, acquiredAt) {
@@ -146,7 +277,7 @@ function makeKeyLockHandle(store, key, keyId, lease, hold = false, acquiredAt) {
146
277
  */
147
278
  async function acquireRecordKey(txn, store, key, keyId, waitMs, lease, hold = false) {
148
279
  const existing = txn.recordLockFor(store, keyId);
149
- if (existing && !existing.released && !existing.expired)
280
+ if (existing && !existing.isExpired())
150
281
  return existing;
151
282
  const deadline = Date.now() + waitMs;
152
283
  // One persistent wake slot: at most one onUnlocked callback is registered per waiter at any
@@ -1 +1 @@
1
- {"version":3,"file":"recordLock.js","sourceRoot":"","sources":["../../resources/recordLock.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"recordLock.js","sourceRoot":"","sources":["../../resources/recordLock.ts"],"names":[],"mappings":"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"}