@rocicorp/zero 1.11.0-canary.0 → 1.11.0-canary.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 (577) hide show
  1. package/out/analyze-query/src/bin-analyze.js +1 -1
  2. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  3. package/out/replicache/src/btree/read.d.ts +12 -1
  4. package/out/replicache/src/btree/read.d.ts.map +1 -1
  5. package/out/replicache/src/btree/read.js +24 -12
  6. package/out/replicache/src/btree/read.js.map +1 -1
  7. package/out/replicache/src/dag/gc.d.ts.map +1 -1
  8. package/out/replicache/src/dag/gc.js +2 -1
  9. package/out/replicache/src/dag/gc.js.map +1 -1
  10. package/out/replicache/src/dag/invalid-ref-count-error.d.ts +12 -0
  11. package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +1 -0
  12. package/out/replicache/src/dag/invalid-ref-count-error.js +19 -0
  13. package/out/replicache/src/dag/invalid-ref-count-error.js.map +1 -0
  14. package/out/replicache/src/dag/store-impl.d.ts +12 -2
  15. package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
  16. package/out/replicache/src/dag/store-impl.js +22 -8
  17. package/out/replicache/src/dag/store-impl.js.map +1 -1
  18. package/out/replicache/src/db/rebase.d.ts +14 -2
  19. package/out/replicache/src/db/rebase.d.ts.map +1 -1
  20. package/out/replicache/src/db/rebase.js +27 -5
  21. package/out/replicache/src/db/rebase.js.map +1 -1
  22. package/out/replicache/src/db/write.js.map +1 -1
  23. package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
  24. package/out/replicache/src/kv/expo-sqlite/store.js +28 -5
  25. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  26. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +15 -5
  27. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +1 -1
  28. package/out/replicache/src/kv/idb-store-with-mem-fallback.js +25 -25
  29. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
  30. package/out/replicache/src/kv/idb-store.d.ts +9 -0
  31. package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
  32. package/out/replicache/src/kv/idb-store.js +14 -2
  33. package/out/replicache/src/kv/idb-store.js.map +1 -1
  34. package/out/replicache/src/kv/mem-store.d.ts +1 -0
  35. package/out/replicache/src/kv/mem-store.d.ts.map +1 -1
  36. package/out/replicache/src/kv/mem-store.js +3 -0
  37. package/out/replicache/src/kv/mem-store.js.map +1 -1
  38. package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
  39. package/out/replicache/src/kv/op-sqlite/store.js +1 -1
  40. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  41. package/out/replicache/src/kv/sqlite-store.d.ts +13 -1
  42. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  43. package/out/replicache/src/kv/sqlite-store.js +49 -4
  44. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  45. package/out/replicache/src/kv/store.d.ts +6 -0
  46. package/out/replicache/src/kv/store.d.ts.map +1 -1
  47. package/out/replicache/src/persist/collect-idb-databases.d.ts +10 -5
  48. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  49. package/out/replicache/src/persist/collect-idb-databases.js +16 -9
  50. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  51. package/out/replicache/src/persist/persist.d.ts.map +1 -1
  52. package/out/replicache/src/persist/persist.js +12 -5
  53. package/out/replicache/src/persist/persist.js.map +1 -1
  54. package/out/replicache/src/persist/refresh.js +6 -2
  55. package/out/replicache/src/persist/refresh.js.map +1 -1
  56. package/out/replicache/src/replicache-impl.d.ts +14 -3
  57. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  58. package/out/replicache/src/replicache-impl.js +118 -11
  59. package/out/replicache/src/replicache-impl.js.map +1 -1
  60. package/out/replicache/src/replicache-options.d.ts +9 -0
  61. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  62. package/out/replicache/src/transactions.d.ts.map +1 -1
  63. package/out/replicache/src/transactions.js +1 -1
  64. package/out/replicache/src/transactions.js.map +1 -1
  65. package/out/shared/src/error.d.ts +11 -0
  66. package/out/shared/src/error.d.ts.map +1 -1
  67. package/out/shared/src/error.js +35 -1
  68. package/out/shared/src/error.js.map +1 -1
  69. package/out/shared/src/iterables.d.ts +2 -0
  70. package/out/shared/src/iterables.d.ts.map +1 -1
  71. package/out/shared/src/iterables.js +18 -1
  72. package/out/shared/src/iterables.js.map +1 -1
  73. package/out/shared/src/map.d.ts +7 -2
  74. package/out/shared/src/map.d.ts.map +1 -1
  75. package/out/shared/src/map.js.map +1 -1
  76. package/out/shared/src/ring-buffer.d.ts +8 -0
  77. package/out/shared/src/ring-buffer.d.ts.map +1 -1
  78. package/out/shared/src/ring-buffer.js +22 -1
  79. package/out/shared/src/ring-buffer.js.map +1 -1
  80. package/out/zero/package.js +3 -4
  81. package/out/zero/package.js.map +1 -1
  82. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  83. package/out/zero-cache/src/config/normalize.js +25 -1
  84. package/out/zero-cache/src/config/normalize.js.map +1 -1
  85. package/out/zero-cache/src/config/zero-config.d.ts +48 -2
  86. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  87. package/out/zero-cache/src/config/zero-config.js +171 -29
  88. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  89. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  90. package/out/zero-cache/src/server/change-streamer.js +25 -9
  91. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  92. package/out/zero-cache/src/server/inspector-delegate.d.ts +18 -2
  93. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  94. package/out/zero-cache/src/server/inspector-delegate.js +20 -7
  95. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  96. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  97. package/out/zero-cache/src/server/main.js +8 -1
  98. package/out/zero-cache/src/server/main.js.map +1 -1
  99. package/out/zero-cache/src/server/mutator.js +2 -0
  100. package/out/zero-cache/src/server/mutator.js.map +1 -1
  101. package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
  102. package/out/zero-cache/src/server/reaper.js +2 -0
  103. package/out/zero-cache/src/server/reaper.js.map +1 -1
  104. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  105. package/out/zero-cache/src/server/replicator.js +8 -2
  106. package/out/zero-cache/src/server/replicator.js.map +1 -1
  107. package/out/zero-cache/src/server/runner/run-worker.js +1 -1
  108. package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
  109. package/out/zero-cache/src/server/runner/zero-dispatcher.js +3 -0
  110. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  111. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  112. package/out/zero-cache/src/server/syncer.js +2 -0
  113. package/out/zero-cache/src/server/syncer.js.map +1 -1
  114. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  115. package/out/zero-cache/src/services/analyze.js +3 -2
  116. package/out/zero-cache/src/services/analyze.js.map +1 -1
  117. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
  118. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +14 -1
  119. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  120. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
  121. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +15 -3
  122. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  123. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  124. package/out/zero-cache/src/services/change-source/common/replica-schema.js +2 -39
  125. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  126. package/out/zero-cache/src/services/change-source/pg/backfill-resume.d.ts +156 -0
  127. package/out/zero-cache/src/services/change-source/pg/backfill-resume.d.ts.map +1 -0
  128. package/out/zero-cache/src/services/change-source/pg/backfill-resume.js +15 -0
  129. package/out/zero-cache/src/services/change-source/pg/backfill-resume.js.map +1 -0
  130. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts +25 -0
  131. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts.map +1 -0
  132. package/out/zero-cache/src/services/change-source/pg/change-source-init.js +202 -0
  133. package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -0
  134. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +14 -16
  135. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  136. package/out/zero-cache/src/services/change-source/pg/change-source.js +64 -143
  137. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  138. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +28 -2
  139. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  140. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +44 -21
  141. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  142. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts +16 -0
  143. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts.map +1 -0
  144. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js +113 -0
  145. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js.map +1 -0
  146. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +21 -15
  147. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  148. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +86 -23
  149. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  150. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +1 -1
  151. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +68 -8
  152. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -1
  153. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  154. package/out/zero-cache/src/services/change-source/pg/schema/init.js +32 -1
  155. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  156. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.d.ts +10 -0
  157. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.d.ts.map +1 -0
  158. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js +6 -0
  159. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js.map +1 -0
  160. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +50 -27
  161. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  162. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +100 -34
  163. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  164. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  165. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +58 -7
  166. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  167. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +8 -2
  168. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  169. package/out/zero-cache/src/services/change-streamer/broadcast.js +24 -4
  170. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  171. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -4
  172. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -1
  173. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +28 -8
  174. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -1
  175. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +5 -2
  176. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  177. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +21 -14
  178. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  179. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +6 -0
  180. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  181. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +97 -63
  182. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  183. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +12 -8
  184. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  185. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  186. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +3 -3
  187. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  188. package/out/zero-cache/src/services/change-streamer/forwarder.js +36 -5
  189. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  190. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +1 -1
  191. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  192. package/out/zero-cache/src/services/change-streamer/schema/tables.js +4 -4
  193. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  194. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +3 -1
  195. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
  196. package/out/zero-cache/src/services/change-streamer/snapshot.js +54 -20
  197. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  198. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +6 -1
  199. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -1
  200. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +27 -9
  201. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -1
  202. package/out/zero-cache/src/services/change-streamer/storer.d.ts +2 -2
  203. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  204. package/out/zero-cache/src/services/change-streamer/storer.js +8 -5
  205. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  206. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +4 -1
  207. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  208. package/out/zero-cache/src/services/change-streamer/subscriber.js +42 -0
  209. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  210. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +17 -1
  211. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -1
  212. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +19 -3
  213. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -1
  214. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +1 -1
  215. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +1 -0
  216. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js.map +1 -1
  217. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  218. package/out/zero-cache/src/services/life-cycle.js +3 -1
  219. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  220. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  221. package/out/zero-cache/src/services/litestream/commands.js +8 -3
  222. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  223. package/out/zero-cache/src/services/litestream/config-v5.yml +15 -1
  224. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +131 -0
  225. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +1 -0
  226. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts +70 -0
  227. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts.map +1 -0
  228. package/out/zero-cache/src/services/litestream/litestream-controller.js +101 -0
  229. package/out/zero-cache/src/services/litestream/litestream-controller.js.map +1 -0
  230. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +5 -0
  231. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  232. package/out/zero-cache/src/services/mutagen/mutagen.js +7 -1
  233. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  234. package/out/zero-cache/src/services/mutagen/pusher.js +2 -1
  235. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  236. package/out/zero-cache/src/services/profz.d.ts +7 -0
  237. package/out/zero-cache/src/services/profz.d.ts.map +1 -0
  238. package/out/zero-cache/src/services/profz.js +105 -0
  239. package/out/zero-cache/src/services/profz.js.map +1 -0
  240. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -1
  241. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +5 -4
  242. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -1
  243. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +20 -22
  244. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -1
  245. package/out/zero-cache/src/services/replicator/change-processor.js +1 -0
  246. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  247. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
  248. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  249. package/out/zero-cache/src/services/replicator/incremental-sync.js +58 -17
  250. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  251. package/out/zero-cache/src/services/replicator/replication-status.d.ts +35 -1
  252. package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
  253. package/out/zero-cache/src/services/replicator/replication-status.js +96 -6
  254. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  255. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  256. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +6 -6
  257. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -1
  258. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +19 -14
  259. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -1
  260. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +31 -6
  261. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
  262. package/out/zero-cache/src/services/replicator/write-worker-client.js +5 -4
  263. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  264. package/out/zero-cache/src/services/replicator/write-worker.js +30 -5
  265. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  266. package/out/zero-cache/src/services/run-ast.d.ts +12 -0
  267. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  268. package/out/zero-cache/src/services/run-ast.js +26 -14
  269. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  270. package/out/zero-cache/src/services/runner.d.ts.map +1 -1
  271. package/out/zero-cache/src/services/runner.js +1 -1
  272. package/out/zero-cache/src/services/runner.js.map +1 -1
  273. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +1 -1
  274. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  275. package/out/zero-cache/src/services/view-syncer/client-handler.js +36 -31
  276. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  277. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +45 -0
  278. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  279. package/out/zero-cache/src/services/view-syncer/cvr.js +133 -1
  280. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  281. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +14 -1
  282. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
  283. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +30 -4
  284. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  285. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts +33 -0
  286. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts.map +1 -0
  287. package/out/zero-cache/src/services/view-syncer/hydration-budget.js +62 -0
  288. package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +1 -0
  289. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +51 -0
  290. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +1 -0
  291. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +78 -0
  292. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -0
  293. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +1 -1
  294. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  295. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +2 -2
  296. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  297. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +2 -1
  298. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  299. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +33 -18
  300. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  301. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +4 -1
  302. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  303. package/out/zero-cache/src/services/view-syncer/snapshotter.js +9 -3
  304. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  305. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
  306. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  307. package/out/zero-cache/src/services/view-syncer/view-syncer.js +507 -93
  308. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  309. package/out/zero-cache/src/types/processes.d.ts +32 -0
  310. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  311. package/out/zero-cache/src/types/processes.js +43 -4
  312. package/out/zero-cache/src/types/processes.js.map +1 -1
  313. package/out/zero-cache/src/types/profiler.d.ts +12 -0
  314. package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
  315. package/out/zero-cache/src/types/profiler.js +46 -1
  316. package/out/zero-cache/src/types/profiler.js.map +1 -1
  317. package/out/zero-cache/src/types/streams.d.ts +25 -9
  318. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  319. package/out/zero-cache/src/types/streams.js +118 -34
  320. package/out/zero-cache/src/types/streams.js.map +1 -1
  321. package/out/zero-cache/src/types/subscription.d.ts +4 -0
  322. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  323. package/out/zero-cache/src/types/subscription.js +71 -0
  324. package/out/zero-cache/src/types/subscription.js.map +1 -1
  325. package/out/zero-cache/src/types/ws.d.ts.map +1 -1
  326. package/out/zero-cache/src/types/ws.js +23 -8
  327. package/out/zero-cache/src/types/ws.js.map +1 -1
  328. package/out/zero-cache/src/workers/connection.js +2 -2
  329. package/out/zero-cache/src/workers/replicator.d.ts +1 -0
  330. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  331. package/out/zero-cache/src/workers/replicator.js +4 -2
  332. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  333. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  334. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +21 -16
  335. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  336. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  337. package/out/zero-cache/src/workers/syncer.js +10 -1
  338. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  339. package/out/zero-client/src/client/connection-manager.d.ts +20 -0
  340. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  341. package/out/zero-client/src/client/connection-manager.js +77 -13
  342. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  343. package/out/zero-client/src/client/connection-status-enum.d.ts +2 -0
  344. package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
  345. package/out/zero-client/src/client/connection-status-enum.js +3 -1
  346. package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
  347. package/out/zero-client/src/client/connection.d.ts +6 -0
  348. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  349. package/out/zero-client/src/client/connection.js +2 -1
  350. package/out/zero-client/src/client/connection.js.map +1 -1
  351. package/out/zero-client/src/client/context.d.ts +27 -2
  352. package/out/zero-client/src/client/context.d.ts.map +1 -1
  353. package/out/zero-client/src/client/context.js +112 -1
  354. package/out/zero-client/src/client/context.js.map +1 -1
  355. package/out/zero-client/src/client/custom.js +2 -2
  356. package/out/zero-client/src/client/custom.js.map +1 -1
  357. package/out/zero-client/src/client/error.js +1 -1
  358. package/out/zero-client/src/client/inspector/lazy-inspector.js +2 -2
  359. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  360. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  361. package/out/zero-client/src/client/ivm-branch.js +20 -3
  362. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  363. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  364. package/out/zero-client/src/client/mutator-proxy.js +2 -1
  365. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  366. package/out/zero-client/src/client/options.d.ts +3 -0
  367. package/out/zero-client/src/client/options.d.ts.map +1 -1
  368. package/out/zero-client/src/client/options.js.map +1 -1
  369. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  370. package/out/zero-client/src/client/query-manager.js +42 -6
  371. package/out/zero-client/src/client/query-manager.js.map +1 -1
  372. package/out/zero-client/src/client/version.js +1 -1
  373. package/out/zero-client/src/client/zero-rep.d.ts +1 -0
  374. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  375. package/out/zero-client/src/client/zero-rep.js +9 -6
  376. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  377. package/out/zero-client/src/client/zero.d.ts +18 -3
  378. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  379. package/out/zero-client/src/client/zero.js +122 -34
  380. package/out/zero-client/src/client/zero.js.map +1 -1
  381. package/out/zero-client/src/types/query-result.d.ts +2 -0
  382. package/out/zero-client/src/types/query-result.d.ts.map +1 -1
  383. package/out/zero-events/src/status.d.ts +26 -0
  384. package/out/zero-events/src/status.d.ts.map +1 -1
  385. package/out/zero-protocol/src/analyze-query-result.d.ts +5 -5
  386. package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
  387. package/out/zero-protocol/src/analyze-query-result.js +1 -1
  388. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  389. package/out/zero-protocol/src/down.d.ts +4 -4
  390. package/out/zero-protocol/src/inspect-down.d.ts +6 -6
  391. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  392. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  393. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  394. package/out/zero-react/src/use-query.d.ts +5 -4
  395. package/out/zero-react/src/use-query.d.ts.map +1 -1
  396. package/out/zero-react/src/use-query.js +86 -9
  397. package/out/zero-react/src/use-query.js.map +1 -1
  398. package/out/zero-server/src/adapters/drizzle.d.ts +2 -1
  399. package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
  400. package/out/zero-server/src/adapters/drizzle.js +12 -7
  401. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  402. package/out/zero-server/src/adapters/kysely.d.ts +2 -1
  403. package/out/zero-server/src/adapters/kysely.d.ts.map +1 -1
  404. package/out/zero-server/src/adapters/kysely.js +8 -2
  405. package/out/zero-server/src/adapters/kysely.js.map +1 -1
  406. package/out/zero-server/src/adapters/pg.d.ts +1 -0
  407. package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
  408. package/out/zero-server/src/adapters/pg.js +8 -2
  409. package/out/zero-server/src/adapters/pg.js.map +1 -1
  410. package/out/zero-server/src/adapters/postgresjs.d.ts +1 -0
  411. package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
  412. package/out/zero-server/src/adapters/postgresjs.js +7 -1
  413. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  414. package/out/zero-server/src/adapters/prisma.d.ts +3 -2
  415. package/out/zero-server/src/adapters/prisma.d.ts.map +1 -1
  416. package/out/zero-server/src/adapters/prisma.js +8 -2
  417. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  418. package/out/zero-server/src/custom.d.ts +5 -1
  419. package/out/zero-server/src/custom.d.ts.map +1 -1
  420. package/out/zero-server/src/custom.js +6 -3
  421. package/out/zero-server/src/custom.js.map +1 -1
  422. package/out/zero-server/src/mod.d.ts +1 -1
  423. package/out/zero-server/src/mod.d.ts.map +1 -1
  424. package/out/zero-server/src/pg-query-executor.d.ts +2 -2
  425. package/out/zero-server/src/pg-query-executor.d.ts.map +1 -1
  426. package/out/zero-server/src/pg-query-executor.js +2 -2
  427. package/out/zero-server/src/pg-query-executor.js.map +1 -1
  428. package/out/zero-server/src/schema.d.ts +2 -2
  429. package/out/zero-server/src/schema.d.ts.map +1 -1
  430. package/out/zero-server/src/schema.js +2 -2
  431. package/out/zero-server/src/schema.js.map +1 -1
  432. package/out/zero-server/src/zql-database.d.ts +21 -1
  433. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  434. package/out/zero-server/src/zql-database.js +33 -2
  435. package/out/zero-server/src/zql-database.js.map +1 -1
  436. package/out/zero-solid/src/solid-view.d.ts +17 -0
  437. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  438. package/out/zero-solid/src/solid-view.js +39 -1
  439. package/out/zero-solid/src/solid-view.js.map +1 -1
  440. package/out/zero-solid/src/use-query.js +5 -3
  441. package/out/zero-solid/src/use-query.js.map +1 -1
  442. package/out/zql/src/builder/builder.d.ts.map +1 -1
  443. package/out/zql/src/builder/builder.js +16 -10
  444. package/out/zql/src/builder/builder.js.map +1 -1
  445. package/out/zql/src/builder/debug-delegate.d.ts +6 -1
  446. package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
  447. package/out/zql/src/builder/debug-delegate.js +14 -2
  448. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  449. package/out/zql/src/ivm/array-view.d.ts +29 -0
  450. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  451. package/out/zql/src/ivm/array-view.js +63 -12
  452. package/out/zql/src/ivm/array-view.js.map +1 -1
  453. package/out/zql/src/ivm/cap.d.ts.map +1 -1
  454. package/out/zql/src/ivm/cap.js +5 -3
  455. package/out/zql/src/ivm/cap.js.map +1 -1
  456. package/out/zql/src/ivm/data.d.ts.map +1 -1
  457. package/out/zql/src/ivm/data.js +8 -3
  458. package/out/zql/src/ivm/data.js.map +1 -1
  459. package/out/zql/src/ivm/deferred-input.d.ts +44 -0
  460. package/out/zql/src/ivm/deferred-input.d.ts.map +1 -0
  461. package/out/zql/src/ivm/deferred-input.js +89 -0
  462. package/out/zql/src/ivm/deferred-input.js.map +1 -0
  463. package/out/zql/src/ivm/exists.d.ts +1 -1
  464. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  465. package/out/zql/src/ivm/exists.js.map +1 -1
  466. package/out/zql/src/ivm/fan-in.d.ts +2 -2
  467. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  468. package/out/zql/src/ivm/fan-in.js +6 -5
  469. package/out/zql/src/ivm/fan-in.js.map +1 -1
  470. package/out/zql/src/ivm/fan-out.d.ts +2 -2
  471. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  472. package/out/zql/src/ivm/fan-out.js.map +1 -1
  473. package/out/zql/src/ivm/filter-operators.d.ts +7 -6
  474. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  475. package/out/zql/src/ivm/filter-operators.js +29 -12
  476. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  477. package/out/zql/src/ivm/filter.d.ts +2 -2
  478. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  479. package/out/zql/src/ivm/filter.js +7 -4
  480. package/out/zql/src/ivm/filter.js.map +1 -1
  481. package/out/zql/src/ivm/flipped-join.js +2 -2
  482. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  483. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  484. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  485. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +6 -4
  486. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  487. package/out/zql/src/ivm/memory-source.d.ts +15 -3
  488. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  489. package/out/zql/src/ivm/memory-source.js +57 -23
  490. package/out/zql/src/ivm/memory-source.js.map +1 -1
  491. package/out/zql/src/ivm/operator.d.ts +40 -0
  492. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  493. package/out/zql/src/ivm/operator.js.map +1 -1
  494. package/out/zql/src/ivm/take.d.ts.map +1 -1
  495. package/out/zql/src/ivm/take.js +3 -4
  496. package/out/zql/src/ivm/take.js.map +1 -1
  497. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  498. package/out/zql/src/ivm/union-fan-in.js +9 -7
  499. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  500. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  501. package/out/zql/src/ivm/view-apply-change.js +9 -4
  502. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  503. package/out/zql/src/ivm/view.d.ts +15 -0
  504. package/out/zql/src/ivm/view.d.ts.map +1 -1
  505. package/out/zql/src/mutate/custom.d.ts +24 -1
  506. package/out/zql/src/mutate/custom.d.ts.map +1 -1
  507. package/out/zql/src/mutate/custom.js.map +1 -1
  508. package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
  509. package/out/zql/src/mutate/mutator-registry.js +2 -2
  510. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  511. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  512. package/out/zql/src/planner/planner-builder.js +14 -4
  513. package/out/zql/src/planner/planner-builder.js.map +1 -1
  514. package/out/zql/src/planner/planner-connection.d.ts +13 -0
  515. package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
  516. package/out/zql/src/planner/planner-connection.js +42 -7
  517. package/out/zql/src/planner/planner-connection.js.map +1 -1
  518. package/out/zql/src/planner/planner-debug.d.ts +1 -1
  519. package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
  520. package/out/zql/src/planner/planner-debug.js.map +1 -1
  521. package/out/zql/src/planner/planner-fan-out.d.ts +1 -0
  522. package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -1
  523. package/out/zql/src/planner/planner-fan-out.js +3 -0
  524. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  525. package/out/zql/src/planner/planner-filter.d.ts +59 -0
  526. package/out/zql/src/planner/planner-filter.d.ts.map +1 -0
  527. package/out/zql/src/planner/planner-filter.js +116 -0
  528. package/out/zql/src/planner/planner-filter.js.map +1 -0
  529. package/out/zql/src/planner/planner-graph.d.ts +2 -0
  530. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  531. package/out/zql/src/planner/planner-graph.js +2 -0
  532. package/out/zql/src/planner/planner-graph.js.map +1 -1
  533. package/out/zql/src/planner/planner-join.d.ts +2 -0
  534. package/out/zql/src/planner/planner-join.d.ts.map +1 -1
  535. package/out/zql/src/planner/planner-join.js +7 -0
  536. package/out/zql/src/planner/planner-join.js.map +1 -1
  537. package/out/zql/src/planner/planner-node.d.ts +2 -1
  538. package/out/zql/src/planner/planner-node.d.ts.map +1 -1
  539. package/out/zql/src/planner/planner-node.js.map +1 -1
  540. package/out/zql/src/query/query-delegate-base.d.ts +9 -1
  541. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  542. package/out/zql/src/query/query-delegate-base.js +129 -33
  543. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  544. package/out/zql/src/query/query-delegate.d.ts +50 -1
  545. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  546. package/out/zql/src/query/query-impl.d.ts +13 -11
  547. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  548. package/out/zql/src/query/query-impl.js +383 -60
  549. package/out/zql/src/query/query-impl.js.map +1 -1
  550. package/out/zql/src/query/query-transitions.d.ts +171 -0
  551. package/out/zql/src/query/query-transitions.d.ts.map +1 -0
  552. package/out/zql/src/query/query-transitions.js +207 -0
  553. package/out/zql/src/query/query-transitions.js.map +1 -0
  554. package/out/zql/src/query/query.d.ts +11 -2
  555. package/out/zql/src/query/query.d.ts.map +1 -1
  556. package/out/zql/src/query/runnable-query-impl.d.ts +1 -0
  557. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
  558. package/out/zql/src/query/runnable-query-impl.js +21 -1
  559. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  560. package/out/zql/src/query/typed-view.d.ts +1 -1
  561. package/out/zql/src/query/typed-view.d.ts.map +1 -1
  562. package/out/zqlite/src/db.d.ts +9 -1
  563. package/out/zqlite/src/db.d.ts.map +1 -1
  564. package/out/zqlite/src/db.js +8 -2
  565. package/out/zqlite/src/db.js.map +1 -1
  566. package/out/zqlite/src/query-builder.d.ts +1 -1
  567. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  568. package/out/zqlite/src/query-builder.js +2 -1
  569. package/out/zqlite/src/query-builder.js.map +1 -1
  570. package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
  571. package/out/zqlite/src/sqlite-cost-model.js +2 -30
  572. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  573. package/out/zqlite/src/table-source.d.ts +1 -0
  574. package/out/zqlite/src/table-source.d.ts.map +1 -1
  575. package/out/zqlite/src/table-source.js +20 -8
  576. package/out/zqlite/src/table-source.js.map +1 -1
  577. package/package.json +3 -4
@@ -16,8 +16,32 @@ export declare const MESSAGE_TYPES: {
16
16
  readonly notify: 'notify';
17
17
  readonly ready: 'ready';
18
18
  readonly backupWatermarkUpdate: 'backupWatermakUpdate';
19
+ readonly profile: 'profile';
20
+ readonly profileResponse: 'profileResponse';
19
21
  };
22
+ export type ProfileRequest = {
23
+ readonly id: string;
24
+ readonly durationMs: number;
25
+ readonly worker?: string | undefined;
26
+ readonly workerIndex?: number | undefined;
27
+ };
28
+ export type ProfileResponse = {
29
+ readonly id: string;
30
+ readonly name: string;
31
+ readonly profile?: unknown | undefined;
32
+ readonly error?: string | undefined;
33
+ };
34
+ export type ProfileMessage = ['profile', ProfileRequest];
35
+ export type ProfileResponseMessage = ['profileResponse', ProfileResponse];
20
36
  export type Message<Payload> = [keyof typeof MESSAGE_TYPES, Payload];
37
+ /**
38
+ * Subscribes the `handler` to messages of the given `type` and returns a
39
+ * function that unsubscribes it. Use this (rather than
40
+ * {@link Receiver.onMessageType()}) for handlers scoped to a request or
41
+ * operation rather than to the lifetime of the {@link Worker}; the
42
+ * `'message'` listener is otherwise retained by the Worker forever.
43
+ */
44
+ export declare function subscribeToMessageType<M extends Message<unknown>>(e: EventEmitter, type: M[0], handler: (msg: M[1], sendHandle?: SendHandle) => void): () => void;
21
45
  export interface Sender {
22
46
  send<M extends Message<unknown>>(message: M, sendHandle?: SendHandle, callback?: (error: Error | null) => void): boolean;
23
47
  kill(signal?: NodeJS.Signals): void;
@@ -86,4 +110,12 @@ export declare function forkChildWorker(moduleUrl: URL, env?: NodeJS.ProcessEnv,
86
110
  * in a single process.
87
111
  */
88
112
  export declare function inProcChannel(): [Worker, Worker];
113
+ /**
114
+ * Creates a {@link Worker} facade that broadcasts `send()` to all provided
115
+ * workers and aggregates their `'message'` events into one stream.
116
+ *
117
+ * This is useful for code that expects a single Worker for IPC (e.g.
118
+ * `handleProfzRequest`) but needs to reach multiple child workers.
119
+ */
120
+ export declare function broadcastWorker(workers: Worker[]): Worker;
89
121
  //# sourceMappingURL=processes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"processes.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/processes.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,YAAY,MAAM,aAAa,CAAC;AAIvC;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa;aACxB,OAAO,EAAE,SAAS;aAClB,MAAM,EAAE,QAAQ;aAChB,SAAS,EAAE,WAAW;aACtB,MAAM,EAAE,QAAQ;aAChB,KAAK,EAAE,OAAO;aACd,qBAAqB,EAAE,sBAAsB;CACrC,CAAC;AAEX,MAAM,MAAM,OAAO,CAAC,OAAO,IAAI,CAAC,MAAM,OAAO,aAAa,EAAE,OAAO,CAAC,CAAC;AAwCrE,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,EAC7B,OAAO,EAAE,CAAC,EACV,UAAU,CAAC,EAAE,UAAU,EACvB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GACvC,OAAO,CAAC;IAEX,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,UAAW,SAAQ,MAAM,EAAE,YAAY;IACtD,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,MAAM,WAAW,QAAS,SAAQ,YAAY;IAC5C;;;;OAIG;IACH,aAAa,CAAC,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,EACtC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EACV,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,UAAU,KAAK,IAAI,GACpD,IAAI,CAAC;IAER;;;;OAIG;IACH,eAAe,CAAC,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,EACxC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EACV,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,UAAU,KAAK,IAAI,GACpD,IAAI,CAAC;CACT;AAED,MAAM,WAAW,MAAO,SAAQ,UAAU,EAAE,QAAQ;CAAG;AAkCvD;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,GAAG,IAE5B,CAAC;AAIT,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,OAAc,GAAG,IAAI,CAElE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,mBAAmB,EAAE,OAAO,GAC3B,OAAO,CAET;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,GAAG,EACd,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,EACvB,GAAG,IAAI,EAAE,MAAM,EAAE,GAChB,MAAM,CAoBR;AAED,wBAAgB,eAAe,CAC7B,SAAS,EAAE,GAAG,EACd,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,EACvB,GAAG,IAAI,EAAE,MAAM,EAAE,GAChB,MAAM,CAER;AAuBD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CA+BhD"}
1
+ {"version":3,"file":"processes.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/processes.ts"],"names":[],"mappings":"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"}
@@ -7,11 +7,26 @@ function getMessage(type, data) {
7
7
  if (Array.isArray(data) && data.length === 2 && data[0] === type) return data[1];
8
8
  return null;
9
9
  }
10
- function onMessageType(e, type, handler) {
11
- return e.on("message", (data, sendHandle) => {
10
+ /**
11
+ * Subscribes the `handler` to messages of the given `type` and returns a
12
+ * function that unsubscribes it. Use this (rather than
13
+ * {@link Receiver.onMessageType()}) for handlers scoped to a request or
14
+ * operation rather than to the lifetime of the {@link Worker}; the
15
+ * `'message'` listener is otherwise retained by the Worker forever.
16
+ */
17
+ function subscribeToMessageType(e, type, handler) {
18
+ const listener = (data, sendHandle) => {
12
19
  const msg = getMessage(type, data);
13
20
  if (msg) handler(msg, sendHandle);
14
- });
21
+ };
22
+ e.on("message", listener);
23
+ return () => {
24
+ e.off("message", listener);
25
+ };
26
+ }
27
+ function onMessageType(e, type, handler) {
28
+ subscribeToMessageType(e, type, handler);
29
+ return e;
15
30
  }
16
31
  function onceMessageType(e, type, handler) {
17
32
  const listener = (data, sendHandle) => {
@@ -112,7 +127,31 @@ function inProcChannel() {
112
127
  pid
113
128
  }))];
114
129
  }
130
+ /**
131
+ * Creates a {@link Worker} facade that broadcasts `send()` to all provided
132
+ * workers and aggregates their `'message'` events into one stream.
133
+ *
134
+ * This is useful for code that expects a single Worker for IPC (e.g.
135
+ * `handleProfzRequest`) but needs to reach multiple child workers.
136
+ */
137
+ function broadcastWorker(workers) {
138
+ const emitter = new EventEmitter();
139
+ for (const w of workers) w.on("message", (message, sendHandle) => emitter.emit("message", message, sendHandle));
140
+ const send = (message, sendHandle, callback) => {
141
+ for (const w of workers) w.send(message, sendHandle);
142
+ if (callback) callback(null);
143
+ return true;
144
+ };
145
+ const kill = (signal = "SIGTERM") => {
146
+ for (const w of workers) w.kill(signal);
147
+ };
148
+ return wrap(Object.assign(emitter, {
149
+ send,
150
+ kill,
151
+ pid
152
+ }));
153
+ }
115
154
  //#endregion
116
- export { childWorker, parentWorker, singleProcessMode };
155
+ export { broadcastWorker, childWorker, parentWorker, singleProcessMode, subscribeToMessageType };
117
156
 
118
157
  //# sourceMappingURL=processes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"processes.js","names":[],"sources":["../../../../../zero-cache/src/types/processes.ts"],"sourcesContent":["import {\n type ChildProcess,\n fork,\n type SendHandle,\n type Serializable,\n} from 'node:child_process';\nimport EventEmitter from 'node:events';\nimport {platform} from 'node:os';\nimport {pid} from 'node:process';\n\n/**\n * Central registry of message type names, which are used to identify\n * the payload in {@link Message} objects sent between processes. The\n * payloads themselves are implementation specific and defined in each\n * component; only the type name is reserved here to avoid collisions.\n *\n * Receiving logic can call {@link getMessage()} with the name of\n * the message of interest to filter messages to those of interest.\n */\nexport const MESSAGE_TYPES = {\n handoff: 'handoff',\n status: 'status',\n subscribe: 'subscribe',\n notify: 'notify',\n ready: 'ready',\n backupWatermarkUpdate: 'backupWatermakUpdate',\n} as const;\n\nexport type Message<Payload> = [keyof typeof MESSAGE_TYPES, Payload];\n\nfunction getMessage<M extends Message<unknown>>(\n type: M[0],\n data: unknown,\n): M[1] | null {\n if (Array.isArray(data) && data.length === 2 && data[0] === type) {\n return data[1] as M[1];\n }\n return null;\n}\n\nfunction onMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n) {\n return e.on('message', (data, sendHandle) => {\n const msg = getMessage(type, data);\n if (msg) {\n handler(msg, sendHandle);\n }\n });\n}\n\nfunction onceMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n) {\n const listener = (data: unknown, sendHandle: SendHandle) => {\n const msg = getMessage(type, data);\n if (msg) {\n e.off('message', listener);\n handler(msg, sendHandle);\n }\n };\n return e.on('message', listener);\n}\n\nexport interface Sender {\n send<M extends Message<unknown>>(\n message: M,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ): boolean;\n\n kill(signal?: NodeJS.Signals): void;\n}\n\nexport interface Subprocess extends Sender, EventEmitter {\n pid?: number | undefined;\n}\n\nexport interface Receiver extends EventEmitter {\n /**\n * The receiving side of {@link Sender.send()} that is a wrapper around\n * {@link on}('message', ...) that invokes the `handler` for messages of\n * the specified `type`.\n */\n onMessageType<M extends Message<unknown>>(\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n ): this;\n\n /**\n * The receiving side of {@link Sender.send()} that behaves like\n * {@link once}('message', ...) that invokes the `handler` for the next\n * message of the specified `type` and then unsubscribes.\n */\n onceMessageType<M extends Message<unknown>>(\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n ): this;\n}\n\nexport interface Worker extends Subprocess, Receiver {}\n\n/**\n * Adds the {@link Receiver.onMessageType()} and {@link Receiver.onceMessageType()}\n * methods to convert the given `EventEmitter` to a `Receiver`.\n */\nfunction wrap<P extends EventEmitter>(proc: P): P & Receiver {\n return new Proxy(proc, {\n get(target: P, prop: string | symbol, receiver: unknown) {\n switch (prop) {\n case 'onMessageType':\n return (\n type: keyof typeof MESSAGE_TYPES,\n handler: (msg: unknown, sendHandle?: SendHandle) => void,\n ) => {\n onMessageType(target, type, handler);\n return receiver; // this\n };\n case 'onceMessageType':\n return (\n type: keyof typeof MESSAGE_TYPES,\n handler: (msg: unknown, sendHandle?: SendHandle) => void,\n ) => {\n onceMessageType(target, type, handler);\n return receiver; // this\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n }) as P & Receiver;\n}\n\ntype Proc = Pick<ChildProcess, 'send' | 'kill' | 'pid'> & EventEmitter;\n\n/**\n * The parentWorker for forked processes, or `null` if the process was not forked.\n * (Analogous to the `parentPort: MessagePort | null` of the `\"workers\"` library).\n */\nexport const parentWorker: Worker | null = process.send\n ? wrap(process as Proc)\n : null;\n\nconst SINGLE_PROCESS = 'SINGLE_PROCESS';\nlet singleProcessOverride = false;\nexport function singleProcessMode(): boolean {\n return singleProcessOverride || (process.env[SINGLE_PROCESS] ?? '0') !== '0';\n}\n\nexport function setSingleProcessMode(enabled: boolean = true): void {\n singleProcessOverride = enabled;\n}\n\n/**\n * Determines whether a module loaded as a worker process entry point should\n * start its worker.\n *\n * Most workers are launched via {@link childWorker}, which in single-process\n * mode runs them in-process (no real fork) by invoking their exported\n * `runWorker` directly; those entry points must therefore *not* self-start in\n * single-process mode, or they would run twice.\n *\n * A worker launched via {@link forkChildWorker}, however, is *always* a real\n * forked OS process — even in single-process mode — and it inherits the\n * parent's `SINGLE_PROCESS` env. So {@link singleProcessMode} alone would\n * wrongly suppress its startup, leaving the parent to spin re-forking a child\n * that immediately exits. Such a forked child has a non-null\n * {@link parentWorker} (`process.send` is defined), which is the signal to\n * start regardless. A standalone direct launch (no parent, not single-process)\n * also starts.\n *\n * @param parent The entry point's {@link parentWorker} (non-null iff forked).\n * @param isSingleProcessMode The result of {@link singleProcessMode}.\n */\nexport function shouldStartWorker(\n parent: Worker | null,\n isSingleProcessMode: boolean,\n): boolean {\n return parent !== null || !isSingleProcessMode;\n}\n\n/**\n *\n * @param modulePath Path to the module file, relative to zero-cache/src/, or an absolute file:// URL\n */\nexport function childWorker(\n moduleUrl: URL,\n env?: NodeJS.ProcessEnv,\n ...args: string[]\n): Worker {\n args = workerArgs(args);\n\n if (singleProcessMode()) {\n const [parent, child] = inProcChannel();\n import(moduleUrl.href)\n .then(async ({default: runWorker}) => {\n try {\n await runWorker(parent, env ?? process.env, ...args);\n child.emit('close', 0);\n return;\n } catch (err) {\n child.emit('error', err);\n child.emit('close', -1);\n }\n })\n .catch(err => child.emit('error', err));\n return child;\n }\n return forkChildWorkerWithArgs(moduleUrl, env, args);\n}\n\nexport function forkChildWorker(\n moduleUrl: URL,\n env?: NodeJS.ProcessEnv,\n ...args: string[]\n): Worker {\n return forkChildWorkerWithArgs(moduleUrl, env, workerArgs(args));\n}\n\nfunction workerArgs(args: string[]): string[] {\n return [...args, ...process.argv.slice(2)];\n}\n\nfunction forkChildWorkerWithArgs(\n moduleUrl: URL,\n env: NodeJS.ProcessEnv | undefined,\n args: string[],\n): Worker {\n const child = fork(moduleUrl, args, {\n // For production / non-windows, set `detached` to `true` so that SIGINT is\n // not automatically propagated and graceful shutdown happens as intended.\n // For Win32, detached: true causes all subprocesses to open in separate\n // terminals and breaks inter-process kill signals, so set it to false.\n detached: platform() !== 'win32',\n serialization: 'advanced', // use structured clone for IPC\n env,\n });\n return wrap(child);\n}\n\n/**\n * Creates two connected `Worker` instances such that messages sent to one\n * via the {@link Worker.send()} method are received by the other's\n * `on('message', ...)` handler.\n *\n * This is analogous to the two `MessagePort`s of a `MessageChannel`, and\n * is useful for executing code written for inter-process communication\n * in a single process.\n */\nexport function inProcChannel(): [Worker, Worker] {\n const worker1 = new EventEmitter();\n const worker2 = new EventEmitter();\n\n const sendTo =\n (dest: EventEmitter) =>\n (\n message: Serializable,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ) => {\n dest.emit('message', message, sendHandle);\n if (callback) {\n callback(null);\n }\n return true;\n };\n\n const kill =\n (dest: EventEmitter) =>\n (signal: NodeJS.Signals = 'SIGTERM') =>\n dest.emit(signal, signal);\n\n return [\n wrap(\n Object.assign(worker1, {send: sendTo(worker2), kill: kill(worker2), pid}),\n ),\n wrap(\n Object.assign(worker2, {send: sendTo(worker1), kill: kill(worker1), pid}),\n ),\n ];\n}\n"],"mappings":";;;;;AA8BA,SAAS,WACP,MACA,MACa;CACb,IAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,KAAK,KAAK,OAAO,MAC1D,OAAO,KAAK;CAEd,OAAO;AACT;AAEA,SAAS,cACP,GACA,MACA,SACA;CACA,OAAO,EAAE,GAAG,YAAY,MAAM,eAAe;EAC3C,MAAM,MAAM,WAAW,MAAM,IAAI;EACjC,IAAI,KACF,QAAQ,KAAK,UAAU;CAE3B,CAAC;AACH;AAEA,SAAS,gBACP,GACA,MACA,SACA;CACA,MAAM,YAAY,MAAe,eAA2B;EAC1D,MAAM,MAAM,WAAW,MAAM,IAAI;EACjC,IAAI,KAAK;GACP,EAAE,IAAI,WAAW,QAAQ;GACzB,QAAQ,KAAK,UAAU;EACzB;CACF;CACA,OAAO,EAAE,GAAG,WAAW,QAAQ;AACjC;;;;;AA4CA,SAAS,KAA6B,MAAuB;CAC3D,OAAO,IAAI,MAAM,MAAM,EACrB,IAAI,QAAW,MAAuB,UAAmB;EACvD,QAAQ,MAAR;GACE,KAAK,iBACH,QACE,MACA,YACG;IACH,cAAc,QAAQ,MAAM,OAAO;IACnC,OAAO;GACT;GACF,KAAK,mBACH,QACE,MACA,YACG;IACH,gBAAgB,QAAQ,MAAM,OAAO;IACrC,OAAO;GACT;EACJ;EACA,OAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;CAC3C,EACF,CAAC;AACH;;;;;AAQA,IAAa,eAA8B,QAAQ,OAC/C,KAAK,OAAe,IACpB;AAEJ,IAAM,iBAAiB;AACvB,IAAI,wBAAwB;AAC5B,SAAgB,oBAA6B;CAC3C,OAAO,0BAA0B,QAAQ,IAAI,mBAAmB,SAAS;AAC3E;;;;;AAsCA,SAAgB,YACd,WACA,KACA,GAAG,MACK;CACR,OAAO,WAAW,IAAI;CAEtB,IAAI,kBAAkB,GAAG;EACvB,MAAM,CAAC,QAAQ,SAAS,cAAc;EACtC,OAAO,UAAU,MACd,KAAK,OAAO,EAAC,SAAS,gBAAe;GACpC,IAAI;IACF,MAAM,UAAU,QAAQ,OAAO,QAAQ,KAAK,GAAG,IAAI;IACnD,MAAM,KAAK,SAAS,CAAC;IACrB;GACF,SAAS,KAAK;IACZ,MAAM,KAAK,SAAS,GAAG;IACvB,MAAM,KAAK,SAAS,EAAE;GACxB;EACF,CAAC,EACA,OAAM,QAAO,MAAM,KAAK,SAAS,GAAG,CAAC;EACxC,OAAO;CACT;CACA,OAAO,wBAAwB,WAAW,KAAK,IAAI;AACrD;AAUA,SAAS,WAAW,MAA0B;CAC5C,OAAO,CAAC,GAAG,MAAM,GAAG,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC3C;AAEA,SAAS,wBACP,WACA,KACA,MACQ;CAUR,OAAO,KATO,KAAK,WAAW,MAAM;EAKlC,UAAU,SAAS,MAAM;EACzB,eAAe;EACf;CACF,CACY,CAAK;AACnB;;;;;;;;;;AAWA,SAAgB,gBAAkC;CAChD,MAAM,UAAU,IAAI,aAAa;CACjC,MAAM,UAAU,IAAI,aAAa;CAEjC,MAAM,UACH,UAEC,SACA,YACA,aACG;EACH,KAAK,KAAK,WAAW,SAAS,UAAU;EACxC,IAAI,UACF,SAAS,IAAI;EAEf,OAAO;CACT;CAEF,MAAM,QACH,UACA,SAAyB,cACxB,KAAK,KAAK,QAAQ,MAAM;CAE5B,OAAO,CACL,KACE,OAAO,OAAO,SAAS;EAAC,MAAM,OAAO,OAAO;EAAG,MAAM,KAAK,OAAO;EAAG;CAAG,CAAC,CAC1E,GACA,KACE,OAAO,OAAO,SAAS;EAAC,MAAM,OAAO,OAAO;EAAG,MAAM,KAAK,OAAO;EAAG;CAAG,CAAC,CAC1E,CACF;AACF"}
1
+ {"version":3,"file":"processes.js","names":[],"sources":["../../../../../zero-cache/src/types/processes.ts"],"sourcesContent":["import {\n type ChildProcess,\n fork,\n type SendHandle,\n type Serializable,\n} from 'node:child_process';\nimport EventEmitter from 'node:events';\nimport {platform} from 'node:os';\nimport {pid} from 'node:process';\n\n/**\n * Central registry of message type names, which are used to identify\n * the payload in {@link Message} objects sent between processes. The\n * payloads themselves are implementation specific and defined in each\n * component; only the type name is reserved here to avoid collisions.\n *\n * Receiving logic can call {@link getMessage()} with the name of\n * the message of interest to filter messages to those of interest.\n */\nexport const MESSAGE_TYPES = {\n handoff: 'handoff',\n status: 'status',\n subscribe: 'subscribe',\n notify: 'notify',\n ready: 'ready',\n backupWatermarkUpdate: 'backupWatermakUpdate',\n profile: 'profile',\n profileResponse: 'profileResponse',\n} as const;\n\nexport type ProfileRequest = {\n readonly id: string;\n readonly durationMs: number;\n readonly worker?: string | undefined;\n readonly workerIndex?: number | undefined;\n};\n\nexport type ProfileResponse = {\n readonly id: string;\n readonly name: string;\n readonly profile?: unknown | undefined;\n readonly error?: string | undefined;\n};\n\nexport type ProfileMessage = ['profile', ProfileRequest];\nexport type ProfileResponseMessage = ['profileResponse', ProfileResponse];\n\nexport type Message<Payload> = [keyof typeof MESSAGE_TYPES, Payload];\n\nfunction getMessage<M extends Message<unknown>>(\n type: M[0],\n data: unknown,\n): M[1] | null {\n if (Array.isArray(data) && data.length === 2 && data[0] === type) {\n return data[1] as M[1];\n }\n return null;\n}\n\n/**\n * Subscribes the `handler` to messages of the given `type` and returns a\n * function that unsubscribes it. Use this (rather than\n * {@link Receiver.onMessageType()}) for handlers scoped to a request or\n * operation rather than to the lifetime of the {@link Worker}; the\n * `'message'` listener is otherwise retained by the Worker forever.\n */\nexport function subscribeToMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n): () => void {\n const listener = (data: unknown, sendHandle?: SendHandle) => {\n const msg = getMessage(type, data);\n if (msg) {\n handler(msg, sendHandle);\n }\n };\n e.on('message', listener);\n return () => {\n e.off('message', listener);\n };\n}\n\nfunction onMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n) {\n subscribeToMessageType(e, type, handler);\n return e;\n}\n\nfunction onceMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n) {\n const listener = (data: unknown, sendHandle: SendHandle) => {\n const msg = getMessage(type, data);\n if (msg) {\n e.off('message', listener);\n handler(msg, sendHandle);\n }\n };\n return e.on('message', listener);\n}\n\nexport interface Sender {\n send<M extends Message<unknown>>(\n message: M,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ): boolean;\n\n kill(signal?: NodeJS.Signals): void;\n}\n\nexport interface Subprocess extends Sender, EventEmitter {\n pid?: number | undefined;\n}\n\nexport interface Receiver extends EventEmitter {\n /**\n * The receiving side of {@link Sender.send()} that is a wrapper around\n * {@link on}('message', ...) that invokes the `handler` for messages of\n * the specified `type`.\n */\n onMessageType<M extends Message<unknown>>(\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n ): this;\n\n /**\n * The receiving side of {@link Sender.send()} that behaves like\n * {@link once}('message', ...) that invokes the `handler` for the next\n * message of the specified `type` and then unsubscribes.\n */\n onceMessageType<M extends Message<unknown>>(\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n ): this;\n}\n\nexport interface Worker extends Subprocess, Receiver {}\n\n/**\n * Adds the {@link Receiver.onMessageType()} and {@link Receiver.onceMessageType()}\n * methods to convert the given `EventEmitter` to a `Receiver`.\n */\nfunction wrap<P extends EventEmitter>(proc: P): P & Receiver {\n return new Proxy(proc, {\n get(target: P, prop: string | symbol, receiver: unknown) {\n switch (prop) {\n case 'onMessageType':\n return (\n type: keyof typeof MESSAGE_TYPES,\n handler: (msg: unknown, sendHandle?: SendHandle) => void,\n ) => {\n onMessageType(target, type, handler);\n return receiver; // this\n };\n case 'onceMessageType':\n return (\n type: keyof typeof MESSAGE_TYPES,\n handler: (msg: unknown, sendHandle?: SendHandle) => void,\n ) => {\n onceMessageType(target, type, handler);\n return receiver; // this\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n }) as P & Receiver;\n}\n\ntype Proc = Pick<ChildProcess, 'send' | 'kill' | 'pid'> & EventEmitter;\n\n/**\n * The parentWorker for forked processes, or `null` if the process was not forked.\n * (Analogous to the `parentPort: MessagePort | null` of the `\"workers\"` library).\n */\nexport const parentWorker: Worker | null = process.send\n ? wrap(process as Proc)\n : null;\n\nconst SINGLE_PROCESS = 'SINGLE_PROCESS';\nlet singleProcessOverride = false;\nexport function singleProcessMode(): boolean {\n return singleProcessOverride || (process.env[SINGLE_PROCESS] ?? '0') !== '0';\n}\n\nexport function setSingleProcessMode(enabled: boolean = true): void {\n singleProcessOverride = enabled;\n}\n\n/**\n * Determines whether a module loaded as a worker process entry point should\n * start its worker.\n *\n * Most workers are launched via {@link childWorker}, which in single-process\n * mode runs them in-process (no real fork) by invoking their exported\n * `runWorker` directly; those entry points must therefore *not* self-start in\n * single-process mode, or they would run twice.\n *\n * A worker launched via {@link forkChildWorker}, however, is *always* a real\n * forked OS process — even in single-process mode — and it inherits the\n * parent's `SINGLE_PROCESS` env. So {@link singleProcessMode} alone would\n * wrongly suppress its startup, leaving the parent to spin re-forking a child\n * that immediately exits. Such a forked child has a non-null\n * {@link parentWorker} (`process.send` is defined), which is the signal to\n * start regardless. A standalone direct launch (no parent, not single-process)\n * also starts.\n *\n * @param parent The entry point's {@link parentWorker} (non-null iff forked).\n * @param isSingleProcessMode The result of {@link singleProcessMode}.\n */\nexport function shouldStartWorker(\n parent: Worker | null,\n isSingleProcessMode: boolean,\n): boolean {\n return parent !== null || !isSingleProcessMode;\n}\n\n/**\n *\n * @param modulePath Path to the module file, relative to zero-cache/src/, or an absolute file:// URL\n */\nexport function childWorker(\n moduleUrl: URL,\n env?: NodeJS.ProcessEnv,\n ...args: string[]\n): Worker {\n args = workerArgs(args);\n\n if (singleProcessMode()) {\n const [parent, child] = inProcChannel();\n import(moduleUrl.href)\n .then(async ({default: runWorker}) => {\n try {\n await runWorker(parent, env ?? process.env, ...args);\n child.emit('close', 0);\n return;\n } catch (err) {\n child.emit('error', err);\n child.emit('close', -1);\n }\n })\n .catch(err => child.emit('error', err));\n return child;\n }\n return forkChildWorkerWithArgs(moduleUrl, env, args);\n}\n\nexport function forkChildWorker(\n moduleUrl: URL,\n env?: NodeJS.ProcessEnv,\n ...args: string[]\n): Worker {\n return forkChildWorkerWithArgs(moduleUrl, env, workerArgs(args));\n}\n\nfunction workerArgs(args: string[]): string[] {\n return [...args, ...process.argv.slice(2)];\n}\n\nfunction forkChildWorkerWithArgs(\n moduleUrl: URL,\n env: NodeJS.ProcessEnv | undefined,\n args: string[],\n): Worker {\n const child = fork(moduleUrl, args, {\n // For production / non-windows, set `detached` to `true` so that SIGINT is\n // not automatically propagated and graceful shutdown happens as intended.\n // For Win32, detached: true causes all subprocesses to open in separate\n // terminals and breaks inter-process kill signals, so set it to false.\n detached: platform() !== 'win32',\n serialization: 'advanced', // use structured clone for IPC\n env,\n });\n return wrap(child);\n}\n\n/**\n * Creates two connected `Worker` instances such that messages sent to one\n * via the {@link Worker.send()} method are received by the other's\n * `on('message', ...)` handler.\n *\n * This is analogous to the two `MessagePort`s of a `MessageChannel`, and\n * is useful for executing code written for inter-process communication\n * in a single process.\n */\nexport function inProcChannel(): [Worker, Worker] {\n const worker1 = new EventEmitter();\n const worker2 = new EventEmitter();\n\n const sendTo =\n (dest: EventEmitter) =>\n (\n message: Serializable,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ) => {\n dest.emit('message', message, sendHandle);\n if (callback) {\n callback(null);\n }\n return true;\n };\n\n const kill =\n (dest: EventEmitter) =>\n (signal: NodeJS.Signals = 'SIGTERM') =>\n dest.emit(signal, signal);\n\n return [\n wrap(\n Object.assign(worker1, {send: sendTo(worker2), kill: kill(worker2), pid}),\n ),\n wrap(\n Object.assign(worker2, {send: sendTo(worker1), kill: kill(worker1), pid}),\n ),\n ];\n}\n\n/**\n * Creates a {@link Worker} facade that broadcasts `send()` to all provided\n * workers and aggregates their `'message'` events into one stream.\n *\n * This is useful for code that expects a single Worker for IPC (e.g.\n * `handleProfzRequest`) but needs to reach multiple child workers.\n */\nexport function broadcastWorker(workers: Worker[]): Worker {\n const emitter = new EventEmitter();\n\n for (const w of workers) {\n w.on('message', (message: Serializable, sendHandle?: SendHandle) =>\n emitter.emit('message', message, sendHandle),\n );\n }\n\n const send = <M extends Message<unknown>>(\n message: M,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ) => {\n for (const w of workers) {\n w.send(message, sendHandle);\n }\n if (callback) {\n callback(null);\n }\n return true;\n };\n\n const kill = (signal: NodeJS.Signals = 'SIGTERM') => {\n for (const w of workers) {\n w.kill(signal);\n }\n };\n\n return wrap(Object.assign(emitter, {send, kill, pid}));\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { LogContext } from '@rocicorp/logger';
2
+ import type { Worker } from './processes.ts';
2
3
  /**
3
4
  * Convenience wrapper around a `node:inspector` {@link Session} for
4
5
  * optionally taking cpu profiles.
@@ -8,6 +9,17 @@ export declare class CpuProfiler {
8
9
  static connect(): Promise<CpuProfiler>;
9
10
  private constructor();
10
11
  start(): Promise<void>;
12
+ /**
13
+ * Captures a CPU profile for the specified duration (in milliseconds)
14
+ * and returns the V8 profile object.
15
+ */
16
+ static profile(durationMs: number): Promise<unknown>;
17
+ stop(): Promise<unknown>;
11
18
  stopAndDispose(lc: LogContext, filename: string): Promise<void>;
12
19
  }
20
+ /**
21
+ * Registers an IPC handler on `parent` to capture a CPU profile when
22
+ * requested, sending back the resulting V8 profile.
23
+ */
24
+ export declare function installProfileHandler(parent: Worker | null, workerName: string, workerIndex?: number | undefined): void;
13
25
  //# sourceMappingURL=profiler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"profiler.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/profiler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD;;;GAGG;AACH,qBAAa,WAAW;;IACtB,OAAa,OAAO,yBAKnB;IAID,OAAO,eAEN;IAEK,KAAK,kBAEV;IAEK,cAAc,CAAC,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAMpD;CACF"}
1
+ {"version":3,"file":"profiler.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/profiler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAiB,MAAM,EAAC,MAAM,gBAAgB,CAAC;AAE3D;;;GAGG;AACH,qBAAa,WAAW;;IACtB,OAAa,OAAO,yBAKnB;IAID,OAAO,eAEN;IAEK,KAAK,kBAEV;IAED;;;OAGG;IACH,OAAa,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKzD;IAEK,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAK7B;IAEK,cAAc,CAAC,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAMpD;CACF;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,GAC/B,IAAI,CA6BN"}
@@ -21,6 +21,22 @@ var CpuProfiler = class CpuProfiler {
21
21
  async start() {
22
22
  await this.#session.post("Profiler.start");
23
23
  }
24
+ /**
25
+ * Captures a CPU profile for the specified duration (in milliseconds)
26
+ * and returns the V8 profile object.
27
+ */
28
+ static async profile(durationMs) {
29
+ const profiler = await CpuProfiler.connect();
30
+ await profiler.start();
31
+ await new Promise((resolve) => setTimeout(resolve, durationMs));
32
+ return await profiler.stop();
33
+ }
34
+ async stop() {
35
+ const { profile } = await this.#session.post("Profiler.stop");
36
+ await this.#session.post("Profiler.disable");
37
+ this.#session.disconnect();
38
+ return profile;
39
+ }
24
40
  async stopAndDispose(lc, filename) {
25
41
  const { profile } = await this.#session.post("Profiler.stop");
26
42
  const path = join(tmpdir(), `${filename}.cpuprofile`);
@@ -29,7 +45,36 @@ var CpuProfiler = class CpuProfiler {
29
45
  this.#session.disconnect();
30
46
  }
31
47
  };
48
+ var WORKER_INDEX_SUFFIX = /-\d+$/;
49
+ /**
50
+ * Registers an IPC handler on `parent` to capture a CPU profile when
51
+ * requested, sending back the resulting V8 profile.
52
+ */
53
+ function installProfileHandler(parent, workerName, workerIndex) {
54
+ if (!parent) return;
55
+ parent.onMessageType("profile", async (req) => {
56
+ if (req.worker !== void 0) {
57
+ const baseName = workerName.replace(WORKER_INDEX_SUFFIX, "");
58
+ if (!(req.worker === workerName || req.worker === baseName)) return;
59
+ if (req.workerIndex !== void 0 && workerIndex !== void 0 && req.workerIndex !== workerIndex) return;
60
+ }
61
+ try {
62
+ const profile = await CpuProfiler.profile(req.durationMs);
63
+ parent.send(["profileResponse", {
64
+ id: req.id,
65
+ name: workerName,
66
+ profile
67
+ }]);
68
+ } catch (err) {
69
+ parent.send(["profileResponse", {
70
+ id: req.id,
71
+ name: workerName,
72
+ error: String(err)
73
+ }]);
74
+ }
75
+ });
76
+ }
32
77
  //#endregion
33
- export { CpuProfiler };
78
+ export { CpuProfiler, installProfileHandler };
34
79
 
35
80
  //# sourceMappingURL=profiler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"profiler.js","names":["#session"],"sources":["../../../../../zero-cache/src/types/profiler.ts"],"sourcesContent":["import {writeFile} from 'node:fs/promises';\nimport {Session} from 'node:inspector/promises';\nimport {tmpdir} from 'node:os';\nimport {join} from 'node:path';\nimport type {LogContext} from '@rocicorp/logger';\n\n/**\n * Convenience wrapper around a `node:inspector` {@link Session} for\n * optionally taking cpu profiles.\n */\nexport class CpuProfiler {\n static async connect() {\n const session = new Session();\n session.connect();\n await session.post('Profiler.enable');\n return new CpuProfiler(session);\n }\n\n readonly #session;\n\n private constructor(session: Session) {\n this.#session = session;\n }\n\n async start() {\n await this.#session.post('Profiler.start');\n }\n\n async stopAndDispose(lc: LogContext, filename: string) {\n const {profile} = await this.#session.post('Profiler.stop');\n const path = join(tmpdir(), `${filename}.cpuprofile`);\n await writeFile(path, JSON.stringify(profile));\n lc.info?.(`wrote cpu profile to ${path}`);\n this.#session.disconnect();\n }\n}\n"],"mappings":";;;;;;;;;AAUA,IAAa,cAAb,MAAa,YAAY;CACvB,aAAa,UAAU;EACrB,MAAM,UAAU,IAAI,QAAQ;EAC5B,QAAQ,QAAQ;EAChB,MAAM,QAAQ,KAAK,iBAAiB;EACpC,OAAO,IAAI,YAAY,OAAO;CAChC;CAEA;CAEA,YAAoB,SAAkB;EACpC,KAAKA,WAAW;CAClB;CAEA,MAAM,QAAQ;EACZ,MAAM,KAAKA,SAAS,KAAK,gBAAgB;CAC3C;CAEA,MAAM,eAAe,IAAgB,UAAkB;EACrD,MAAM,EAAC,YAAW,MAAM,KAAKA,SAAS,KAAK,eAAe;EAC1D,MAAM,OAAO,KAAK,OAAO,GAAG,GAAG,SAAS,YAAY;EACpD,MAAM,UAAU,MAAM,KAAK,UAAU,OAAO,CAAC;EAC7C,GAAG,OAAO,wBAAwB,MAAM;EACxC,KAAKA,SAAS,WAAW;CAC3B;AACF"}
1
+ {"version":3,"file":"profiler.js","names":["#session"],"sources":["../../../../../zero-cache/src/types/profiler.ts"],"sourcesContent":["import {writeFile} from 'node:fs/promises';\nimport {Session} from 'node:inspector/promises';\nimport {tmpdir} from 'node:os';\nimport {join} from 'node:path';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {ProfileMessage, Worker} from './processes.ts';\n\n/**\n * Convenience wrapper around a `node:inspector` {@link Session} for\n * optionally taking cpu profiles.\n */\nexport class CpuProfiler {\n static async connect() {\n const session = new Session();\n session.connect();\n await session.post('Profiler.enable');\n return new CpuProfiler(session);\n }\n\n readonly #session;\n\n private constructor(session: Session) {\n this.#session = session;\n }\n\n async start() {\n await this.#session.post('Profiler.start');\n }\n\n /**\n * Captures a CPU profile for the specified duration (in milliseconds)\n * and returns the V8 profile object.\n */\n static async profile(durationMs: number): Promise<unknown> {\n const profiler = await CpuProfiler.connect();\n await profiler.start();\n await new Promise(resolve => setTimeout(resolve, durationMs));\n return await profiler.stop();\n }\n\n async stop(): Promise<unknown> {\n const {profile} = await this.#session.post('Profiler.stop');\n await this.#session.post('Profiler.disable');\n this.#session.disconnect();\n return profile;\n }\n\n async stopAndDispose(lc: LogContext, filename: string) {\n const {profile} = await this.#session.post('Profiler.stop');\n const path = join(tmpdir(), `${filename}.cpuprofile`);\n await writeFile(path, JSON.stringify(profile));\n lc.info?.(`wrote cpu profile to ${path}`);\n this.#session.disconnect();\n }\n}\n\nconst WORKER_INDEX_SUFFIX = /-\\d+$/;\n\n/**\n * Registers an IPC handler on `parent` to capture a CPU profile when\n * requested, sending back the resulting V8 profile.\n */\nexport function installProfileHandler(\n parent: Worker | null,\n workerName: string,\n workerIndex?: number | undefined,\n): void {\n if (!parent) {\n return;\n }\n parent.onMessageType<ProfileMessage>('profile', async req => {\n if (req.worker !== undefined) {\n const baseName = workerName.replace(WORKER_INDEX_SUFFIX, '');\n const matchesName = req.worker === workerName || req.worker === baseName;\n if (!matchesName) {\n return;\n }\n if (\n req.workerIndex !== undefined &&\n workerIndex !== undefined &&\n req.workerIndex !== workerIndex\n ) {\n return;\n }\n }\n try {\n const profile = await CpuProfiler.profile(req.durationMs);\n parent.send(['profileResponse', {id: req.id, name: workerName, profile}]);\n } catch (err) {\n parent.send([\n 'profileResponse',\n {id: req.id, name: workerName, error: String(err)},\n ]);\n }\n });\n}\n"],"mappings":";;;;;;;;;AAWA,IAAa,cAAb,MAAa,YAAY;CACvB,aAAa,UAAU;EACrB,MAAM,UAAU,IAAI,QAAQ;EAC5B,QAAQ,QAAQ;EAChB,MAAM,QAAQ,KAAK,iBAAiB;EACpC,OAAO,IAAI,YAAY,OAAO;CAChC;CAEA;CAEA,YAAoB,SAAkB;EACpC,KAAKA,WAAW;CAClB;CAEA,MAAM,QAAQ;EACZ,MAAM,KAAKA,SAAS,KAAK,gBAAgB;CAC3C;;;;;CAMA,aAAa,QAAQ,YAAsC;EACzD,MAAM,WAAW,MAAM,YAAY,QAAQ;EAC3C,MAAM,SAAS,MAAM;EACrB,MAAM,IAAI,SAAQ,YAAW,WAAW,SAAS,UAAU,CAAC;EAC5D,OAAO,MAAM,SAAS,KAAK;CAC7B;CAEA,MAAM,OAAyB;EAC7B,MAAM,EAAC,YAAW,MAAM,KAAKA,SAAS,KAAK,eAAe;EAC1D,MAAM,KAAKA,SAAS,KAAK,kBAAkB;EAC3C,KAAKA,SAAS,WAAW;EACzB,OAAO;CACT;CAEA,MAAM,eAAe,IAAgB,UAAkB;EACrD,MAAM,EAAC,YAAW,MAAM,KAAKA,SAAS,KAAK,eAAe;EAC1D,MAAM,OAAO,KAAK,OAAO,GAAG,GAAG,SAAS,YAAY;EACpD,MAAM,UAAU,MAAM,KAAK,UAAU,OAAO,CAAC;EAC7C,GAAG,OAAO,wBAAwB,MAAM;EACxC,KAAKA,SAAS,WAAW;CAC3B;AACF;AAEA,IAAM,sBAAsB;;;;;AAM5B,SAAgB,sBACd,QACA,YACA,aACM;CACN,IAAI,CAAC,QACH;CAEF,OAAO,cAA8B,WAAW,OAAM,QAAO;EAC3D,IAAI,IAAI,WAAW,KAAA,GAAW;GAC5B,MAAM,WAAW,WAAW,QAAQ,qBAAqB,EAAE;GAE3D,IAAI,EADgB,IAAI,WAAW,cAAc,IAAI,WAAW,WAE9D;GAEF,IACE,IAAI,gBAAgB,KAAA,KACpB,gBAAgB,KAAA,KAChB,IAAI,gBAAgB,aAEpB;EAEJ;EACA,IAAI;GACF,MAAM,UAAU,MAAM,YAAY,QAAQ,IAAI,UAAU;GACxD,OAAO,KAAK,CAAC,mBAAmB;IAAC,IAAI,IAAI;IAAI,MAAM;IAAY;GAAO,CAAC,CAAC;EAC1E,SAAS,KAAK;GACZ,OAAO,KAAK,CACV,mBACA;IAAC,IAAI,IAAI;IAAI,MAAM;IAAY,OAAO,OAAO,GAAG;GAAC,CACnD,CAAC;EACH;CACF,CAAC;AACH"}
@@ -34,6 +34,13 @@ export type Source<T> = AsyncIterable<T> & {
34
34
  value: T;
35
35
  consumed: () => void;
36
36
  }> | undefined;
37
+ /**
38
+ * Pipelined batching support: eagerly drains available queued messages up to `maxBatch`.
39
+ */
40
+ pipelineBatched?: ((maxBatch?: number) => AsyncIterable<{
41
+ values: T[];
42
+ consumed: () => void;
43
+ }> | undefined) | undefined;
37
44
  };
38
45
  export type Sink<T> = {
39
46
  push(message: T): void;
@@ -53,21 +60,30 @@ type PipeOptions<T> = {
53
60
  bufferMessages?: number;
54
61
  };
55
62
  export declare function pipe<T>({ source, sink, parse, bufferMessages }: PipeOptions<T>): void;
56
- /** A parsed JSON value paired with the exact source text it was parsed from. */
57
- export type ParsedJSON<T> = {
63
+ /** A parsed value paired with its approximate serialized transport size. */
64
+ export type Sized<T> = {
58
65
  data: T;
59
- json: string;
66
+ size: number;
67
+ };
68
+ export type StreamOutOptions = {
69
+ batched?: boolean | undefined;
70
+ maxBatchSize?: number | undefined;
71
+ };
72
+ export type PreSerialized = {
73
+ readonly payload: Buffer;
74
+ readonly byteLength: number;
60
75
  };
61
- export declare function streamOut<T extends JSONValue>(lc: LogContext, source: Source<T>, sink: WebSocket): Promise<void>;
76
+ export declare function isPreSerialized(val: unknown): val is PreSerialized;
77
+ export declare function streamOut<T extends JSONValue>(lc: LogContext, source: Source<T>, sink: WebSocket, options?: StreamOutOptions | undefined): Promise<void>;
62
78
  /**
63
- * Streams out a `Source` for which messages are already stringified JSON.
79
+ * Streams out a `Source` for which messages are already stringified JSON or pre-serialized Buffers.
64
80
  */
65
- export declare function streamOutStringified(lc: LogContext, source: Source<string>, sink: WebSocket): Promise<void>;
81
+ export declare function streamOutStringified(lc: LogContext, source: Source<string | PreSerialized>, sink: WebSocket, options?: StreamOutOptions | undefined): Promise<void>;
66
82
  export declare function streamIn<T extends JSONValue>(lc: LogContext, source: WebSocket, schema: v.Type<T>): Promise<Source<T>>;
67
83
  /**
68
- * Streams in messages sent by {@link streamOutStringified}, preserving the
69
- * exact application-level JSON alongside its parsed and validated value.
84
+ * Streams in parsed messages while retaining only the transport-frame size.
85
+ * The size bounds downstream batching without keeping or copying the JSON.
70
86
  */
71
- export declare function streamInStringified<T extends JSONValue>(lc: LogContext, source: WebSocket, schema: v.Type<T>): Promise<Source<ParsedJSON<T>>>;
87
+ export declare function streamInWithSize<T extends JSONValue>(lc: LogContext, source: WebSocket, schema: v.Type<T>): Promise<Source<Sized<T>>>;
72
88
  export {};
73
89
  //# sourceMappingURL=streams.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"streams.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/streams.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"streams.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/streams.ts"],"names":[],"mappings":"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"}
@@ -102,23 +102,30 @@ function ensureError(err) {
102
102
  return err instanceof Error ? err : new Error(String(err));
103
103
  }
104
104
  var ackSchema = valita_exports.object({ ack: valita_exports.number() });
105
- function streamOut(lc, source, sink) {
106
- return streamOutInternal(lc, source, sink, BigIntJSON.stringify);
105
+ function isPreSerialized(val) {
106
+ return typeof val === "object" && val !== null && "payload" in val && Buffer.isBuffer(val.payload);
107
+ }
108
+ function sendTextFrame(sink, data) {
109
+ if (typeof data === "string") sink.send(data);
110
+ else sink.send(data, { binary: false });
111
+ }
112
+ function streamOut(lc, source, sink, options) {
113
+ return streamOutInternal(lc, source, sink, BigIntJSON.stringify, options);
107
114
  }
108
115
  /**
109
- * Streams out a `Source` for which messages are already stringified JSON.
116
+ * Streams out a `Source` for which messages are already stringified JSON or pre-serialized Buffers.
110
117
  */
111
- function streamOutStringified(lc, source, sink) {
112
- return streamOutInternal(lc, source, sink, (json) => json);
118
+ function streamOutStringified(lc, source, sink, options) {
119
+ return streamOutInternal(lc, source, sink, (msg) => typeof msg === "string" ? msg : msg.payload.toString("utf8"), options);
113
120
  }
114
- async function streamOutInternal(lc, source, sink, stringify) {
121
+ async function streamOutInternal(lc, source, sink, stringify, options) {
115
122
  sendPingsForLiveness(lc, sink, PING_INTERVAL_MS);
116
123
  const closer = WebSocketCloser.forSource(lc, sink, source);
117
124
  const acks = new Queue();
118
125
  sink.addEventListener("message", ({ data }) => {
119
126
  try {
120
- if (typeof data !== "string") throw new Error("Expected string message");
121
- acks.enqueue(parse(JSON.parse(data), ackSchema));
127
+ const text = typeof data === "string" ? data : data.toString();
128
+ acks.enqueue(parse(JSON.parse(text), ackSchema));
122
129
  } catch (e) {
123
130
  lc.error?.(`error parsing ack`, e);
124
131
  closer.close(e);
@@ -127,24 +134,83 @@ async function streamOutInternal(lc, source, sink, stringify) {
127
134
  try {
128
135
  let nextID = 0;
129
136
  const { pipeline } = source;
137
+ const batched = options?.batched ?? false;
138
+ const maxBatchSize = Math.max(1, Math.floor(options?.maxBatchSize ?? 64));
139
+ if (batched && source.pipelineBatched) {
140
+ const batchedIterable = source.pipelineBatched(maxBatchSize);
141
+ if (batchedIterable) {
142
+ lc.debug?.(`started batched outbound stream (maxBatchSize=${maxBatchSize})`);
143
+ for await (const { values, consumed } of batchedIterable) if (values.length === 1 && isPreSerialized(values[0])) {
144
+ const id = ++nextID;
145
+ const prefix = Buffer.from(`{"id":${id}`);
146
+ sendTextFrame(sink, Buffer.concat([prefix, values[0].payload]));
147
+ (async () => {
148
+ const { ack } = await acks.dequeue();
149
+ if (ack !== id) throw new Error(`Unexpected ack for ${id}: ${ack}`);
150
+ consumed();
151
+ })().catch((e) => closer.close(e));
152
+ } else if (values.some(isPreSerialized)) {
153
+ let remaining = values.length;
154
+ const onConsumed = () => {
155
+ if (--remaining === 0) consumed();
156
+ };
157
+ for (const val of values) {
158
+ const id = ++nextID;
159
+ if (isPreSerialized(val)) {
160
+ const prefix = Buffer.from(`{"id":${id}`);
161
+ sendTextFrame(sink, Buffer.concat([prefix, val.payload]));
162
+ } else {
163
+ const data = `{"id":${id},"msg":${stringify(val)}}`;
164
+ sink.send(data);
165
+ }
166
+ (async () => {
167
+ const { ack } = await acks.dequeue();
168
+ if (ack !== id) throw new Error(`Unexpected ack for ${id}: ${ack}`);
169
+ onConsumed();
170
+ })().catch((e) => closer.close(e));
171
+ }
172
+ } else {
173
+ const id = ++nextID;
174
+ const data = values.length === 1 ? `{"id":${id},"msg":${stringify(values[0])}}` : `{"id":${id},"batch":[${values.map(stringify).join(",")}]}`;
175
+ sink.send(data);
176
+ (async () => {
177
+ const { ack } = await acks.dequeue();
178
+ if (ack !== id) throw new Error(`Unexpected ack for ${id}: ${ack}`);
179
+ consumed();
180
+ })().catch((e) => closer.close(e));
181
+ }
182
+ closer.close();
183
+ return;
184
+ }
185
+ }
130
186
  if (pipeline) {
131
187
  lc.debug?.(`started pipelined outbound stream`);
132
188
  for await (const { value: msg, consumed } of pipeline) {
133
189
  const id = ++nextID;
134
- const data = `{"id":${id},"msg":${stringify(msg)}}`;
135
- sink.send(data);
190
+ if (isPreSerialized(msg)) {
191
+ const prefix = Buffer.from(`{"id":${id}`);
192
+ sendTextFrame(sink, Buffer.concat([prefix, msg.payload]));
193
+ } else {
194
+ const data = `{"id":${id},"msg":${stringify(msg)}}`;
195
+ sink.send(data);
196
+ }
136
197
  (async () => {
137
198
  const { ack } = await acks.dequeue();
138
199
  if (ack !== id) throw new Error(`Unexpected ack for ${id}: ${ack}`);
139
200
  consumed();
140
- })();
201
+ })().catch((e) => closer.close(e));
141
202
  }
142
203
  } else {
143
204
  lc.debug?.(`started synchronous outbound stream`);
144
205
  for await (const msg of source) {
145
206
  const id = ++nextID;
146
- const data = `{"id":${id},"msg":${stringify(msg)}}`;
147
- sink.send(data);
207
+ if (isPreSerialized(msg)) {
208
+ const prefix = Buffer.from(`{"id":${id}`);
209
+ sendTextFrame(sink, Buffer.concat([prefix, msg.payload]));
210
+ } else {
211
+ const data = `{"id":${id},"msg":${stringify(msg)}}`;
212
+ sink.send(data);
213
+ }
148
214
  const { ack } = await acks.dequeue();
149
215
  if (ack !== id) throw new Error(`Unexpected ack for ${id}: ${ack}`);
150
216
  }
@@ -158,23 +224,24 @@ function streamIn(lc, source, schema) {
158
224
  return streamInInternal(lc, source, schema, (data) => data);
159
225
  }
160
226
  /**
161
- * Streams in messages sent by {@link streamOutStringified}, preserving the
162
- * exact application-level JSON alongside its parsed and validated value.
227
+ * Streams in parsed messages while retaining only the transport-frame size.
228
+ * The size bounds downstream batching without keeping or copying the JSON.
163
229
  */
164
- function streamInStringified(lc, source, schema) {
165
- return streamInInternal(lc, source, schema, (data, frame, id) => ({
230
+ function streamInWithSize(lc, source, schema) {
231
+ return streamInInternal(lc, source, schema, (data, _frame, _id, size) => ({
166
232
  data,
167
- json: extractStringifiedMessage(frame, id)
233
+ size
168
234
  }));
169
235
  }
170
236
  async function streamInInternal(lc, source, schema, transform) {
171
237
  expectPingsForLiveness(lc, source, PING_INTERVAL_MS);
172
238
  const streamedSchema = valita_exports.object({
173
- msg: schema,
174
- id: valita_exports.number()
239
+ id: valita_exports.number(),
240
+ msg: schema.optional(),
241
+ batch: valita_exports.array(schema).optional()
175
242
  });
176
243
  const sink = new Subscription({
177
- consumed: ({ id }) => source.send(JSON.stringify({ ack: id })),
244
+ consumed: ({ consumed }) => consumed(),
178
245
  cleanup: () => closer.close()
179
246
  }, ({ data }) => data);
180
247
  const closer = WebSocketCloser.forSink(lc, source, sink, handleMessage);
@@ -185,11 +252,30 @@ async function streamInInternal(lc, source, schema, transform) {
185
252
  return;
186
253
  }
187
254
  try {
188
- const msg = parse(BigIntJSON.parse(data), streamedSchema, "passthrough");
189
- sink.push({
190
- id: msg.id,
191
- data: transform(msg.msg, data, msg.id)
255
+ const { id, msg, batch } = parse(BigIntJSON.parse(data), streamedSchema, "passthrough");
256
+ const sendAck = () => {
257
+ if (source.readyState === source.OPEN) source.send(JSON.stringify({ ack: id }));
258
+ };
259
+ if (batch !== void 0 && msg !== void 0) throw new Error(`Message ${id} has both "msg" and "batch"`);
260
+ if (batch !== void 0) {
261
+ let remaining = batch.length;
262
+ if (remaining === 0) {
263
+ sendAck();
264
+ return;
265
+ }
266
+ const onConsumed = () => {
267
+ if (--remaining === 0) sendAck();
268
+ };
269
+ const itemSize = Math.max(1, Math.round(data.length / batch.length));
270
+ for (const item of batch) sink.push({
271
+ consumed: onConsumed,
272
+ data: transform(item, data, id, itemSize)
273
+ });
274
+ } else if (msg !== void 0) sink.push({
275
+ consumed: sendAck,
276
+ data: transform(msg, data, id, data.length)
192
277
  });
278
+ else throw new Error(`Message ${id} has neither "msg" nor "batch"`);
193
279
  } catch (e) {
194
280
  closer.close(e);
195
281
  }
@@ -197,11 +283,6 @@ async function streamInInternal(lc, source, schema, transform) {
197
283
  await closer.connected;
198
284
  return sink;
199
285
  }
200
- function extractStringifiedMessage(frame, id) {
201
- const prefix = `{"id":${id},"msg":`;
202
- assert(frame.startsWith(prefix) && frame.endsWith("}"), `invalid streamed message frame`);
203
- return frame.slice(prefix.length, -1);
204
- }
205
286
  var WebSocketCloser = class WebSocketCloser {
206
287
  #lc;
207
288
  #ws;
@@ -212,10 +293,13 @@ var WebSocketCloser = class WebSocketCloser {
212
293
  return this.#connected.promise;
213
294
  }
214
295
  static forSource(lc, ws, stream) {
215
- return new WebSocketCloser(lc, ws, () => stream.cancel());
296
+ return new WebSocketCloser(lc, ws, (err) => stream.cancel(err instanceof Error ? err : void 0));
216
297
  }
217
298
  static forSink(lc, ws, stream, messageHandler) {
218
- return new WebSocketCloser(lc, ws, () => stream.end(), messageHandler);
299
+ return new WebSocketCloser(lc, ws, (err) => {
300
+ if (err) stream.fail(err instanceof Error ? err : new Error(String(err)));
301
+ else stream.end();
302
+ }, messageHandler);
219
303
  }
220
304
  constructor(lc, ws, closeStream, messageHandler) {
221
305
  this.#lc = lc;
@@ -259,7 +343,7 @@ var WebSocketCloser = class WebSocketCloser {
259
343
  };
260
344
  close(err) {
261
345
  if (err) this.#lc.error?.(`closing stream with error`, err);
262
- this.#closeStream();
346
+ this.#closeStream(err);
263
347
  if (!this.closed()) this.#ws.close();
264
348
  }
265
349
  closed() {
@@ -267,6 +351,6 @@ var WebSocketCloser = class WebSocketCloser {
267
351
  }
268
352
  };
269
353
  //#endregion
270
- export { pipe, stream, streamIn, streamInStringified, streamOut, streamOutStringified };
354
+ export { pipe, stream, streamIn, streamInWithSize, streamOut, streamOutStringified };
271
355
 
272
356
  //# sourceMappingURL=streams.js.map