@harperfast/harper 5.2.8 → 5.2.10

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 (189) hide show
  1. package/config-root.schema.json +10 -0
  2. package/dist/resources/DatabaseTransaction.d.ts +3 -0
  3. package/dist/resources/DatabaseTransaction.js +90 -2
  4. package/dist/resources/DatabaseTransaction.js.map +1 -1
  5. package/dist/resources/PrimaryRocksDatabase.js +2 -1
  6. package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
  7. package/dist/resources/RocksIndexStore.js +2 -1
  8. package/dist/resources/RocksIndexStore.js.map +1 -1
  9. package/dist/resources/Table.js +13 -5
  10. package/dist/resources/Table.js.map +1 -1
  11. package/dist/resources/auditStore.js +142 -53
  12. package/dist/resources/auditStore.js.map +1 -1
  13. package/dist/resources/databases.d.ts +9 -0
  14. package/dist/resources/databases.js +315 -76
  15. package/dist/resources/databases.js.map +1 -1
  16. package/dist/resources/search.d.ts +1 -0
  17. package/dist/resources/search.js +41 -13
  18. package/dist/resources/search.js.map +1 -1
  19. package/dist/server/storageReclamation.d.ts +7 -0
  20. package/dist/server/storageReclamation.js +10 -0
  21. package/dist/server/storageReclamation.js.map +1 -1
  22. package/dist/server/threads/manageThreads.d.ts +1 -0
  23. package/dist/server/threads/manageThreads.js +7 -0
  24. package/dist/server/threads/manageThreads.js.map +1 -1
  25. package/dist/utility/hdbTerms.d.ts +2 -0
  26. package/dist/utility/hdbTerms.js +2 -0
  27. package/dist/utility/hdbTerms.js.map +1 -1
  28. package/dist/utility/rocksMemoryConfig.js +7 -4
  29. package/dist/utility/rocksMemoryConfig.js.map +1 -1
  30. package/dist/validation/configValidator.js +2 -0
  31. package/dist/validation/configValidator.js.map +1 -1
  32. package/npm-shrinkwrap.json +41 -41
  33. package/package.json +2 -2
  34. package/resources/DatabaseTransaction.ts +88 -2
  35. package/resources/PrimaryRocksDatabase.ts +2 -1
  36. package/resources/RocksIndexStore.ts +2 -1
  37. package/resources/Table.ts +13 -5
  38. package/resources/auditStore.ts +144 -52
  39. package/resources/databases.ts +296 -70
  40. package/resources/search.ts +43 -14
  41. package/server/storageReclamation.ts +10 -0
  42. package/server/threads/manageThreads.js +7 -0
  43. package/studio/web/assets/Chat-Br06zdMA.js +2267 -0
  44. package/studio/web/assets/FloatingChat-BWImX5fA.js +23 -0
  45. package/studio/web/assets/{abnfDiagram-VCTEODGH-C0_BAZyO.js → abnfDiagram-VCTEODGH-B0BebmD2.js} +1 -1
  46. package/studio/web/assets/{alertDialog-DIHt7Z0r.js → alertDialog-CQyAJJhl.js} +1 -1
  47. package/studio/web/assets/{apiToken-CrPb_98N.js → apiToken-DN0nmDsq.js} +1 -1
  48. package/studio/web/assets/applications-kSxVoyeU.js +296 -0
  49. package/studio/web/assets/architecture-7GRP2DOG-LB-MLAAb.js +1 -0
  50. package/studio/web/assets/{architectureDiagram-5GKGNRK7-BWzrASgm.js → architectureDiagram-5GKGNRK7-7SW3GD-K.js} +1 -1
  51. package/studio/web/assets/authStore-C3Nfubqr.js +3 -0
  52. package/studio/web/assets/{blockDiagram-NRAW4CY4-BdJX9Khj.js → blockDiagram-I7D4REHJ-BqguiadH.js} +2 -2
  53. package/studio/web/assets/{button-DhiX-njv.js → button-BIsUKRZq.js} +2 -2
  54. package/studio/web/assets/{c4Diagram-UCG6FXSJ-CI6MzGmQ.js → c4Diagram-7LVT6UL2-LBNf8t_X.js} +1 -1
  55. package/studio/web/assets/channel-yictG-U-.js +1 -0
  56. package/studio/web/assets/{chevron-up-Df2c8uoU.js → chevron-up-DtKGqDn3.js} +1 -1
  57. package/studio/web/assets/{chunk-TEH6E4GO-P87k5mNi.js → chunk-4HAMMTFA-DWtTut21.js} +1 -1
  58. package/studio/web/assets/{chunk-75Z2AOVW-BT8tVmks.js → chunk-75Z2AOVW-QGQD6th2.js} +1 -1
  59. package/studio/web/assets/{chunk-DU6HZSFF-9kAOOmI6.js → chunk-DU6HZSFF-Chq20Ba5.js} +1 -1
  60. package/studio/web/assets/{chunk-F27PBJKO-BW7ao8AY.js → chunk-F27PBJKO-BVA5EPhV.js} +1 -1
  61. package/studio/web/assets/{chunk-GMAD6QVW-BNyXpoQO.js → chunk-GMAD6QVW-BeS7S07A.js} +1 -1
  62. package/studio/web/assets/{chunk-OBVCFTLP-D4wWOqDQ.js → chunk-GVQU2GXP-sbwVIQ8i.js} +1 -1
  63. package/studio/web/assets/{chunk-G27WJ6UU-COyLMcgK.js → chunk-IMKFNOWR-Bnh3tAVd.js} +1 -1
  64. package/studio/web/assets/{chunk-JQ64N6SF-Cyz1IeLf.js → chunk-L3NEJ4N5-COfUyKII.js} +1 -1
  65. package/studio/web/assets/chunk-OSK3NFVY-ByciRftO.js +10 -0
  66. package/studio/web/assets/{chunk-P2QGCYS3-DmIFY4d7.js → chunk-P2QGCYS3-CP1VhG_c.js} +1 -1
  67. package/studio/web/assets/{chunk-POPQ4Y6H-BPrvMyKz.js → chunk-POPQ4Y6H-ClWhhkwW.js} +1 -1
  68. package/studio/web/assets/{chunk-PWAF6VOD-2zB6IW9i.js → chunk-PWAF6VOD-1z1THyS5.js} +1 -1
  69. package/studio/web/assets/{chunk-RHFEMEQ7-2FgyI8YU.js → chunk-SHT3W25Y-LpQkMsah.js} +2 -2
  70. package/studio/web/assets/{chunk-SVP7TREG-FwtbH2QC.js → chunk-SVP7TREG-jtdAHw0S.js} +1 -1
  71. package/studio/web/assets/{chunk-LCL6LL3I-HOzK_ppE.js → chunk-TICWLB2K-VOwzetX-.js} +1 -1
  72. package/studio/web/assets/classDiagram-ZZMXUADV-VaEwSy_g.js +1 -0
  73. package/studio/web/assets/classDiagram-v2-VYDZK3BY-VaEwSy_g.js +1 -0
  74. package/studio/web/assets/{createLucideIcon-BKGPfjm2.js → createLucideIcon-CzW9508A.js} +1 -1
  75. package/studio/web/assets/{cssMode-D8ceA4av.js → cssMode-C1JeufH5.js} +1 -1
  76. package/studio/web/assets/{cynefin-OW5HDTMX-BRkpLFQV.js → cynefin-OW5HDTMX-BbdbCvub.js} +1 -1
  77. package/studio/web/assets/{cynefinDiagram-5FMLGOSQ-CHT1DaX6.js → cynefinDiagram-5FMLGOSQ-TP-aIqbt.js} +1 -1
  78. package/studio/web/assets/{dagre-3AP2YEHR-DpUXBh63.js → dagre-GXQ25YYZ-DShnGpGo.js} +1 -1
  79. package/studio/web/assets/{diagram-S7CK7UJ4-BuymVFZT.js → diagram-S7CK7UJ4-aoCVTtcy.js} +1 -1
  80. package/studio/web/assets/{diagram-UQ7AKVKN-CyP148RM.js → diagram-UQ7AKVKN-DglXtQ6x.js} +1 -1
  81. package/studio/web/assets/{diagram-VSXAHHWV-CoCAg3M9.js → diagram-VSXAHHWV-fhEdmkwM.js} +1 -1
  82. package/studio/web/assets/{diagram-VX7I27RA-BpOqCFca.js → diagram-VX7I27RA-DccVJet6.js} +1 -1
  83. package/studio/web/assets/{diagram-Z3DM3KII-Bfpw7Vbj.js → diagram-Z3DM3KII-D-RyJJb7.js} +1 -1
  84. package/studio/web/assets/{dialog-CBf0Mr1d.js → dialog-Cn2uWgD4.js} +1 -1
  85. package/studio/web/assets/{dist-lkA3O3eM.js → dist-DP8UjMB_.js} +1 -1
  86. package/studio/web/assets/{download-BtTOBem-.js → download-B5T5r7ss.js} +1 -1
  87. package/studio/web/assets/{ebnfDiagram-PWID7BFC-DS_6aWqL.js → ebnfDiagram-PWID7BFC-DJGpIpz_.js} +1 -1
  88. package/studio/web/assets/{editor-C-jlLd1G.js → editor-qoo9CrGO.js} +1 -1
  89. package/studio/web/assets/{erDiagram-SSCWMZ5O-DJNk6Fgw.js → erDiagram-RLTQ6QDP-CIfNlgkC.js} +1 -1
  90. package/studio/web/assets/eventmodeling-NTZA5JFV-CLxnp2CR.js +1 -0
  91. package/studio/web/assets/flowDiagram-HODETNUW-BIbhmz9f.js +1 -0
  92. package/studio/web/assets/{ganttDiagram-EL5Y4UJY-2pOExxMY.js → ganttDiagram-EL5Y4UJY-BxToTzzD.js} +1 -1
  93. package/studio/web/assets/{getAnalytics-D4LKGeVy.js → getAnalytics-GHK8ORfM.js} +1 -1
  94. package/studio/web/assets/{gitGraph-4MIJSDKK-CH5ZxwzF.js → gitGraph-4MIJSDKK-D2s2w8lE.js} +1 -1
  95. package/studio/web/assets/{gitGraphDiagram-WWUBYQGX-DVIsIhbO.js → gitGraphDiagram-WWUBYQGX-Dwntd4-x.js} +1 -1
  96. package/studio/web/assets/{html-BnuKFPjv.js → html-Dt4IIy04.js} +1 -1
  97. package/studio/web/assets/{htmlMode-DXM6YYUw.js → htmlMode-DXgKKr4C.js} +1 -1
  98. package/studio/web/assets/index-6onkYFOG.js +824 -0
  99. package/studio/web/assets/{index-Cxj2_wsl.css → index-7RMEgVG1.css} +1 -1
  100. package/studio/web/assets/index.lazy-BrCFnpNJ.js +2 -0
  101. package/studio/web/assets/{info-A6RAGUB7-CPQfTnaG.js → info-A6RAGUB7-DYjkvb0C.js} +1 -1
  102. package/studio/web/assets/{infoDiagram-RXCK75RN-DlwLYlwm.js → infoDiagram-27XIBGKW-Bnp1FJE5.js} +1 -1
  103. package/studio/web/assets/{ishikawaDiagram-5VMMS53U-BRXRp29U.js → ishikawaDiagram-5VMMS53U-D9Xh2r6X.js} +1 -1
  104. package/studio/web/assets/{javascript-CAuAkYxc.js → javascript-DNCQGUBc.js} +1 -1
  105. package/studio/web/assets/{journeyDiagram-EYS64GPL-B0ou8k0n.js → journeyDiagram-3NMN7TZE-CokIi6ll.js} +2 -2
  106. package/studio/web/assets/{jsonMode-Dny8hrU7.js → jsonMode-CR6HWruP.js} +1 -1
  107. package/studio/web/assets/{kanban-definition-3QL26DDD-uYg7iYzp.js → kanban-definition-UXKFOSKX-CukSFJfX.js} +1 -1
  108. package/studio/web/assets/{languageServices-D1uNqC6s.js → languageServices-BM4fI4rS.js} +1 -1
  109. package/studio/web/assets/{lspLanguageFeatures-Bh-bvkyK.js → lspLanguageFeatures-DSa1ttcD.js} +1 -1
  110. package/studio/web/assets/{mermaid-parser.core-Ck-fC8b7.js → mermaid-parser.core-BlEsOWNO.js} +3 -3
  111. package/studio/web/assets/{mermaid.core-CP8aNNYm.js → mermaid.core-BlkGaMIH.js} +5 -5
  112. package/studio/web/assets/{mindmap-definition-FBJOCRG2-CgTZ-rit.js → mindmap-definition-YA3MSWOX-IprMc_0j.js} +1 -1
  113. package/studio/web/assets/{notifications-DsE0S3zT.js → notifications-BHXLnh6x.js} +1 -1
  114. package/studio/web/assets/notifications-CUmtIA6z.js +1 -0
  115. package/studio/web/assets/{packet-AYTQ26CC-DEyoPtPb.js → packet-AYTQ26CC-Bi3V04Zi.js} +1 -1
  116. package/studio/web/assets/{pegDiagram-XKGWAZYB-DrD-7sD9.js → pegDiagram-XKGWAZYB-BNuPDLZY.js} +1 -1
  117. package/studio/web/assets/{pie-WAS4IAKB-wjj-EI1d.js → pie-WAS4IAKB-_6DoDbng.js} +1 -1
  118. package/studio/web/assets/{pieDiagram-E7YTZNPT-GntqDCzv.js → pieDiagram-E7YTZNPT-DqNb6Ht2.js} +1 -1
  119. package/studio/web/assets/{profile-BIeCZr-w.js → profile-8BeFSF3j.js} +1 -1
  120. package/studio/web/assets/{quadrantDiagram-AXDQQJYC-0UeqXQGd.js → quadrantDiagram-AXDQQJYC-BGH9E2YR.js} +1 -1
  121. package/studio/web/assets/{radar-RG4KPBEZ-DFSA5h7k.js → radar-RG4KPBEZ-DDdVczcL.js} +1 -1
  122. package/studio/web/assets/{railroad-74A4TZTK-CaOUG9wR.js → railroad-74A4TZTK-BJUP4Jds.js} +1 -1
  123. package/studio/web/assets/railroad-abnf-HS5TGJTU-Bm3L1L0h.js +1 -0
  124. package/studio/web/assets/railroad-ebnf-LZEXJU2U-CKzLGlkw.js +1 -0
  125. package/studio/web/assets/railroad-peg-WCYAUIDC-S8xLjslx.js +1 -0
  126. package/studio/web/assets/{railroadDiagram-O6MQD6OU-yHUELZaV.js → railroadDiagram-O6MQD6OU-DGTPh2KZ.js} +1 -1
  127. package/studio/web/assets/{regions-B5lGduv5.js → regions-C8qR0HhD.js} +1 -1
  128. package/studio/web/assets/{register-Cvc1TpmQ.js → register-B4n5i0SD.js} +3 -3
  129. package/studio/web/assets/{requirementDiagram-EFPCY7ZU-DNEGFjuW.js → requirementDiagram-BXWQKSXE-BJnO6uLz.js} +1 -1
  130. package/studio/web/assets/{sankeyDiagram-P5KCCOFB-DpyAmSVR.js → sankeyDiagram-P5KCCOFB-0vSOdymH.js} +1 -1
  131. package/studio/web/assets/{sequenceDiagram-WJ2MYXX4-TyaT7xNk.js → sequenceDiagram-WJ2MYXX4-hETizDWE.js} +1 -1
  132. package/studio/web/assets/{setComponentFile-D8ZLDWhU.js → setComponentFile-g0_B0lgX.js} +1 -1
  133. package/studio/web/assets/{setup-D2az-Ue_.js → setup-B0CTj_Q5.js} +2 -2
  134. package/studio/web/assets/{stateDiagram-HBIQ2CUA-CeEdTArZ.js → stateDiagram-D77RDMKH-CdYQ_KtC.js} +1 -1
  135. package/studio/web/assets/stateDiagram-v2-MP3YSRHH-CdKuzQMT.js +1 -0
  136. package/studio/web/assets/status-C6Yib7-K.js +61 -0
  137. package/studio/web/assets/{swimlanes-XN3QIQJK-B54FmF46.js → swimlanes-42K2YHIH-B8cHIpU4.js} +1 -1
  138. package/studio/web/assets/swimlanesDiagram-VR7AAH4N-DmOSJwaH.js +8 -0
  139. package/studio/web/assets/{tabs-B_G5zscN.js → tabs-BrHu7gJi.js} +1 -1
  140. package/studio/web/assets/{timeline-definition-24CTP7MA-D-a9ujbo.js → timeline-definition-24CTP7MA-BJWYSXqF.js} +1 -1
  141. package/studio/web/assets/{toggleHighContrast-BdIEw2rK.js → toggleHighContrast-Dgta7bVi.js} +1 -1
  142. package/studio/web/assets/{treeView-Q6P3EWNA-CrW_6JnS.js → treeView-Q6P3EWNA-qxe_v6CQ.js} +1 -1
  143. package/studio/web/assets/{treemap-WGGIJYW6-BxyYLdP_.js → treemap-WGGIJYW6-dDo97XXF.js} +1 -1
  144. package/studio/web/assets/{tsMode-CulNMwI9.js → tsMode-CH_jHvU-.js} +1 -1
  145. package/studio/web/assets/{typescript-BpRqjmvQ.js → typescript-Co9LCXd5.js} +1 -1
  146. package/studio/web/assets/{useEntityRestURL-C7x-Yz9r.js → useEntityRestURL-wKC8NsC_.js} +1 -1
  147. package/studio/web/assets/{useLocalStorage-Dtj1QS8_.js → useLocalStorage-BqMR3D8_.js} +1 -1
  148. package/studio/web/assets/vendor-core-c2JRRJpV.js +58 -0
  149. package/studio/web/assets/vendor-datadog-CLUcJXOo.js +6 -0
  150. package/studio/web/assets/{vendor-react-Dyj4O3HE.js → vendor-react-CJV_K1u4.js} +1 -1
  151. package/studio/web/assets/vendor-tanstack-DxzraizX.js +1 -0
  152. package/studio/web/assets/{vendor-ui-vhu-UHhF.js → vendor-ui-BUjK0h8a.js} +2 -2
  153. package/studio/web/assets/{vennDiagram-4TSXK5OY-Cy7s7Mpy.js → vennDiagram-4TSXK5OY-A3i-lCdl.js} +1 -1
  154. package/studio/web/assets/{wardley-WFR3VGLG-BeBL35g2.js → wardley-WFR3VGLG-B0ik-_6g.js} +1 -1
  155. package/studio/web/assets/{wardleyDiagram-VM6X3IG4-BylmIGSg.js → wardleyDiagram-VM6X3IG4-CjrkKWUR.js} +1 -1
  156. package/studio/web/assets/{workers-B2WpJDK9.js → workers-CWeLxCXA.js} +1 -1
  157. package/studio/web/assets/x-DIzaLEdK.js +1 -0
  158. package/studio/web/assets/{xml-CZnimVSX.js → xml-BadC-0Rk.js} +1 -1
  159. package/studio/web/assets/{xychartDiagram-S5SC5T6Z-CoKALMXr.js → xychartDiagram-S5SC5T6Z-Biok4GYV.js} +1 -1
  160. package/studio/web/assets/{yaml-BwNuyZS-.js → yaml-BiUfxPbC.js} +1 -1
  161. package/studio/web/index.html +14 -14
  162. package/utility/hdbTerms.ts +2 -0
  163. package/utility/rocksMemoryConfig.ts +7 -4
  164. package/validation/configValidator.ts +2 -0
  165. package/studio/web/assets/Chat-DDlysEi_.js +0 -2067
  166. package/studio/web/assets/FloatingChat-DdJ3DZJX.js +0 -23
  167. package/studio/web/assets/applications-C6Y4nL_X.js +0 -296
  168. package/studio/web/assets/architecture-7GRP2DOG-DNdx5tEU.js +0 -1
  169. package/studio/web/assets/authStore-qKmCZcaf.js +0 -3
  170. package/studio/web/assets/channel-DtCV8PTL.js +0 -1
  171. package/studio/web/assets/chunk-R7TYR2AO-Irip67yr.js +0 -10
  172. package/studio/web/assets/classDiagram-DTDB5LWJ-DbO_dCNE.js +0 -1
  173. package/studio/web/assets/classDiagram-v2-JRS7N3AN-DbO_dCNE.js +0 -1
  174. package/studio/web/assets/eventmodeling-NTZA5JFV-5jbe4A5P.js +0 -1
  175. package/studio/web/assets/flowDiagram-A5DVABFB-Dp9Ezlow.js +0 -1
  176. package/studio/web/assets/index-BtTvoLf8.js +0 -824
  177. package/studio/web/assets/index.lazy-PVbC6xQh.js +0 -2
  178. package/studio/web/assets/notifications-DPTOF-SX.js +0 -1
  179. package/studio/web/assets/railroad-abnf-HS5TGJTU-Bc0Qi0WH.js +0 -1
  180. package/studio/web/assets/railroad-ebnf-LZEXJU2U-G8rVVZ2C.js +0 -1
  181. package/studio/web/assets/railroad-peg-WCYAUIDC-CrehKBhC.js +0 -1
  182. package/studio/web/assets/stateDiagram-v2-4QOOHH4V-D4tuw9Su.js +0 -1
  183. package/studio/web/assets/status-BJegPrWN.js +0 -61
  184. package/studio/web/assets/swimlanesDiagram-VK2B7HYN-XOhmNEvq.js +0 -8
  185. package/studio/web/assets/vendor-core-RCcadM3e.js +0 -73
  186. package/studio/web/assets/vendor-datadog-BRv-mOv1.js +0 -6
  187. package/studio/web/assets/vendor-tanstack-BiFWSB3W.js +0 -1
  188. package/studio/web/assets/x-B9o9hsep.js +0 -1
  189. /package/studio/web/assets/{sizeCapture-X5ZJPWSS-B0uUizjq.js → sizeCapture-INFHLROL-B0uUizjq.js} +0 -0
@@ -1055,7 +1055,7 @@ export function filterByType(searchCondition, Table, context, filtered, isPrimar
1055
1055
  canUseIndex =
1056
1056
  canUseIndex && // is it a comparator that makes sense to use index
1057
1057
  !isPrimaryKey && // no need to use index for primary keys, since we will be iterating over the primary keys
1058
- Table?.indices[attribute] && // is there an index for this attribute
1058
+ !!(Table && usableIndex(Table, attribute)) && // is there a usable (complete) index for this attribute
1059
1059
  estimatedIncomingCount > 3; // do we have a valid estimate of multiple incoming records (that is worth using an index for)
1060
1060
  if (canUseIndex) {
1061
1061
  if (searchCondition.estimated_count == undefined) estimateCondition(Table)(searchCondition);
@@ -1112,6 +1112,28 @@ export function filterByType(searchCondition, Table, context, filtered, isPrimar
1112
1112
  }
1113
1113
  }
1114
1114
 
1115
+ /** The index a condition can be driven by; searchByIndex refuses a rebuilding one, so it reads as absent. */
1116
+ function usableIndex(table, attributeName): any {
1117
+ const index = attributeName == null ? undefined : table.indices[attributeName];
1118
+ return index?.isIndexing ? undefined : index;
1119
+ }
1120
+
1121
+ /**
1122
+ * True when an index this attribute would have to be driven by is still being built, following a
1123
+ * relationship path to the local join index and on to the related table's leaf index.
1124
+ */
1125
+ function drivesRebuildingIndex(table, attributeName, relationshipOffset = 0): boolean {
1126
+ if (!Array.isArray(attributeName))
1127
+ return attributeName != null && attributeName !== table.primaryKey && !!table.indices[attributeName]?.isIndexing;
1128
+ if (relationshipOffset >= attributeName.length - 1)
1129
+ return drivesRebuildingIndex(table, attributeName[relationshipOffset]);
1130
+ const attribute = findAttribute(table.attributes, attributeName[relationshipOffset]);
1131
+ if (!attribute) return false;
1132
+ if (table.indices[attribute.relationship?.from]?.isIndexing) return true;
1133
+ const relatedTable = attribute.definition?.tableClass || attribute.elements?.definition?.tableClass;
1134
+ return !!relatedTable && drivesRebuildingIndex(relatedTable, attributeName, relationshipOffset + 1);
1135
+ }
1136
+
1115
1137
  export function estimateCondition(table) {
1116
1138
  function estimateConditionForTable(condition) {
1117
1139
  if (condition.estimated_count === undefined) {
@@ -1131,7 +1153,7 @@ export function estimateCondition(table) {
1131
1153
  for (const subCondition of condition.conditions) {
1132
1154
  estimateConditionForTable(subCondition);
1133
1155
  estimatedCount = isFinite(estimatedCount)
1134
- ? (estimatedCount * subCondition.estimated_count) / estimatedEntryCount(table.primaryStore)
1156
+ ? (estimatedCount * subCondition.estimated_count) / (estimatedEntryCount(table.primaryStore) || 1)
1135
1157
  : subCondition.estimated_count;
1136
1158
  }
1137
1159
  }
@@ -1141,7 +1163,10 @@ export function estimateCondition(table) {
1141
1163
  // skip if it is cached
1142
1164
  let searchType = condition.comparator || condition.search_type;
1143
1165
  searchType = ALTERNATE_COMPARATOR_NAMES[searchType] || searchType;
1144
- if (searchType === SEARCH_TYPES.EQUALS || !searchType) {
1166
+ // before comparator dispatch: several branches fall back to a finite table-fraction heuristic
1167
+ if (drivesRebuildingIndex(table, condition[0] ?? condition.attribute)) {
1168
+ condition.estimated_count = Infinity;
1169
+ } else if (searchType === SEARCH_TYPES.EQUALS || !searchType) {
1145
1170
  const attribute_name = condition[0] ?? condition.attribute;
1146
1171
  if (attribute_name == null || attribute_name === table.primaryKey) condition.estimated_count = 1;
1147
1172
  else if (Array.isArray(attribute_name) && attribute_name.length > 1) {
@@ -1167,19 +1192,21 @@ export function estimateCondition(table) {
1167
1192
  }
1168
1193
  } else {
1169
1194
  // we only attempt to estimate count on equals operator because that's really all that LMDB supports (some other key-value stores like libmdbx could be considered if we need to do estimated counts of ranges at some point)
1170
- const index = table.indices[attribute_name];
1195
+ const index = usableIndex(table, attribute_name);
1171
1196
  condition.estimated_count = index ? index.getValuesCount(condition[1] ?? condition.value) : Infinity;
1172
1197
  }
1173
1198
  } else if (searchType === 'contains' || searchType === 'ends_with' || searchType === 'ne') {
1174
1199
  const attribute_name = condition[0] ?? condition.attribute;
1175
- const index = table.indices[attribute_name];
1200
+ const index = usableIndex(table, attribute_name);
1176
1201
  if (condition.value === null && searchType === 'ne') {
1177
- condition.estimated_count =
1178
- estimatedEntryCount(table.primaryStore) - (index ? index.getValuesCount(null) : 0);
1202
+ condition.estimated_count = Math.max(
1203
+ estimatedEntryCount(table.primaryStore) - (index ? index.getValuesCount(null) : 0),
1204
+ 0
1205
+ );
1179
1206
  } else condition.estimated_count = Infinity;
1180
1207
  } else if (searchType === 'in') {
1181
1208
  const attribute_name = condition[0] ?? condition.attribute;
1182
- const index = table.indices[attribute_name];
1209
+ const index = usableIndex(table, attribute_name);
1183
1210
  if (Array.isArray(condition.value) && index) {
1184
1211
  // Sum of per-value matches (over-counts duplicates but is a fine ceiling)
1185
1212
  let estimate = 0;
@@ -1197,7 +1224,7 @@ export function estimateCondition(table) {
1197
1224
  condition.estimated_count = BETWEEN_ESTIMATE * estimatedEntryCount(table.primaryStore) + 1;
1198
1225
  else if (searchType === 'sort') {
1199
1226
  const attribute_name = condition[0] ?? condition.attribute;
1200
- const index = table.indices[attribute_name];
1227
+ const index = usableIndex(table, attribute_name);
1201
1228
  if (index?.customIndex?.estimateCountAsSort)
1202
1229
  // allow custom index to define its own estimation of counts
1203
1230
  condition.estimated_count = index.customIndex.estimateCountAsSort(condition);
@@ -1205,7 +1232,7 @@ export function estimateCondition(table) {
1205
1232
  } else {
1206
1233
  // for the search types that use the broadest range, try do them last
1207
1234
  const attribute_name = condition[0] ?? condition.attribute;
1208
- const index = table.indices[attribute_name];
1235
+ const index = usableIndex(table, attribute_name);
1209
1236
  if (index?.customIndex?.estimateCount)
1210
1237
  // allow custom index to define its own estimation of counts
1211
1238
  condition.estimated_count = index.customIndex.estimateCount(condition.value);
@@ -1619,16 +1646,18 @@ export function flattenKey(key) {
1619
1646
  return key;
1620
1647
  }
1621
1648
 
1622
- function estimatedEntryCount(store) {
1649
+ export function estimatedEntryCount(store) {
1623
1650
  const now = Date.now();
1624
1651
  if ((store.estimatedEntryCountExpires || 0) < now) {
1625
- // use getStats for LMDB because it is fast path, otherwise RocksDB can handle fast path on its own
1626
- store.estimatedEntryCount = store instanceof RocksDatabase ? store.getKeysCount() : store.getStats().entryCount;
1652
+ // getStats is the LMDB fast path; for RocksDB, estimate-num-keys is O(1) where an exact
1653
+ // getKeysCount() would iterate the entire store
1654
+ store.estimatedEntryCount =
1655
+ store instanceof RocksDatabase ? store.getEstimatedKeyCount() : store.getStats().entryCount;
1627
1656
  store.estimatedEntryCountExpires = now + 10000;
1628
1657
  }
1629
1658
  return store.estimatedEntryCount;
1630
1659
  }
1631
1660
 
1632
1661
  export function intersectionEstimate(store, left, right) {
1633
- return (left * right) / estimatedEntryCount(store);
1662
+ return (left * right) / Math.max(estimatedEntryCount(store), 1);
1634
1663
  }
@@ -118,6 +118,16 @@ export function onStorageReclamation(
118
118
  if (!reclamationTimer) reclamationTimer = setTimeout(runReclamationHandlers, RECLAMATION_INTERVAL).unref();
119
119
  }
120
120
  }
121
+
122
+ /**
123
+ * Drop every reclamation handler registered for `path`. Registration is process-global and keyed by
124
+ * storage path with no lifetime of its own, so a store that is closed and discarded leaves both its
125
+ * handler and the closure holding the closed store alive for the life of the process, and every
126
+ * re-open of the same path appends another.
127
+ */
128
+ export function removeStorageReclamation(path: string): boolean {
129
+ return reclamationHandlers.delete(path);
130
+ }
121
131
  let reclamationTimer: NodeJS.Timeout;
122
132
 
123
133
  export type StorageSpaceStats = {
@@ -159,6 +159,11 @@ module.exports = {
159
159
  isThreadRunning,
160
160
  waitUntilConfirmedGone,
161
161
  restartNumber: workerData?.restartNumber || 1,
162
+ // Identifies this process incarnation, where the PID cannot: a container reuses PID 1. Minted once
163
+ // on the main thread and carried to workers, so live siblings agree on it — one derived per thread
164
+ // would not. `undefined` on a worker started without it; consumers must fall back, not treat that
165
+ // as a mismatch.
166
+ processIncarnation: workerData ? workerData.processIncarnation : randomBytes(8).toString('hex'),
162
167
  };
163
168
 
164
169
  connectedPorts.onMessageByType = onMessageByType;
@@ -225,6 +230,7 @@ const RESERVED_WORKER_DATA_KEYS = [
225
230
  'workerCount',
226
231
  'name',
227
232
  'restartNumber',
233
+ 'processIncarnation',
228
234
  'ticketKeys',
229
235
  'noServerStart',
230
236
  '__proto__', // never a legitimate payload name; spread would define it as an own property
@@ -409,6 +415,7 @@ function startWorker(path, options = {}) {
409
415
  workerCount: (workerCount = options.threadCount),
410
416
  name: options.name,
411
417
  restartNumber: module.exports.restartNumber,
418
+ processIncarnation: module.exports.processIncarnation,
412
419
  ticketKeys: getTicketKeys(),
413
420
  },
414
421
  transferList: portsToSend,