@sixb/core 0.1.9 → 0.1.11

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 (328) hide show
  1. package/dist/actions/index.js +9 -9
  2. package/dist/agents/index.js +17 -16
  3. package/dist/agents/index.js.map +1 -1
  4. package/dist/blob-storage/types.d.ts +4 -1
  5. package/dist/blob-storage/types.d.ts.map +1 -1
  6. package/dist/bootstrap/index.js +21 -20
  7. package/dist/bootstrap/index.js.map +1 -1
  8. package/dist/broker/in-memory.d.ts +8 -2
  9. package/dist/broker/in-memory.d.ts.map +1 -1
  10. package/dist/broker/index.d.ts +4 -2
  11. package/dist/broker/index.d.ts.map +1 -1
  12. package/dist/broker/index.js +7 -3
  13. package/dist/broker/index.js.map +1 -1
  14. package/dist/broker/retention.d.ts +4 -0
  15. package/dist/broker/retention.d.ts.map +1 -0
  16. package/dist/broker/subscriber.d.ts +10 -0
  17. package/dist/broker/subscriber.d.ts.map +1 -0
  18. package/dist/broker/types.d.ts +14 -1
  19. package/dist/broker/types.d.ts.map +1 -1
  20. package/dist/{chunk-ypbtykv6.js → chunk-01kj2pbh.js} +1 -1
  21. package/dist/{chunk-k3cqkkn2.js → chunk-1824gssz.js} +30 -65
  22. package/dist/chunk-1824gssz.js.map +12 -0
  23. package/dist/{chunk-xyr8kppc.js → chunk-1yefycb1.js} +1 -1
  24. package/dist/chunk-2c4j899j.js.map +1 -1
  25. package/dist/{chunk-ppytyr6w.js → chunk-358caqf5.js} +4 -4
  26. package/dist/chunk-358caqf5.js.map +12 -0
  27. package/dist/{chunk-m3z3x9v0.js → chunk-3ckk0xfj.js} +2 -2
  28. package/dist/{chunk-kxwa347f.js → chunk-3qms4nax.js} +2 -2
  29. package/dist/{chunk-kxwa347f.js.map → chunk-3qms4nax.js.map} +3 -3
  30. package/dist/{chunk-52hbv0ak.js → chunk-4zhmdsx6.js} +141 -55
  31. package/dist/chunk-4zhmdsx6.js.map +36 -0
  32. package/dist/{chunk-zcnq6105.js → chunk-85cd7e8c.js} +2 -1
  33. package/dist/chunk-85cd7e8c.js.map +10 -0
  34. package/dist/{chunk-3f7veca0.js → chunk-9x8dybsb.js} +3 -3
  35. package/dist/chunk-9x8dybsb.js.map +10 -0
  36. package/dist/{chunk-0w35wavj.js → chunk-a0e6x5hd.js} +1 -1
  37. package/dist/{chunk-r29fxdhn.js → chunk-aa6z4a19.js} +160 -44
  38. package/dist/chunk-aa6z4a19.js.map +12 -0
  39. package/dist/{chunk-emyyk7dx.js → chunk-cfvakeax.js} +22 -145
  40. package/dist/chunk-cfvakeax.js.map +12 -0
  41. package/dist/chunk-d62kjtbg.js.map +1 -1
  42. package/dist/{chunk-h1gfhhbh.js → chunk-d63nnr5b.js} +2 -2
  43. package/dist/{chunk-r4tfx1sf.js → chunk-fh8kgex1.js} +5 -5
  44. package/dist/{chunk-an5tt9y0.js → chunk-ftv470j8.js} +42 -4
  45. package/dist/{chunk-an5tt9y0.js.map → chunk-ftv470j8.js.map} +7 -7
  46. package/dist/{chunk-jjy0fhrn.js → chunk-g91qxjj0.js} +20 -3
  47. package/dist/chunk-g91qxjj0.js.map +12 -0
  48. package/dist/{chunk-hpr1r6av.js → chunk-gq8vhakp.js} +51 -40
  49. package/dist/{chunk-hpr1r6av.js.map → chunk-gq8vhakp.js.map} +6 -6
  50. package/dist/{chunk-x57ycxq0.js → chunk-gqh45d2n.js} +42 -3
  51. package/dist/{chunk-x57ycxq0.js.map → chunk-gqh45d2n.js.map} +3 -3
  52. package/dist/{chunk-mjbk2djy.js → chunk-gqm76kse.js} +231 -125
  53. package/dist/{chunk-mjbk2djy.js.map → chunk-gqm76kse.js.map} +9 -8
  54. package/dist/{chunk-e0d1rzef.js → chunk-jsy70480.js} +16 -3
  55. package/dist/chunk-jsy70480.js.map +15 -0
  56. package/dist/{chunk-0rdrecsb.js → chunk-kfee1h52.js} +116 -32
  57. package/dist/chunk-kfee1h52.js.map +13 -0
  58. package/dist/{chunk-3frsnm7x.js → chunk-qma80ych.js} +4 -6
  59. package/dist/chunk-qma80ych.js.map +11 -0
  60. package/dist/{chunk-vf691g1r.js → chunk-sepyxgpc.js} +3 -3
  61. package/dist/chunk-v2vcg0w6.js +151 -0
  62. package/dist/chunk-v2vcg0w6.js.map +11 -0
  63. package/dist/{chunk-3tgwrcyh.js → chunk-wf88w4kp.js} +17 -23
  64. package/dist/chunk-wf88w4kp.js.map +14 -0
  65. package/dist/{chunk-xfbydgzy.js → chunk-x9m9x2eq.js} +7 -8
  66. package/dist/{chunk-xfbydgzy.js.map → chunk-x9m9x2eq.js.map} +3 -3
  67. package/dist/{chunk-qhcpj9wc.js → chunk-z0271qkp.js} +98 -2
  68. package/dist/chunk-z0271qkp.js.map +15 -0
  69. package/dist/{chunk-1enhpacz.js → chunk-z0s4axeh.js} +6 -6
  70. package/dist/connectors/connections/authorizations.d.ts.map +1 -1
  71. package/dist/connectors/connections/command-context.d.ts +2 -0
  72. package/dist/connectors/connections/command-context.d.ts.map +1 -1
  73. package/dist/connectors/connections/contracts.d.ts +4 -1
  74. package/dist/connectors/connections/contracts.d.ts.map +1 -1
  75. package/dist/connectors/connections/execution.d.ts +1 -0
  76. package/dist/connectors/connections/execution.d.ts.map +1 -1
  77. package/dist/connectors/connections/internal.js +1 -1
  78. package/dist/connectors/connections/request.d.ts +3 -1
  79. package/dist/connectors/connections/request.d.ts.map +1 -1
  80. package/dist/connectors/connections/runs.d.ts +1 -0
  81. package/dist/connectors/connections/runs.d.ts.map +1 -1
  82. package/dist/connectors/connections/service.d.ts +2 -0
  83. package/dist/connectors/connections/service.d.ts.map +1 -1
  84. package/dist/connectors/connections/tokens.d.ts.map +1 -1
  85. package/dist/connectors/connections/validation.d.ts +5 -1
  86. package/dist/connectors/connections/validation.d.ts.map +1 -1
  87. package/dist/connectors/types.d.ts +19 -4
  88. package/dist/connectors/types.d.ts.map +1 -1
  89. package/dist/events/execution.d.ts +1 -1
  90. package/dist/events/execution.d.ts.map +1 -1
  91. package/dist/events/index.js +1 -1
  92. package/dist/events/outbox-dispatcher.d.ts +2 -2
  93. package/dist/events/outbox-dispatcher.d.ts.map +1 -1
  94. package/dist/events/service.d.ts +2 -2
  95. package/dist/events/service.d.ts.map +1 -1
  96. package/dist/execution/agent.js +17 -16
  97. package/dist/execution/agent.js.map +1 -1
  98. package/dist/execution/primitive.js +17 -16
  99. package/dist/execution/primitive.js.map +2 -2
  100. package/dist/execution/request.js +17 -16
  101. package/dist/execution/request.js.map +2 -2
  102. package/dist/index.d.ts +3 -3
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +31 -29
  105. package/dist/index.js.map +1 -1
  106. package/dist/lake-storage/changes.d.ts +5 -0
  107. package/dist/lake-storage/changes.d.ts.map +1 -0
  108. package/dist/lake-storage/in-memory.d.ts +2 -1
  109. package/dist/lake-storage/in-memory.d.ts.map +1 -1
  110. package/dist/lake-storage/index.d.ts +2 -1
  111. package/dist/lake-storage/index.d.ts.map +1 -1
  112. package/dist/lake-storage/index.js +4 -2
  113. package/dist/lake-storage/index.js.map +1 -1
  114. package/dist/lake-storage/types.d.ts +38 -0
  115. package/dist/lake-storage/types.d.ts.map +1 -1
  116. package/dist/logging/internal.js +1 -1
  117. package/dist/maintenance/ontology-maintenance.d.ts.map +1 -1
  118. package/dist/maintenance/types.d.ts +1 -1
  119. package/dist/maintenance/types.d.ts.map +1 -1
  120. package/dist/materialization/index.d.ts +1 -1
  121. package/dist/materialization/index.d.ts.map +1 -1
  122. package/dist/materialization/model.d.ts +12 -1
  123. package/dist/materialization/model.d.ts.map +1 -1
  124. package/dist/materializer/index.d.ts +1 -1
  125. package/dist/materializer/index.d.ts.map +1 -1
  126. package/dist/materializer/index.js +6 -6
  127. package/dist/materializer/materializer.d.ts +5 -1
  128. package/dist/materializer/materializer.d.ts.map +1 -1
  129. package/dist/materializer/projections/entry-validator.d.ts +2 -1
  130. package/dist/materializer/projections/entry-validator.d.ts.map +1 -1
  131. package/dist/materializer/projections/replace.d.ts.map +1 -1
  132. package/dist/materializer/projections/source-materialization.d.ts +4 -3
  133. package/dist/materializer/projections/source-materialization.d.ts.map +1 -1
  134. package/dist/materializer/shared/normalize.d.ts +2 -1
  135. package/dist/materializer/shared/normalize.d.ts.map +1 -1
  136. package/dist/models/definitions.d.ts +7 -0
  137. package/dist/models/definitions.d.ts.map +1 -1
  138. package/dist/models/execution/index.js +6 -6
  139. package/dist/models/index.js +1 -1
  140. package/dist/objects/index.js +10 -10
  141. package/dist/objects/query/index.js +6 -6
  142. package/dist/pipelines/index.js +7 -7
  143. package/dist/pipelines/run-dispatch.d.ts.map +1 -1
  144. package/dist/projections/internal.js +7 -9
  145. package/dist/projections/internal.js.map +1 -1
  146. package/dist/projections/run-dispatch.d.ts.map +1 -1
  147. package/dist/queues/in-memory.d.ts +7 -3
  148. package/dist/queues/in-memory.d.ts.map +1 -1
  149. package/dist/queues/index.js +1 -1
  150. package/dist/queues/indexed-heap.d.ts +15 -0
  151. package/dist/queues/indexed-heap.d.ts.map +1 -0
  152. package/dist/runtime/host.d.ts.map +1 -1
  153. package/dist/runtime/internal.js +1 -1
  154. package/dist/runtime/ontology-mutations.d.ts +3 -1
  155. package/dist/runtime/ontology-mutations.d.ts.map +1 -1
  156. package/dist/shares/internal.js +5 -5
  157. package/dist/storage/agents/provider.js +1 -1
  158. package/dist/storage/connector-connections/in-memory.d.ts +1 -0
  159. package/dist/storage/connector-connections/in-memory.d.ts.map +1 -1
  160. package/dist/storage/connector-connections/provider/connections.d.ts.map +1 -1
  161. package/dist/storage/connector-connections/provider/runs.d.ts +1 -0
  162. package/dist/storage/connector-connections/provider/runs.d.ts.map +1 -1
  163. package/dist/storage/connector-connections/provider/shared.d.ts +1 -0
  164. package/dist/storage/connector-connections/provider/shared.d.ts.map +1 -1
  165. package/dist/storage/connector-connections/provider.d.ts +1 -0
  166. package/dist/storage/connector-connections/provider.d.ts.map +1 -1
  167. package/dist/storage/connector-connections/provider.js +11 -17
  168. package/dist/storage/connector-connections/provider.js.map +6 -6
  169. package/dist/storage/connector-connections/types.d.ts +6 -3
  170. package/dist/storage/connector-connections/types.d.ts.map +1 -1
  171. package/dist/storage/index.d.ts +1 -1
  172. package/dist/storage/index.d.ts.map +1 -1
  173. package/dist/storage/index.js +5 -5
  174. package/dist/storage/internal.js +1 -1
  175. package/dist/storage/ontology/in-memory/materializations-state.d.ts.map +1 -1
  176. package/dist/storage/ontology/in-memory/materializations.d.ts +1 -1
  177. package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
  178. package/dist/storage/ontology/in-memory/shared-state.d.ts +15 -2
  179. package/dist/storage/ontology/in-memory/shared-state.d.ts.map +1 -1
  180. package/dist/storage/ontology/in-memory/source-roots.d.ts +6 -0
  181. package/dist/storage/ontology/in-memory/source-roots.d.ts.map +1 -0
  182. package/dist/storage/ontology/in-memory/sources.d.ts.map +1 -1
  183. package/dist/storage/ontology/index.d.ts +1 -1
  184. package/dist/storage/ontology/index.d.ts.map +1 -1
  185. package/dist/storage/ontology/outbox.d.ts +1 -0
  186. package/dist/storage/ontology/outbox.d.ts.map +1 -1
  187. package/dist/storage/ontology/provider.d.ts +16 -0
  188. package/dist/storage/ontology/provider.d.ts.map +1 -1
  189. package/dist/storage/ontology/provider.js +4 -2
  190. package/dist/storage/ontology/provider.js.map +1 -1
  191. package/dist/storage/ontology/sources.d.ts +13 -4
  192. package/dist/storage/ontology/sources.d.ts.map +1 -1
  193. package/dist/storage/projection-runs/lifecycle.d.ts.map +1 -1
  194. package/dist/storage/projection-runs/provider.js +2 -2
  195. package/dist/storage/projection-runs/types.d.ts +2 -0
  196. package/dist/storage/projection-runs/types.d.ts.map +1 -1
  197. package/dist/syncs/index.js +9 -8
  198. package/dist/syncs/index.js.map +1 -1
  199. package/dist/syncs/run-dispatch.d.ts.map +1 -1
  200. package/dist/testing/broker-contract.d.ts.map +1 -1
  201. package/dist/testing/connector-connection-storage-contract.d.ts.map +1 -1
  202. package/dist/testing/index.d.ts +1 -0
  203. package/dist/testing/index.d.ts.map +1 -1
  204. package/dist/testing/index.js +1499 -963
  205. package/dist/testing/index.js.map +10 -9
  206. package/dist/testing/lake-changes-contract.d.ts +6 -0
  207. package/dist/testing/lake-changes-contract.d.ts.map +1 -0
  208. package/dist/testing/lake-storage-contract.d.ts.map +1 -1
  209. package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
  210. package/dist/testing/ontology-storage-contract.d.ts.map +1 -1
  211. package/dist/testing/projection-run-storage-contract.d.ts.map +1 -1
  212. package/dist/webhooks/connections.d.ts +6 -0
  213. package/dist/webhooks/connections.d.ts.map +1 -0
  214. package/dist/webhooks/index.d.ts +1 -1
  215. package/dist/webhooks/index.d.ts.map +1 -1
  216. package/dist/webhooks/internal.d.ts +2 -0
  217. package/dist/webhooks/internal.d.ts.map +1 -1
  218. package/dist/webhooks/internal.js +55 -10
  219. package/dist/webhooks/internal.js.map +4 -3
  220. package/dist/webhooks/registry.d.ts +1 -1
  221. package/dist/webhooks/registry.d.ts.map +1 -1
  222. package/dist/webhooks/types.d.ts +15 -4
  223. package/dist/webhooks/types.d.ts.map +1 -1
  224. package/dist/workflows/index.js +18 -17
  225. package/dist/workflows/index.js.map +1 -1
  226. package/dist/workflows/run-dispatch.d.ts +3 -1
  227. package/dist/workflows/run-dispatch.d.ts.map +1 -1
  228. package/package.json +1 -1
  229. package/src/agents/model-loop.ts +7 -0
  230. package/src/blob-storage/types.ts +4 -1
  231. package/src/broker/in-memory.ts +104 -39
  232. package/src/broker/index.ts +4 -1
  233. package/src/broker/retention.ts +28 -0
  234. package/src/broker/subscriber.ts +21 -0
  235. package/src/broker/types.ts +15 -1
  236. package/src/connectors/builders.ts +0 -6
  237. package/src/connectors/connections/authorizations.ts +11 -5
  238. package/src/connectors/connections/command-context.ts +21 -4
  239. package/src/connectors/connections/contracts.ts +7 -1
  240. package/src/connectors/connections/execution.ts +3 -0
  241. package/src/connectors/connections/request.ts +56 -22
  242. package/src/connectors/connections/runs.ts +39 -1
  243. package/src/connectors/connections/service.ts +6 -0
  244. package/src/connectors/connections/tokens.ts +4 -0
  245. package/src/connectors/connections/validation.ts +91 -5
  246. package/src/connectors/types.ts +19 -4
  247. package/src/events/execution.ts +2 -2
  248. package/src/events/outbox-dispatcher.ts +20 -26
  249. package/src/events/service.ts +3 -3
  250. package/src/index.ts +10 -2
  251. package/src/lake-storage/changes.ts +43 -0
  252. package/src/lake-storage/in-memory.ts +75 -0
  253. package/src/lake-storage/index.ts +4 -0
  254. package/src/lake-storage/types.ts +42 -0
  255. package/src/logging/service.ts +1 -1
  256. package/src/maintenance/ontology-maintenance.ts +6 -2
  257. package/src/maintenance/types.ts +1 -1
  258. package/src/materialization/index.ts +2 -0
  259. package/src/materialization/model.ts +14 -1
  260. package/src/materializer/README.md +1 -1
  261. package/src/materializer/index.ts +2 -0
  262. package/src/materializer/materializer.ts +10 -0
  263. package/src/materializer/projections/entry-validator.ts +19 -1
  264. package/src/materializer/projections/replace.ts +36 -1
  265. package/src/materializer/projections/source-materialization.ts +26 -6
  266. package/src/materializer/shared/normalize.ts +1 -1
  267. package/src/models/definitions.ts +19 -0
  268. package/src/models/pricing.ts +6 -2
  269. package/src/pipelines/run-dispatch.ts +21 -1
  270. package/src/projections/run-dispatch.ts +30 -68
  271. package/src/queues/in-memory.ts +105 -62
  272. package/src/queues/indexed-heap.ts +74 -0
  273. package/src/runtime/host.ts +0 -14
  274. package/src/runtime/ontology-mutations.ts +4 -0
  275. package/src/storage/connector-connections/in-memory.ts +19 -19
  276. package/src/storage/connector-connections/provider/connections.ts +1 -15
  277. package/src/storage/connector-connections/provider/runs.ts +9 -1
  278. package/src/storage/connector-connections/provider/shared.ts +2 -3
  279. package/src/storage/connector-connections/provider.ts +6 -0
  280. package/src/storage/connector-connections/types.ts +8 -3
  281. package/src/storage/index.ts +1 -0
  282. package/src/storage/ontology/in-memory/materializations-state.ts +5 -18
  283. package/src/storage/ontology/in-memory/materializations.ts +73 -92
  284. package/src/storage/ontology/in-memory/shared-state.ts +36 -4
  285. package/src/storage/ontology/in-memory/source-roots.ts +123 -0
  286. package/src/storage/ontology/in-memory/sources.ts +78 -23
  287. package/src/storage/ontology/index.ts +1 -0
  288. package/src/storage/ontology/outbox.ts +1 -0
  289. package/src/storage/ontology/provider.ts +70 -0
  290. package/src/storage/ontology/sources.ts +14 -3
  291. package/src/storage/projection-runs/lifecycle.ts +5 -2
  292. package/src/storage/projection-runs/types.ts +4 -3
  293. package/src/syncs/run-dispatch.ts +19 -1
  294. package/src/testing/broker-contract.ts +95 -0
  295. package/src/testing/connector-connection-storage-contract.ts +29 -12
  296. package/src/testing/index.ts +1 -0
  297. package/src/testing/lake-changes-contract.ts +240 -0
  298. package/src/testing/lake-storage-contract.ts +29 -0
  299. package/src/testing/materializer-storage-contract.ts +172 -1
  300. package/src/testing/ontology-storage-contract.ts +15 -3
  301. package/src/testing/projection-run-storage-contract.ts +34 -0
  302. package/src/webhooks/connections.ts +56 -0
  303. package/src/webhooks/index.ts +2 -0
  304. package/src/webhooks/internal.ts +2 -0
  305. package/src/webhooks/registry.ts +3 -4
  306. package/src/webhooks/types.ts +17 -4
  307. package/src/workflows/run-dispatch.ts +42 -29
  308. package/dist/chunk-0rdrecsb.js.map +0 -11
  309. package/dist/chunk-3f7veca0.js.map +0 -10
  310. package/dist/chunk-3frsnm7x.js.map +0 -11
  311. package/dist/chunk-3tgwrcyh.js.map +0 -14
  312. package/dist/chunk-52hbv0ak.js.map +0 -36
  313. package/dist/chunk-e0d1rzef.js.map +0 -15
  314. package/dist/chunk-emyyk7dx.js.map +0 -14
  315. package/dist/chunk-jjy0fhrn.js.map +0 -12
  316. package/dist/chunk-k3cqkkn2.js.map +0 -12
  317. package/dist/chunk-ppytyr6w.js.map +0 -12
  318. package/dist/chunk-qhcpj9wc.js.map +0 -14
  319. package/dist/chunk-r29fxdhn.js.map +0 -11
  320. package/dist/chunk-zcnq6105.js.map +0 -10
  321. /package/dist/{chunk-ypbtykv6.js.map → chunk-01kj2pbh.js.map} +0 -0
  322. /package/dist/{chunk-xyr8kppc.js.map → chunk-1yefycb1.js.map} +0 -0
  323. /package/dist/{chunk-m3z3x9v0.js.map → chunk-3ckk0xfj.js.map} +0 -0
  324. /package/dist/{chunk-0w35wavj.js.map → chunk-a0e6x5hd.js.map} +0 -0
  325. /package/dist/{chunk-h1gfhhbh.js.map → chunk-d63nnr5b.js.map} +0 -0
  326. /package/dist/{chunk-r4tfx1sf.js.map → chunk-fh8kgex1.js.map} +0 -0
  327. /package/dist/{chunk-vf691g1r.js.map → chunk-sepyxgpc.js.map} +0 -0
  328. /package/dist/{chunk-1enhpacz.js.map → chunk-z0s4axeh.js.map} +0 -0
@@ -1,7 +1,4 @@
1
1
  import { randomUUID } from "node:crypto"
2
- import { reportRunFailure } from "../error-reporting/capability"
3
- import { createSixbError, toSixbFailure } from "../errors/internal"
4
- import type { SixbFailure } from "../errors/types"
5
2
  import type { RunDispatcher } from "../execution/dispatch"
6
3
  import { createPrimitiveExecutionRecord } from "../execution/durable"
7
4
  import type { DatasetProducer, LakeStorage } from "../lake-storage"
@@ -17,11 +14,7 @@ import {
17
14
  import { getProjectionRegistry } from "./capability"
18
15
  import { ProjectionValidationError } from "./errors"
19
16
  import { createProjectionRunId } from "./run-id"
20
- import {
21
- PROJECTION_RUN_FAILURE_CODES,
22
- type ProjectionDefinition,
23
- type ProjectionRunFailureCode,
24
- } from "./types"
17
+ import type { ProjectionDefinition } from "./types"
25
18
 
26
19
  /** Target maximum mapped points per telemetry commit; a single-property projection reads 500 rows. */
27
20
  export const PROJECTION_TELEMETRY_BATCH_SIZE = 500
@@ -106,7 +99,7 @@ export class ProjectionRunDispatcher implements ProjectionRunDispatchPort {
106
99
  const runId = createProjectionRunId(this.dependencies.id, identity)
107
100
  const projectionRuns = requireProjectionRunStorage(this.dependencies.storage)
108
101
  const existing = await projectionRuns.getById({ projectId: this.dependencies.id, id: runId })
109
- const persisted = existing
102
+ let persisted = existing
110
103
  ? await reuseProjectionRun(this.dependencies, existing, identity)
111
104
  : await persistProjectionRun({
112
105
  dependencies: this.dependencies,
@@ -120,6 +113,9 @@ export class ProjectionRunDispatcher implements ProjectionRunDispatchPort {
120
113
  ),
121
114
  })
122
115
 
116
+ if (!persisted.publish && persisted.run.status === "queued") {
117
+ persisted = await reuseProjectionRun(this.dependencies, persisted.run, identity)
118
+ }
123
119
  if (!persisted.publish) return existingResult(persisted.run)
124
120
  return publishProjectionRun(this.dependencies, input.metadata, persisted)
125
121
  }
@@ -195,6 +191,9 @@ async function reuseProjectionRun(
195
191
  identity: ProjectionRunRecord["identity"]
196
192
  ): Promise<PersistedProjectionRun> {
197
193
  await assertExistingRun(dependencies.storage, existing, identity)
194
+ if (existing.status === "queued") {
195
+ return { publish: true, run: existing, queuedAt: existing.queuedAt, created: false }
196
+ }
198
197
  if (
199
198
  existing.status !== "failed" ||
200
199
  existing.error?.code !== "queue.enqueue_failed" ||
@@ -228,45 +227,29 @@ async function publishProjectionRun(
228
227
  metadata: Readonly<Record<string, string>> | undefined,
229
228
  persisted: Extract<PersistedProjectionRun, { readonly publish: true }>
230
229
  ): Promise<ProjectionRunDispatchResult> {
231
- try {
232
- const [job] = await dependencies.queues.projections.enqueue({
233
- projectId: dependencies.id,
234
- jobs: [
235
- {
236
- id: persisted.run.id,
237
- type: "projection.run.requested",
238
- payload: { runId: persisted.run.id },
239
- ...(metadata === undefined ? {} : { metadata }),
240
- },
241
- ],
242
- })
243
- return {
244
- projectionId: persisted.run.identity.projectionId,
245
- runId: persisted.run.id,
246
- queuedAt: persisted.queuedAt.toISOString(),
247
- ...(job?.id ? { jobId: job.id } : {}),
248
- created: persisted.created,
249
- }
250
- } catch (error) {
251
- const failedAt = new Date()
252
- const failure = toEnqueueFailure(error, persisted.run, failedAt)
253
- const failed = await requireProjectionRunStorage(dependencies.storage).failEnqueue({
254
- projectId: dependencies.id,
255
- id: persisted.run.id,
256
- finishedAt: failedAt,
257
- error: failure,
258
- })
259
- reportRunFailure(dependencies, error, {
260
- projectId: dependencies.id,
261
- runKind: "projection",
262
- run: {
263
- runId: failed.id,
264
- projectionId: failed.identity.projectionId,
265
- projectionKind: failed.identity.projectionKind,
230
+ // Keep the run queued on uncertain publication; the caller retries the same identity.
231
+ const [job] = await dependencies.queues.projections.enqueue({
232
+ projectId: dependencies.id,
233
+ jobs: [
234
+ {
235
+ id: persisted.run.id,
236
+ type: "projection.run.requested",
237
+ payload: { runId: persisted.run.id },
238
+ ...(metadata === undefined ? {} : { metadata }),
266
239
  },
267
- failure,
268
- })
269
- throw error
240
+ ],
241
+ })
242
+ if (!job || job.id !== persisted.run.id) {
243
+ throw new ProjectionRunError(
244
+ `[Sixb] Queue did not acknowledge Projection run '${persisted.run.id}'.`
245
+ )
246
+ }
247
+ return {
248
+ projectionId: persisted.run.identity.projectionId,
249
+ runId: persisted.run.id,
250
+ queuedAt: persisted.queuedAt.toISOString(),
251
+ ...(job?.id ? { jobId: job.id } : {}),
252
+ created: persisted.created,
270
253
  }
271
254
  }
272
255
 
@@ -478,24 +461,3 @@ function assertDispatchInput(input: ProjectionRunDispatchInput): void {
478
461
  throw new ProjectionValidationError("[Sixb] Projection dataset version timestamp is invalid.")
479
462
  }
480
463
  }
481
-
482
- function toEnqueueFailure(
483
- error: unknown,
484
- run: ProjectionRunRecord,
485
- at: Date
486
- ): SixbFailure<ProjectionRunFailureCode> {
487
- const enqueueError = createSixbError(
488
- "queue.enqueue_failed",
489
- `[Sixb] Could not enqueue Projection run '${run.id}'.`,
490
- {
491
- cause: error,
492
- details: {
493
- projectionId: run.identity.projectionId,
494
- projectionKind: run.identity.projectionKind,
495
- runId: run.id,
496
- phase: "enqueue",
497
- },
498
- }
499
- )
500
- return toSixbFailure(enqueueError, { allowedCodes: PROJECTION_RUN_FAILURE_CODES, at })
501
- }
@@ -1,6 +1,7 @@
1
1
  import { randomUUID } from "node:crypto"
2
2
  import type { SixbErrorCode } from "../errors/types"
3
3
  import { QueueError } from "./errors"
4
+ import { IndexedHeap } from "./indexed-heap"
4
5
  import type {
5
6
  ActionQueueJobFailureCode,
6
7
  ActionRunRequestedQueueJob,
@@ -29,6 +30,9 @@ interface QueueRecord<TQueueJob extends QueueJob = QueueJob> {
29
30
  readonly sequence: number
30
31
  readonly queueId: string
31
32
  job: TQueueJob
33
+ availableAtMs: number
34
+ readonly createdAtMs: number
35
+ leaseExpiryMs: number | null
32
36
  // A leased job stays "queued" until a worker completes or fails it.
33
37
  state: QueueRecordState
34
38
  failure: QueueJobFailure | null
@@ -63,25 +67,15 @@ function clearLease(record: QueueRecord): void {
63
67
  record.leaseId = null
64
68
  record.claimedAt = null
65
69
  record.leaseExpiresAt = null
70
+ record.leaseExpiryMs = null
66
71
  }
67
72
 
68
73
  // Best-effort ordering is part of the contract; this keeps the in-memory provider deterministic.
69
74
  function compareQueueRecords(left: QueueRecord, right: QueueRecord): number {
70
- const availableDifference =
71
- parseTimestamp(left.job.availableAt, "job.availableAt") -
72
- parseTimestamp(right.job.availableAt, "job.availableAt")
73
-
74
- if (availableDifference !== 0) {
75
- return availableDifference
76
- }
77
-
78
- const createdDifference =
79
- parseTimestamp(left.job.createdAt, "job.createdAt") -
80
- parseTimestamp(right.job.createdAt, "job.createdAt")
81
-
82
- if (createdDifference !== 0) {
83
- return createdDifference
84
- }
75
+ const availableDifference = left.availableAtMs - right.availableAtMs
76
+ if (availableDifference !== 0) return availableDifference
77
+ const createdDifference = left.createdAtMs - right.createdAtMs
78
+ if (createdDifference !== 0) return createdDifference
85
79
 
86
80
  return left.sequence - right.sequence
87
81
  }
@@ -107,11 +101,18 @@ function createQueueJob<TQueueJob extends QueueJob>(
107
101
  }
108
102
 
109
103
  function leaseExpiresAtMs(record: QueueRecord): number | null {
110
- if (!record.leaseId || !record.leaseExpiresAt) {
111
- return null
112
- }
104
+ return record.leaseExpiryMs
105
+ }
113
106
 
114
- return parseTimestamp(record.leaseExpiresAt, "leaseExpiresAt")
107
+ function eligibleAt(record: QueueRecord): number {
108
+ return Math.max(record.availableAtMs, record.leaseExpiryMs ?? -Infinity)
109
+ }
110
+
111
+ interface QueueLane {
112
+ // Terminal records remain here for caller-id deduplication, never in the delivery indexes.
113
+ readonly records: Map<string, QueueRecord>
114
+ readonly ready: IndexedHeap<QueueRecord>
115
+ readonly waiting: IndexedHeap<QueueRecord>
115
116
  }
116
117
 
117
118
  function toClaimedQueueJob<TQueueJob extends QueueJob>(
@@ -130,27 +131,26 @@ function toClaimedQueueJob<TQueueJob extends QueueJob>(
130
131
  }
131
132
 
132
133
  class InMemoryQueueStore {
133
- private readonly recordsByProject = new Map<string, QueueRecord[]>()
134
+ private readonly projects = new Map<string, Map<string, QueueLane>>()
134
135
  private nextSequence = 1
135
136
 
136
137
  add<TQueueJob extends QueueJob>(projectId: string, queueId: string, job: TQueueJob): void {
137
- const records = this.getOrCreateRecords(projectId)
138
- records.push({
139
- sequence: this.nextSequence,
138
+ const lane = this.lane(projectId, queueId)
139
+ const record: QueueRecord = {
140
+ sequence: this.nextSequence++,
140
141
  queueId,
141
142
  job,
143
+ availableAtMs: parseTimestamp(job.availableAt, "job.availableAt"),
144
+ createdAtMs: parseTimestamp(job.createdAt, "job.createdAt"),
145
+ leaseExpiryMs: null,
142
146
  state: "queued",
143
147
  failure: null,
144
148
  leaseId: null,
145
149
  claimedAt: null,
146
150
  leaseExpiresAt: null,
147
- })
148
- this.nextSequence += 1
149
- }
150
-
151
- list<TQueueJob extends QueueJob>(projectId: string, queueId: string): QueueRecord<TQueueJob>[] {
152
- const records = this.recordsByProject.get(projectId) ?? []
153
- return records.filter((record) => record.queueId === queueId) as QueueRecord<TQueueJob>[]
151
+ }
152
+ lane.records.set(job.id, record)
153
+ this.schedule(projectId, record, Date.now())
154
154
  }
155
155
 
156
156
  find<TQueueJob extends QueueJob>(
@@ -158,20 +158,67 @@ class InMemoryQueueStore {
158
158
  queueId: string,
159
159
  jobId: string
160
160
  ): QueueRecord<TQueueJob> | null {
161
- return (
162
- this.list<TQueueJob>(projectId, queueId).find((record) => record.job.id === jobId) ?? null
163
- )
161
+ return (this.projects.get(projectId)?.get(queueId)?.records.get(jobId) ??
162
+ null) as QueueRecord<TQueueJob> | null
164
163
  }
165
164
 
166
- private getOrCreateRecords(projectId: string): QueueRecord[] {
167
- const existing = this.recordsByProject.get(projectId)
168
- if (existing) {
169
- return existing
165
+ schedule(projectId: string, record: QueueRecord, now: number): void {
166
+ const lane = this.lane(projectId, record.queueId)
167
+ if (record.state !== "queued") {
168
+ lane.ready.delete(record)
169
+ lane.waiting.delete(record)
170
+ } else if (eligibleAt(record) <= now) {
171
+ lane.waiting.delete(record)
172
+ lane.ready.set(record)
173
+ } else {
174
+ lane.ready.delete(record)
175
+ lane.waiting.set(record)
176
+ }
177
+ }
178
+
179
+ takeReady<TQueueJob extends QueueJob>(
180
+ projectId: string,
181
+ queueId: string,
182
+ now: number,
183
+ limit: number
184
+ ): QueueRecord<TQueueJob>[] {
185
+ const lane = this.projects.get(projectId)?.get(queueId)
186
+ if (!lane) return []
187
+ // Wake delayed jobs and expired leases, then order all ready jobs by the original contract.
188
+ // A lease expiry controls eligibility, not the priority of a redelivered job.
189
+ while (lane.waiting.peek() && eligibleAt(lane.waiting.peek()!) <= now) {
190
+ lane.ready.set(lane.waiting.pop()!)
170
191
  }
192
+ const selected: QueueRecord[] = []
193
+ while (selected.length < limit) {
194
+ const record = lane.ready.peek()
195
+ if (!record || record.availableAtMs > now) break
196
+ lane.ready.pop()
197
+ // A backwards wall-clock adjustment can make a previously expired lease live again.
198
+ if (eligibleAt(record) > now) lane.waiting.set(record)
199
+ else selected.push(record)
200
+ }
201
+ return selected as QueueRecord<TQueueJob>[]
202
+ }
171
203
 
172
- const records: QueueRecord[] = []
173
- this.recordsByProject.set(projectId, records)
174
- return records
204
+ private lane(projectId: string, queueId: string): QueueLane {
205
+ let queues = this.projects.get(projectId)
206
+ if (!queues) {
207
+ queues = new Map()
208
+ this.projects.set(projectId, queues)
209
+ }
210
+ let lane = queues.get(queueId)
211
+ if (!lane) {
212
+ lane = {
213
+ records: new Map(),
214
+ ready: new IndexedHeap(compareQueueRecords),
215
+ waiting: new IndexedHeap(
216
+ (left, right) => eligibleAt(left) - eligibleAt(right) || left.sequence - right.sequence
217
+ ),
218
+ }
219
+ queues.set(queueId, lane)
220
+ }
221
+ return lane
175
222
  }
176
223
  }
177
224
 
@@ -219,8 +266,8 @@ class InMemoryQueue<TQueueJob extends QueueJob, TFailureCode extends SixbErrorCo
219
266
  assertNonEmpty(params.projectId, "projectId")
220
267
  assertNonEmpty(params.workerId, "workerId")
221
268
 
222
- const limit = params.limit ?? 1
223
- if (limit <= 0) {
269
+ const limit = Math.trunc(params.limit ?? 1)
270
+ if (!(limit > 0)) {
224
271
  return []
225
272
  }
226
273
 
@@ -228,24 +275,11 @@ class InMemoryQueue<TQueueJob extends QueueJob, TFailureCode extends SixbErrorCo
228
275
  assertPositiveNumber(leaseMs, "leaseMs")
229
276
 
230
277
  const now = Date.now()
231
- const claimable = this.store
232
- .list<TQueueJob>(params.projectId, this.queueId)
233
- .filter((record) => {
234
- if (record.state !== "queued") {
235
- return false
236
- }
237
-
238
- if (parseTimestamp(record.job.availableAt, "job.availableAt") > now) {
239
- return false
240
- }
241
-
242
- const expiresAt = leaseExpiresAtMs(record)
243
- return expiresAt === null || expiresAt <= now
244
- })
245
- .sort(compareQueueRecords)
246
- .slice(0, limit)
247
-
248
278
  const claimedAt = new Date(now).toISOString()
279
+ // Validate before removing candidates, and cache the same millisecond precision we return.
280
+ const leaseExpiry = new Date(now + leaseMs)
281
+ const leaseExpiresAt = leaseExpiry.toISOString()
282
+ const claimable = this.store.takeReady<TQueueJob>(params.projectId, this.queueId, now, limit)
249
283
 
250
284
  return claimable.map((record) => {
251
285
  // Attempts count claims so redelivery after lease expiry or retry is visible to workers.
@@ -255,7 +289,9 @@ class InMemoryQueue<TQueueJob extends QueueJob, TFailureCode extends SixbErrorCo
255
289
  }
256
290
  record.leaseId = randomUUID()
257
291
  record.claimedAt = claimedAt
258
- record.leaseExpiresAt = new Date(now + leaseMs).toISOString()
292
+ record.leaseExpiresAt = leaseExpiresAt
293
+ record.leaseExpiryMs = leaseExpiry.getTime()
294
+ this.store.schedule(params.projectId, record, now)
259
295
 
260
296
  return toClaimedQueueJob(record)
261
297
  })
@@ -265,6 +301,7 @@ class InMemoryQueue<TQueueJob extends QueueJob, TFailureCode extends SixbErrorCo
265
301
  const record = this.requireActiveLease(params)
266
302
  record.state = "completed"
267
303
  clearLease(record)
304
+ this.store.schedule(params.projectId, record, Date.now())
268
305
  }
269
306
 
270
307
  async retry(params: {
@@ -275,13 +312,15 @@ class InMemoryQueue<TQueueJob extends QueueJob, TFailureCode extends SixbErrorCo
275
312
  }): Promise<void> {
276
313
  const record = this.requireActiveLease(params)
277
314
  const availableAt = params.availableAt ?? new Date().toISOString()
278
- parseTimestamp(availableAt, "availableAt")
315
+ const availableAtMs = parseTimestamp(availableAt, "availableAt")
279
316
 
317
+ record.availableAtMs = availableAtMs
280
318
  record.job = {
281
319
  ...record.job,
282
320
  availableAt,
283
321
  }
284
322
  clearLease(record)
323
+ this.store.schedule(params.projectId, record, Date.now())
285
324
  }
286
325
 
287
326
  async fail(params: {
@@ -294,6 +333,7 @@ class InMemoryQueue<TQueueJob extends QueueJob, TFailureCode extends SixbErrorCo
294
333
  record.state = "failed"
295
334
  record.failure = structuredClone(params.failure)
296
335
  clearLease(record)
336
+ this.store.schedule(params.projectId, record, Date.now())
297
337
  }
298
338
 
299
339
  async renewLease(params: {
@@ -319,7 +359,10 @@ class InMemoryQueue<TQueueJob extends QueueJob, TFailureCode extends SixbErrorCo
319
359
  return null
320
360
  }
321
361
 
322
- record.leaseExpiresAt = new Date(now + params.leaseMs).toISOString()
362
+ const leaseExpiry = new Date(now + params.leaseMs)
363
+ record.leaseExpiresAt = leaseExpiry.toISOString()
364
+ record.leaseExpiryMs = leaseExpiry.getTime()
365
+ this.store.schedule(params.projectId, record, now)
323
366
  return toClaimedQueueJob(record)
324
367
  }
325
368
 
@@ -0,0 +1,74 @@
1
+ /** Internal mutable priority index. Updating or removing an entry never leaves stale copies. */
2
+ export class IndexedHeap<T> {
3
+ private readonly items: T[] = []
4
+ private readonly positions = new Map<T, number>()
5
+
6
+ constructor(private readonly compare: (left: T, right: T) => number) {}
7
+
8
+ peek(): T | undefined {
9
+ return this.items[0]
10
+ }
11
+
12
+ pop(): T | undefined {
13
+ const first = this.peek()
14
+ if (first !== undefined) this.delete(first)
15
+ return first
16
+ }
17
+
18
+ set(item: T): void {
19
+ const index = this.positions.get(item)
20
+ if (index === undefined) {
21
+ this.positions.set(item, this.items.length)
22
+ this.items.push(item)
23
+ this.up(this.items.length - 1)
24
+ } else {
25
+ this.down(this.up(index))
26
+ }
27
+ }
28
+
29
+ delete(item: T): void {
30
+ const index = this.positions.get(item)
31
+ if (index === undefined) return
32
+ const last = this.items.pop()!
33
+ this.positions.delete(item)
34
+ if (index === this.items.length) return
35
+ this.items[index] = last
36
+ this.positions.set(last, index)
37
+ this.down(this.up(index))
38
+ }
39
+
40
+ private up(start: number): number {
41
+ let index = start
42
+ while (index > 0) {
43
+ const parent = Math.floor((index - 1) / 2)
44
+ if (this.compare(this.items[parent]!, this.items[index]!) <= 0) break
45
+ this.swap(parent, index)
46
+ index = parent
47
+ }
48
+ return index
49
+ }
50
+
51
+ private down(start: number): void {
52
+ let index = start
53
+ while (index * 2 + 1 < this.items.length) {
54
+ const left = index * 2 + 1
55
+ const right = left + 1
56
+ const child =
57
+ right < this.items.length && this.compare(this.items[right]!, this.items[left]!) < 0
58
+ ? right
59
+ : left
60
+ if (this.compare(this.items[index]!, this.items[child]!) <= 0) break
61
+ this.swap(index, child)
62
+ index = child
63
+ }
64
+ }
65
+
66
+ private swap(left: number, right: number): void {
67
+ const a = this.items[left]!
68
+ const b = this.items[right]!
69
+ this.items[left] = b
70
+ this.items[right] = a
71
+ this.positions.set(a, right)
72
+ this.positions.set(b, left)
73
+ }
74
+ }
@@ -19,7 +19,6 @@ import type { BlobStorage } from "../blob-storage"
19
19
  import type { Broker } from "../broker"
20
20
  import { registerConnectorConnectionCallbackProcess } from "../connectors/connections/capability"
21
21
  import { createConnectorCredentialProtectorFromKey } from "../connectors/credentials"
22
- import { createConnectorCodedError } from "../connectors/errors"
23
22
  import { ConnectorService } from "../connectors/service"
24
23
  import {
25
24
  type ConnectorConnectionOptions,
@@ -185,7 +184,6 @@ export class SixbHost<
185
184
  })
186
185
  validateAuthStrategySecurityReferences(this.auth.getStrategy(), definitions.security)
187
186
  const connectors = definitions.connectors.list()
188
- assertConnectorConnectionSurfaces(connectors)
189
187
  const hasOAuthConnectors = connectors.some(isOAuthConnectorDefinition)
190
188
  const credentialProtector =
191
189
  hasOAuthConnectors && options.connectorConnections?.encryptionKey !== undefined
@@ -386,15 +384,3 @@ function assertWebhookRunStorage(
386
384
  }
387
385
  }
388
386
  }
389
-
390
- function assertConnectorConnectionSurfaces(connectors: readonly ConnectorDefinition[]): void {
391
- for (const connector of connectors) {
392
- if (!isOAuthConnectorDefinition(connector)) continue
393
- if (connector.adapter.webhooks !== undefined) {
394
- throw createConnectorCodedError(
395
- "connector.configuration_invalid",
396
- `OAuth connector '${connector.id}' cannot register webhooks until connection routing is defined.`
397
- )
398
- }
399
- }
400
- }
@@ -3,13 +3,16 @@ import type {
3
3
  OntologyEditCommit,
4
4
  ProjectionCommitResult,
5
5
  ProjectionRunFinishInput,
6
+ ProjectionSourceRef,
6
7
  ProjectionSourceReplacement,
7
8
  TelemetryAppend,
8
9
  TelemetryCommitResult,
9
10
  } from "../materialization/model"
10
11
  import type { BoundOntologyMaterializer } from "../materializer"
12
+ import type { OntologySourceRecord } from "../storage/ontology"
11
13
 
12
14
  export interface OntologyMutationRuntime {
15
+ getProjectionSource?(source: ProjectionSourceRef): Promise<OntologySourceRecord | null>
13
16
  commitEdits(input: OntologyEditCommit): Promise<EditCommitResult>
14
17
  replaceProjection(input: ProjectionSourceReplacement): Promise<ProjectionCommitResult>
15
18
  finishProjection(input: ProjectionRunFinishInput): Promise<void>
@@ -55,6 +58,7 @@ export function createOntologyMutationRuntime(input: {
55
58
  readonly notifyCommittedFacts: () => void
56
59
  }): OntologyMutationRuntime {
57
60
  const runtime: OntologyMutationRuntime = {
61
+ getProjectionSource: (source) => input.materializer.projections.getActive(source),
58
62
  commitEdits: (command) =>
59
63
  commitAndNotify(() => input.materializer.edits.commit(command), input.notifyCommittedFacts),
60
64
  replaceProjection: (command) =>
@@ -147,7 +147,9 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
147
147
  slot: input.slot,
148
148
  initiatedByExecutionId: input.initiatedByExecutionId,
149
149
  stateHash: input.stateHash,
150
- codeVerifier: structuredClone(input.codeVerifier),
150
+ ...(input.codeVerifier === undefined
151
+ ? {}
152
+ : { codeVerifier: structuredClone(input.codeVerifier) }),
151
153
  redirectUri: input.redirectUri,
152
154
  ...(input.connectionRunId === undefined ? {} : { connectionRunId: input.connectionRunId }),
153
155
  ...(input.returnTo === undefined ? {} : { returnTo: input.returnTo }),
@@ -411,6 +413,20 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
411
413
  return structuredClone(finished)
412
414
  }
413
415
 
416
+ async listPendingConnectionRuns(
417
+ input: Parameters<ConnectorConnectionStorage["listPendingConnectionRuns"]>[0]
418
+ ): Promise<readonly ConnectorConnectionRunRecord[]> {
419
+ return [...this.connectionRuns.values()]
420
+ .filter(
421
+ (run) =>
422
+ run.projectId === input.projectId &&
423
+ run.connectorId === input.connectorId &&
424
+ (run.status === "running" ||
425
+ (run.status === "waiting" && run.waitingFor === "account_selection"))
426
+ )
427
+ .map((run) => structuredClone(run))
428
+ }
429
+
414
430
  async getConnectionRun(
415
431
  input: GetConnectorConnectionRunInput
416
432
  ): Promise<ConnectorConnectionRunRecord | null> {
@@ -853,7 +869,7 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
853
869
  input: PutConnectorConnectionInput,
854
870
  now: Date
855
871
  ): PutConnectorConnectionResult {
856
- let authorization = this.authorizations.get(input.authorizationId)
872
+ const authorization = this.authorizations.get(input.authorizationId)
857
873
  if (
858
874
  !sameAuthorizationScope(authorization, input) ||
859
875
  !isSelectable(authorization.status) ||
@@ -861,20 +877,6 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
861
877
  ) {
862
878
  throw authorizationConflict()
863
879
  }
864
- if (
865
- authorization.status === "pending_selection" &&
866
- authorization.selectionExpiresAt!.getTime() <= now.getTime()
867
- ) {
868
- authorization = {
869
- ...authorization,
870
- status: "revocation_pending",
871
- selectionExpiresAt: undefined,
872
- revision: authorization.revision + 1,
873
- updatedAt: now,
874
- }
875
- this.authorizations.set(authorization.id, authorization)
876
- throw authorizationConflict()
877
- }
878
880
  const account = authorization.accounts.find((candidate) => candidate.id === input.account.id)
879
881
  if (!account) {
880
882
  throw new ConnectorConnectionStorageError(
@@ -1076,6 +1078,7 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
1076
1078
  const run = this.connectionRuns.get(runId)
1077
1079
  if (!run || (run.status !== "waiting" && run.status !== "running")) return run
1078
1080
 
1081
+ if (run.status === "waiting" && run.waitingFor === "account_selection") return run
1079
1082
  const now = this.now()
1080
1083
  if (run.expiresAt.getTime() > now.getTime()) return run
1081
1084
 
@@ -1084,9 +1087,6 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
1084
1087
  if (attempt) this.attempts.delete(attempt.id)
1085
1088
  }
1086
1089
  if (run.status === "waiting") {
1087
- if (run.kind === "connect" && run.waitingFor === "account_selection") {
1088
- this.markPendingAuthorizationForCleanup(run.connectorId, run.authorizationId, now)
1089
- }
1090
1090
  const expired = expireConnectionRun(run, now)
1091
1091
  this.connectionRuns.set(run.id, expired)
1092
1092
  return expired
@@ -165,7 +165,7 @@ export class DurableConnectorConnections extends ConnectorConnectionOperations {
165
165
  input: PutConnectorConnectionInput,
166
166
  now: Date
167
167
  ): Promise<PutConnectorConnectionResult | CommittedConnectorConnectionError> {
168
- let authorization = await persistence.getAuthorization(input.authorizationId)
168
+ const authorization = await persistence.getAuthorization(input.authorizationId)
169
169
  if (
170
170
  !authorization ||
171
171
  !isSelectable(authorization.status) ||
@@ -173,20 +173,6 @@ export class DurableConnectorConnections extends ConnectorConnectionOperations {
173
173
  ) {
174
174
  throw authorizationConflict()
175
175
  }
176
- if (
177
- authorization.status === "pending_selection" &&
178
- authorization.selectionExpiresAt!.getTime() <= now.getTime()
179
- ) {
180
- authorization = {
181
- ...authorization,
182
- status: "revocation_pending",
183
- selectionExpiresAt: undefined,
184
- revision: authorization.revision + 1,
185
- updatedAt: now,
186
- }
187
- await persistence.updateAuthorization(authorization)
188
- return { error: authorizationConflict() }
189
- }
190
176
  const account = authorization.accounts.find((candidate) => candidate.id === input.account.id)
191
177
  if (!account) {
192
178
  throw new ConnectorConnectionStorageError(
@@ -63,7 +63,9 @@ export class DurableConnectorConnectionRuns extends ConnectorConnectionOperation
63
63
  slot: input.slot,
64
64
  initiatedByExecutionId: input.initiatedByExecutionId,
65
65
  stateHash: input.stateHash,
66
- codeVerifier: structuredClone(input.codeVerifier),
66
+ ...(input.codeVerifier === undefined
67
+ ? {}
68
+ : { codeVerifier: structuredClone(input.codeVerifier) }),
67
69
  redirectUri: input.redirectUri,
68
70
  ...(input.connectionRunId === undefined ? {} : { connectionRunId: input.connectionRunId }),
69
71
  ...(input.returnTo === undefined ? {} : { returnTo: input.returnTo }),
@@ -358,6 +360,12 @@ export class DurableConnectorConnectionRuns extends ConnectorConnectionOperation
358
360
  })
359
361
  }
360
362
 
363
+ listPendingConnectionRuns(
364
+ input: Parameters<ConnectorConnectionStorage["listPendingConnectionRuns"]>[0]
365
+ ) {
366
+ return this.read(input, (persistence) => persistence.listPendingConnectionRuns())
367
+ }
368
+
361
369
  getConnectionRun(
362
370
  input: GetConnectorConnectionRunInput
363
371
  ): Promise<ConnectorConnectionRunRecord | null> {