@qlever-llc/trellis 0.10.17 → 0.19.0-rc.1

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 (283) hide show
  1. package/esm/auth/mod.d.ts +1 -1
  2. package/esm/auth/mod.d.ts.map +1 -1
  3. package/esm/auth/mod.js +1 -1
  4. package/esm/auth/protocol.d.ts +416 -398
  5. package/esm/auth/protocol.d.ts.map +1 -1
  6. package/esm/auth/protocol.js +35 -33
  7. package/esm/codec.d.ts +1 -0
  8. package/esm/codec.d.ts.map +1 -1
  9. package/esm/codec.js +1 -0
  10. package/esm/contract_support/canonical.d.ts +3 -0
  11. package/esm/contract_support/canonical.d.ts.map +1 -1
  12. package/esm/contract_support/canonical.js +3 -0
  13. package/esm/contract_support/mod.d.ts +28 -4
  14. package/esm/contract_support/mod.d.ts.map +1 -1
  15. package/esm/contract_support/mod.js +85 -4
  16. package/esm/contract_support/protocol.d.ts +92 -7
  17. package/esm/contract_support/protocol.d.ts.map +1 -1
  18. package/esm/contract_support/protocol.js +40 -6
  19. package/esm/errors/index.d.ts +9 -9
  20. package/esm/generated-sdk/auth/api.d.ts +4 -1
  21. package/esm/generated-sdk/auth/api.d.ts.map +1 -1
  22. package/esm/generated-sdk/auth/api.js +6 -1
  23. package/esm/generated-sdk/auth/client.d.ts +47 -32
  24. package/esm/generated-sdk/auth/client.d.ts.map +1 -1
  25. package/esm/generated-sdk/auth/contract.d.ts +1 -1
  26. package/esm/generated-sdk/auth/contract.d.ts.map +1 -1
  27. package/esm/generated-sdk/auth/contract.js +1570 -1202
  28. package/esm/generated-sdk/auth/schemas.d.ts +1757 -1759
  29. package/esm/generated-sdk/auth/schemas.d.ts.map +1 -1
  30. package/esm/generated-sdk/auth/schemas.js +963 -768
  31. package/esm/generated-sdk/auth/types.d.ts +292 -302
  32. package/esm/generated-sdk/auth/types.d.ts.map +1 -1
  33. package/esm/generated-sdk/auth/types.js +1 -1
  34. package/esm/generated-sdk/health/client.d.ts +4 -4
  35. package/esm/generated-sdk/health/client.d.ts.map +1 -1
  36. package/esm/generated-sdk/health/contract.d.ts +1 -1
  37. package/esm/generated-sdk/health/contract.d.ts.map +1 -1
  38. package/esm/generated-sdk/health/contract.js +2 -10
  39. package/esm/generated-sdk/health/schemas.d.ts +1 -14
  40. package/esm/generated-sdk/health/schemas.d.ts.map +1 -1
  41. package/esm/generated-sdk/health/schemas.js +1 -9
  42. package/esm/generated-sdk/health/types.d.ts +3 -5
  43. package/esm/generated-sdk/health/types.d.ts.map +1 -1
  44. package/esm/generated-sdk/health/types.js +1 -2
  45. package/esm/generated-sdk/jobs/api.d.ts +13 -0
  46. package/esm/generated-sdk/jobs/api.d.ts.map +1 -1
  47. package/esm/generated-sdk/jobs/client.d.ts +6 -4
  48. package/esm/generated-sdk/jobs/client.d.ts.map +1 -1
  49. package/esm/generated-sdk/jobs/contract.d.ts +14 -1
  50. package/esm/generated-sdk/jobs/contract.d.ts.map +1 -1
  51. package/esm/generated-sdk/jobs/contract.js +268 -1
  52. package/esm/generated-sdk/jobs/owned_api.d.ts +13 -0
  53. package/esm/generated-sdk/jobs/owned_api.d.ts.map +1 -1
  54. package/esm/generated-sdk/jobs/owned_api.js +20 -1
  55. package/esm/generated-sdk/jobs/schemas.d.ts +437 -0
  56. package/esm/generated-sdk/jobs/schemas.d.ts.map +1 -1
  57. package/esm/generated-sdk/jobs/schemas.js +211 -0
  58. package/esm/generated-sdk/jobs/types.d.ts +123 -1
  59. package/esm/generated-sdk/jobs/types.d.ts.map +1 -1
  60. package/esm/generated-sdk/jobs/types.js +1 -1
  61. package/esm/generated-sdk/state/client.d.ts +4 -4
  62. package/esm/generated-sdk/state/client.d.ts.map +1 -1
  63. package/esm/generated-sdk/trellis-core/api.d.ts +4 -1
  64. package/esm/generated-sdk/trellis-core/api.d.ts.map +1 -1
  65. package/esm/generated-sdk/trellis-core/api.js +6 -1
  66. package/esm/generated-sdk/trellis-core/client.d.ts +28 -3
  67. package/esm/generated-sdk/trellis-core/client.d.ts.map +1 -1
  68. package/esm/generated-sdk/trellis-core/contract.d.ts +1 -1
  69. package/esm/generated-sdk/trellis-core/contract.d.ts.map +1 -1
  70. package/esm/generated-sdk/trellis-core/contract.js +91 -1
  71. package/esm/generated-sdk/trellis-core/schemas.d.ts +113 -0
  72. package/esm/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
  73. package/esm/generated-sdk/trellis-core/schemas.js +81 -0
  74. package/esm/generated-sdk/trellis-core/types.d.ts +23 -1
  75. package/esm/generated-sdk/trellis-core/types.d.ts.map +1 -1
  76. package/esm/generated-sdk/trellis-core/types.js +1 -1
  77. package/esm/health.d.ts +1 -1
  78. package/esm/health.d.ts.map +1 -1
  79. package/esm/health.js +1 -1
  80. package/esm/index.d.ts +2 -2
  81. package/esm/index.d.ts.map +1 -1
  82. package/esm/index.js +1 -1
  83. package/esm/jobs.d.ts +69 -3
  84. package/esm/jobs.d.ts.map +1 -1
  85. package/esm/jobs.js +92 -3
  86. package/esm/server/health.d.ts +2 -6
  87. package/esm/server/health.d.ts.map +1 -1
  88. package/esm/server/health_schemas.d.ts +0 -8
  89. package/esm/server/health_schemas.d.ts.map +1 -1
  90. package/esm/server/health_schemas.js +0 -5
  91. package/esm/server/internal_jobs/bindings.d.ts +11 -0
  92. package/esm/server/internal_jobs/bindings.d.ts.map +1 -1
  93. package/esm/server/internal_jobs/job-manager.d.ts +44 -1
  94. package/esm/server/internal_jobs/job-manager.d.ts.map +1 -1
  95. package/esm/server/internal_jobs/job-manager.js +361 -51
  96. package/esm/server/internal_jobs/key-coordinator.d.ts +260 -0
  97. package/esm/server/internal_jobs/key-coordinator.d.ts.map +1 -0
  98. package/esm/server/internal_jobs/key-coordinator.js +580 -0
  99. package/esm/server/internal_jobs/projection.d.ts.map +1 -1
  100. package/esm/server/internal_jobs/projection.js +2 -0
  101. package/esm/server/internal_jobs/runtime-worker.d.ts +5 -1
  102. package/esm/server/internal_jobs/runtime-worker.d.ts.map +1 -1
  103. package/esm/server/internal_jobs/runtime-worker.js +14 -2
  104. package/esm/server/internal_jobs/types.d.ts +5 -5
  105. package/esm/server/internal_jobs/types.d.ts.map +1 -1
  106. package/esm/server/internal_jobs/types.js +6 -0
  107. package/esm/server/service.d.ts +8 -3
  108. package/esm/server/service.d.ts.map +1 -1
  109. package/esm/server/service.js +127 -6
  110. package/esm/service/drizzle.d.ts +27 -0
  111. package/esm/service/drizzle.d.ts.map +1 -0
  112. package/esm/service/drizzle.js +84 -0
  113. package/esm/service/mod.d.ts +1 -1
  114. package/esm/service/mod.d.ts.map +1 -1
  115. package/esm/service/mod.js +1 -1
  116. package/esm/service/outbox_inbox.d.ts.map +1 -1
  117. package/esm/service/outbox_inbox.js +13 -2
  118. package/esm/trellis.d.ts +24 -8
  119. package/esm/trellis.d.ts.map +1 -1
  120. package/esm/trellis.js +44 -22
  121. package/package.json +14 -2
  122. package/script/auth/mod.d.ts +1 -1
  123. package/script/auth/mod.d.ts.map +1 -1
  124. package/script/auth/mod.js +22 -6
  125. package/script/auth/protocol.d.ts +416 -398
  126. package/script/auth/protocol.d.ts.map +1 -1
  127. package/script/auth/protocol.js +40 -37
  128. package/script/codec.d.ts +1 -0
  129. package/script/codec.d.ts.map +1 -1
  130. package/script/codec.js +1 -0
  131. package/script/contract_support/canonical.d.ts +3 -0
  132. package/script/contract_support/canonical.d.ts.map +1 -1
  133. package/script/contract_support/canonical.js +3 -0
  134. package/script/contract_support/mod.d.ts +28 -4
  135. package/script/contract_support/mod.d.ts.map +1 -1
  136. package/script/contract_support/mod.js +90 -4
  137. package/script/contract_support/protocol.d.ts +92 -7
  138. package/script/contract_support/protocol.d.ts.map +1 -1
  139. package/script/contract_support/protocol.js +41 -7
  140. package/script/errors/index.d.ts +9 -9
  141. package/script/generated-sdk/auth/api.d.ts +4 -1
  142. package/script/generated-sdk/auth/api.d.ts.map +1 -1
  143. package/script/generated-sdk/auth/api.js +6 -1
  144. package/script/generated-sdk/auth/client.d.ts +47 -32
  145. package/script/generated-sdk/auth/client.d.ts.map +1 -1
  146. package/script/generated-sdk/auth/contract.d.ts +1 -1
  147. package/script/generated-sdk/auth/contract.d.ts.map +1 -1
  148. package/script/generated-sdk/auth/contract.js +1570 -1202
  149. package/script/generated-sdk/auth/schemas.d.ts +1757 -1759
  150. package/script/generated-sdk/auth/schemas.d.ts.map +1 -1
  151. package/script/generated-sdk/auth/schemas.js +963 -768
  152. package/script/generated-sdk/auth/types.d.ts +292 -302
  153. package/script/generated-sdk/auth/types.d.ts.map +1 -1
  154. package/script/generated-sdk/auth/types.js +1 -1
  155. package/script/generated-sdk/health/client.d.ts +4 -4
  156. package/script/generated-sdk/health/client.d.ts.map +1 -1
  157. package/script/generated-sdk/health/contract.d.ts +1 -1
  158. package/script/generated-sdk/health/contract.d.ts.map +1 -1
  159. package/script/generated-sdk/health/contract.js +2 -10
  160. package/script/generated-sdk/health/schemas.d.ts +1 -14
  161. package/script/generated-sdk/health/schemas.d.ts.map +1 -1
  162. package/script/generated-sdk/health/schemas.js +1 -9
  163. package/script/generated-sdk/health/types.d.ts +3 -5
  164. package/script/generated-sdk/health/types.d.ts.map +1 -1
  165. package/script/generated-sdk/health/types.js +1 -2
  166. package/script/generated-sdk/jobs/api.d.ts +13 -0
  167. package/script/generated-sdk/jobs/api.d.ts.map +1 -1
  168. package/script/generated-sdk/jobs/client.d.ts +6 -4
  169. package/script/generated-sdk/jobs/client.d.ts.map +1 -1
  170. package/script/generated-sdk/jobs/contract.d.ts +14 -1
  171. package/script/generated-sdk/jobs/contract.d.ts.map +1 -1
  172. package/script/generated-sdk/jobs/contract.js +268 -1
  173. package/script/generated-sdk/jobs/owned_api.d.ts +13 -0
  174. package/script/generated-sdk/jobs/owned_api.d.ts.map +1 -1
  175. package/script/generated-sdk/jobs/owned_api.js +19 -0
  176. package/script/generated-sdk/jobs/schemas.d.ts +437 -0
  177. package/script/generated-sdk/jobs/schemas.d.ts.map +1 -1
  178. package/script/generated-sdk/jobs/schemas.js +212 -1
  179. package/script/generated-sdk/jobs/types.d.ts +123 -1
  180. package/script/generated-sdk/jobs/types.d.ts.map +1 -1
  181. package/script/generated-sdk/jobs/types.js +1 -1
  182. package/script/generated-sdk/state/client.d.ts +4 -4
  183. package/script/generated-sdk/state/client.d.ts.map +1 -1
  184. package/script/generated-sdk/trellis-core/api.d.ts +4 -1
  185. package/script/generated-sdk/trellis-core/api.d.ts.map +1 -1
  186. package/script/generated-sdk/trellis-core/api.js +6 -1
  187. package/script/generated-sdk/trellis-core/client.d.ts +28 -3
  188. package/script/generated-sdk/trellis-core/client.d.ts.map +1 -1
  189. package/script/generated-sdk/trellis-core/contract.d.ts +1 -1
  190. package/script/generated-sdk/trellis-core/contract.d.ts.map +1 -1
  191. package/script/generated-sdk/trellis-core/contract.js +91 -1
  192. package/script/generated-sdk/trellis-core/schemas.d.ts +113 -0
  193. package/script/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
  194. package/script/generated-sdk/trellis-core/schemas.js +81 -0
  195. package/script/generated-sdk/trellis-core/types.d.ts +23 -1
  196. package/script/generated-sdk/trellis-core/types.d.ts.map +1 -1
  197. package/script/generated-sdk/trellis-core/types.js +1 -1
  198. package/script/health.d.ts +1 -1
  199. package/script/health.d.ts.map +1 -1
  200. package/script/health.js +1 -2
  201. package/script/index.d.ts +2 -2
  202. package/script/index.d.ts.map +1 -1
  203. package/script/index.js +2 -3
  204. package/script/jobs.d.ts +69 -3
  205. package/script/jobs.d.ts.map +1 -1
  206. package/script/jobs.js +93 -3
  207. package/script/server/health.d.ts +2 -6
  208. package/script/server/health.d.ts.map +1 -1
  209. package/script/server/health_schemas.d.ts +0 -8
  210. package/script/server/health_schemas.d.ts.map +1 -1
  211. package/script/server/health_schemas.js +1 -6
  212. package/script/server/internal_jobs/bindings.d.ts +11 -0
  213. package/script/server/internal_jobs/bindings.d.ts.map +1 -1
  214. package/script/server/internal_jobs/job-manager.d.ts +44 -1
  215. package/script/server/internal_jobs/job-manager.d.ts.map +1 -1
  216. package/script/server/internal_jobs/job-manager.js +361 -51
  217. package/script/server/internal_jobs/key-coordinator.d.ts +260 -0
  218. package/script/server/internal_jobs/key-coordinator.d.ts.map +1 -0
  219. package/script/server/internal_jobs/key-coordinator.js +593 -0
  220. package/script/server/internal_jobs/projection.d.ts.map +1 -1
  221. package/script/server/internal_jobs/projection.js +2 -0
  222. package/script/server/internal_jobs/runtime-worker.d.ts +5 -1
  223. package/script/server/internal_jobs/runtime-worker.d.ts.map +1 -1
  224. package/script/server/internal_jobs/runtime-worker.js +14 -2
  225. package/script/server/internal_jobs/types.d.ts +5 -5
  226. package/script/server/internal_jobs/types.d.ts.map +1 -1
  227. package/script/server/internal_jobs/types.js +6 -0
  228. package/script/server/service.d.ts +8 -3
  229. package/script/server/service.d.ts.map +1 -1
  230. package/script/server/service.js +126 -5
  231. package/script/service/drizzle.d.ts +27 -0
  232. package/script/service/drizzle.d.ts.map +1 -0
  233. package/script/service/drizzle.js +88 -0
  234. package/script/service/mod.d.ts +1 -1
  235. package/script/service/mod.d.ts.map +1 -1
  236. package/script/service/mod.js +1 -2
  237. package/script/service/outbox_inbox.d.ts.map +1 -1
  238. package/script/service/outbox_inbox.js +13 -2
  239. package/script/trellis.d.ts +24 -8
  240. package/script/trellis.d.ts.map +1 -1
  241. package/script/trellis.js +44 -22
  242. package/src/auth/mod.ts +28 -2
  243. package/src/auth/protocol.ts +72 -37
  244. package/src/codec.ts +1 -0
  245. package/src/contract_support/canonical.ts +3 -0
  246. package/src/contract_support/mod.ts +158 -5
  247. package/src/contract_support/protocol.ts +56 -9
  248. package/src/health.ts +0 -1
  249. package/src/index.ts +2 -1
  250. package/src/jobs.ts +138 -1
  251. package/src/sdk/_generated/auth/api.ts +9 -2
  252. package/src/sdk/_generated/auth/client.ts +85 -78
  253. package/src/sdk/_generated/auth/contract.ts +1803 -1435
  254. package/src/sdk/_generated/auth/schemas.ts +1166 -971
  255. package/src/sdk/_generated/auth/types.ts +330 -314
  256. package/src/sdk/_generated/core/api.ts +9 -2
  257. package/src/sdk/_generated/core/client.ts +41 -2
  258. package/src/sdk/_generated/core/contract.ts +91 -1
  259. package/src/sdk/_generated/core/schemas.ts +81 -0
  260. package/src/sdk/_generated/core/types.ts +23 -1
  261. package/src/sdk/_generated/health/client.ts +6 -6
  262. package/src/sdk/_generated/health/contract.ts +2 -10
  263. package/src/sdk/_generated/health/schemas.ts +1 -9
  264. package/src/sdk/_generated/health/types.ts +6 -2
  265. package/src/sdk/_generated/jobs/client.ts +17 -6
  266. package/src/sdk/_generated/jobs/contract.ts +269 -1
  267. package/src/sdk/_generated/jobs/owned_api.ts +21 -0
  268. package/src/sdk/_generated/jobs/schemas.ts +213 -0
  269. package/src/sdk/_generated/jobs/types.ts +116 -1
  270. package/src/sdk/_generated/state/client.ts +6 -6
  271. package/src/server/health.ts +2 -6
  272. package/src/server/health_schemas.ts +0 -6
  273. package/src/server/internal_jobs/bindings.ts +11 -0
  274. package/src/server/internal_jobs/job-manager.ts +436 -16
  275. package/src/server/internal_jobs/key-coordinator.ts +955 -0
  276. package/src/server/internal_jobs/projection.ts +2 -0
  277. package/src/server/internal_jobs/runtime-worker.ts +17 -1
  278. package/src/server/internal_jobs/types.ts +6 -0
  279. package/src/server/service.ts +168 -9
  280. package/src/service/drizzle.ts +125 -0
  281. package/src/service/mod.ts +0 -1
  282. package/src/service/outbox_inbox.ts +16 -6
  283. package/src/trellis.ts +76 -27
package/src/trellis.ts CHANGED
@@ -479,24 +479,45 @@ type RequestErrorOf<TA extends AnyTrellisAPI, M extends MethodsOf<TA>> =
479
479
  type HandlerErrorOf<TA extends AnyTrellisAPI, M extends MethodsOf<TA>> =
480
480
  | MethodDeclaredErrorOf<TA, M>
481
481
  | TrellisErrorInstance;
482
- type EventOf<TA extends AnyTrellisAPI, E extends EventsOf<TA>> =
482
+ type EventMessageOf<TA extends AnyTrellisAPI, E extends EventsOf<TA>> =
483
483
  TA["events"][E] extends EventDesc<infer TEvent> ? InferSchemaType<TEvent>
484
484
  : never;
485
+ type EventOf<TA extends AnyTrellisAPI, E extends EventsOf<TA>> = EventMessageOf<
486
+ TA,
487
+ E
488
+ >;
485
489
  type EventDescriptorOf<TA extends AnyTrellisAPI, E extends EventsOf<TA>> =
486
490
  TA["events"][E] extends EventDesc<infer TEvent>
487
491
  ? EventDesc<TEvent> & TA["events"][E]
488
492
  : never;
489
- type EventPayloadOf<TA extends AnyTrellisAPI, E extends EventsOf<TA>> = Omit<
490
- EventOf<TA, E>,
491
- "header"
492
- >;
493
+ type EventPayloadOf<TA extends AnyTrellisAPI, E extends EventsOf<TA>> =
494
+ & EventOf<TA, E>
495
+ & Record<string, unknown>;
496
+ /** Runtime metadata assigned to every Trellis event message. */
497
+ export type TrellisEventHeader = Readonly<{
498
+ /** Stable event id used for event identity and JetStream de-duplication. */
499
+ id: string;
500
+ /** Event creation time in ISO-8601 format. */
501
+ time: string;
502
+ }>;
503
+ /** Event body plus Trellis runtime event metadata. */
504
+ export type TrellisEventMessage<
505
+ TBody extends Record<string, unknown> = Record<string, unknown>,
506
+ > = Readonly<{
507
+ /** User-authored contract event body. */
508
+ body: Readonly<TBody>;
509
+ /** Runtime metadata assigned by Trellis. */
510
+ header: TrellisEventHeader;
511
+ }>;
493
512
  /** A fully encoded event whose subject, payload, and headers are stable. */
494
513
  export type PreparedTrellisEvent<
495
514
  TPayload extends Record<string, unknown> = Record<string, unknown>,
496
515
  > = Readonly<{
497
516
  event: string;
498
517
  subject: string;
499
- payload: Readonly<TPayload & { header: { id: string; time: string } }>;
518
+ /** Runtime event metadata assigned when the event was prepared. */
519
+ header: TrellisEventHeader;
520
+ payload: Readonly<TPayload>;
500
521
  encodedPayload: string;
501
522
  headers: Readonly<Record<string, string>>;
502
523
  }>;
@@ -1088,26 +1109,18 @@ export type EventListenerContext = {
1088
1109
  };
1089
1110
 
1090
1111
  function createEventListenerContext(args: {
1091
- payload: unknown;
1092
1112
  subject: string;
1093
1113
  mode: "durable" | "ephemeral";
1094
1114
  group?: string;
1095
1115
  message: object;
1096
1116
  }): EventListenerContext {
1097
- const header = typeof args.payload === "object" && args.payload !== null
1098
- ? Reflect.get(args.payload, "header")
1099
- : undefined;
1100
- const id = typeof header === "object" && header !== null
1101
- ? Reflect.get(header, "id")
1102
- : undefined;
1103
- const time = typeof header === "object" && header !== null
1104
- ? Reflect.get(header, "time")
1105
- : undefined;
1117
+ const messageId = readMessageHeader(args.message, "Nats-Msg-Id");
1118
+ const messageTime = readMessageHeader(args.message, "Trellis-Event-Time");
1106
1119
  const sequence = Reflect.get(args.message, "seq");
1107
1120
 
1108
1121
  return {
1109
- id: typeof id === "string" ? id : "",
1110
- time: new Date(typeof time === "string" ? time : 0),
1122
+ id: messageId ?? "",
1123
+ time: new Date(messageTime ?? 0),
1111
1124
  subject: args.subject,
1112
1125
  mode: args.mode,
1113
1126
  ...(args.group ? { group: args.group } : {}),
@@ -1115,6 +1128,15 @@ function createEventListenerContext(args: {
1115
1128
  };
1116
1129
  }
1117
1130
 
1131
+ function readMessageHeader(message: object, key: string): string | undefined {
1132
+ const headers = Reflect.get(message, "headers");
1133
+ if (typeof headers !== "object" || headers === null) return undefined;
1134
+ const get = Reflect.get(headers, "get");
1135
+ if (typeof get !== "function") return undefined;
1136
+ const value = get.call(headers, key);
1137
+ return typeof value === "string" ? value : undefined;
1138
+ }
1139
+
1118
1140
  type RuntimeEventConsumers = {
1119
1141
  metadata?: RuntimeEventConsumerGroups;
1120
1142
  bindings?: Record<string, EventConsumerResourceBinding>;
@@ -1383,6 +1405,8 @@ export type HandlerTrellis<
1383
1405
  publishPrepared(
1384
1406
  event: PreparedTrellisEvent,
1385
1407
  ): AsyncResult<void, UnexpectedError>;
1408
+ /** Stops durable event listener loops owned by this handler runtime. */
1409
+ stopEventListeners(): void;
1386
1410
  };
1387
1411
 
1388
1412
  function surfaceGroupName(key: string): string {
@@ -2055,6 +2079,7 @@ export class Trellis<
2055
2079
  #operationStore?: Promise<TypedKV<typeof DurableOperationRecordSchema>>;
2056
2080
  #eventConsumers: RuntimeEventConsumers;
2057
2081
  #durableEventLoops = new Map<string, DurableEventConsumerLoop<TA>>();
2082
+ #durableEventListenersStopped = false;
2058
2083
 
2059
2084
  constructor(
2060
2085
  name: string, // Must be unique for a service
@@ -2323,6 +2348,7 @@ export class Trellis<
2323
2348
  prepare: (event, data) => this.prepare(event, data),
2324
2349
  publish: (event, data) => this.publish(event, data),
2325
2350
  publishPrepared: (event) => this.publishPrepared(event),
2351
+ stopEventListeners: () => this.stopEventListeners(),
2326
2352
  };
2327
2353
  }
2328
2354
 
@@ -3954,10 +3980,7 @@ export class Trellis<
3954
3980
  id: ulid(),
3955
3981
  time: new Date().toISOString(),
3956
3982
  };
3957
- const payload = Object.freeze({
3958
- ...data,
3959
- header: Object.freeze(header),
3960
- });
3983
+ const payload = Object.freeze({ ...data });
3961
3984
  const msg = encodeSchema(ctx.event, payload).take();
3962
3985
  if (isErr(msg)) {
3963
3986
  logger.error({ err: msg.error }, "Failed to encode event.");
@@ -3973,6 +3996,7 @@ export class Trellis<
3973
3996
 
3974
3997
  const headers = natsHeaders();
3975
3998
  headers.set("Nats-Msg-Id", header.id);
3999
+ headers.set("Trellis-Event-Time", header.time);
3976
4000
  injectTraceContext(createNatsHeaderCarrier(headers));
3977
4001
 
3978
4002
  const headerRecord: Record<string, string> = {};
@@ -3983,6 +4007,7 @@ export class Trellis<
3983
4007
  return ok(Object.freeze({
3984
4008
  event: event.toString(),
3985
4009
  subject,
4010
+ header: Object.freeze(header),
3986
4011
  payload,
3987
4012
  encodedPayload: msg,
3988
4013
  headers: Object.freeze(headerRecord),
@@ -4199,7 +4224,6 @@ export class Trellis<
4199
4224
  const result = await Promise.resolve(args.fn(
4200
4225
  args.payload as EventOf<TA, EventsOf<TA>>,
4201
4226
  createEventListenerContext({
4202
- payload: args.payload,
4203
4227
  subject: args.message.subject,
4204
4228
  mode: args.mode,
4205
4229
  ...(args.group ? { group: args.group } : {}),
@@ -4301,7 +4325,7 @@ export class Trellis<
4301
4325
  fn: EventCallback<EventOf<TA, EventsOf<TA>>>;
4302
4326
  signal?: AbortSignal;
4303
4327
  }): void {
4304
- if (args.signal?.aborted) return;
4328
+ if (args.signal?.aborted || this.#durableEventListenersStopped) return;
4305
4329
 
4306
4330
  const loop = this.#durableEventLoops.get(args.group) ?? {
4307
4331
  registrations: [],
@@ -4331,7 +4355,10 @@ export class Trellis<
4331
4355
  group: string,
4332
4356
  loop: DurableEventConsumerLoop<TA>,
4333
4357
  ): void {
4334
- if (loop.started || !this.#durableEventConsumerGroupReady(group, loop)) {
4358
+ if (
4359
+ this.#durableEventListenersStopped || loop.started ||
4360
+ !this.#durableEventConsumerGroupReady(group, loop)
4361
+ ) {
4335
4362
  return;
4336
4363
  }
4337
4364
  loop.started = true;
@@ -4381,7 +4408,10 @@ export class Trellis<
4381
4408
  if (isErr(info)) return info;
4382
4409
 
4383
4410
  const consumer = this.js.consumers.getConsumerFromInfo(info);
4384
- while (this.#durableEventConsumerGroupReady(group, loop)) {
4411
+ while (
4412
+ !this.#durableEventListenersStopped &&
4413
+ this.#durableEventConsumerGroupReady(group, loop)
4414
+ ) {
4385
4415
  const messages = await consumer.fetch({
4386
4416
  max_messages: 1,
4387
4417
  expires: 30_000,
@@ -4394,10 +4424,20 @@ export class Trellis<
4394
4424
  await this.#handleDurableEventConsumer(group, loop, messages)
4395
4425
  .orThrow();
4396
4426
  }
4427
+ } catch (cause) {
4428
+ if (
4429
+ this.#durableEventListenersStopped ||
4430
+ !this.#durableEventConsumerGroupReady(group, loop)
4431
+ ) {
4432
+ return ok(undefined);
4433
+ }
4434
+ return err(new UnexpectedError({ cause, context: { group } }));
4397
4435
  } finally {
4398
4436
  loop.started = false;
4399
4437
  loop.messages = undefined;
4400
- this.#startDurableEventConsumer(group, loop);
4438
+ if (!this.#durableEventListenersStopped) {
4439
+ this.#startDurableEventConsumer(group, loop);
4440
+ }
4401
4441
  }
4402
4442
  return ok(undefined);
4403
4443
  })());
@@ -4549,6 +4589,15 @@ export class Trellis<
4549
4589
  return this.#tasks.wait();
4550
4590
  }
4551
4591
 
4592
+ /** Stops durable event listener loops without closing the underlying transport. */
4593
+ stopEventListeners(): void {
4594
+ this.#durableEventListenersStopped = true;
4595
+ for (const loop of this.#durableEventLoops.values()) {
4596
+ loop.registrations.splice(0, loop.registrations.length);
4597
+ loop.messages?.stop();
4598
+ }
4599
+ }
4600
+
4552
4601
  // FIXME: If are validating things twice in most cases...
4553
4602
  template(
4554
4603
  subject: string,