@toa.io/core 1.0.0-alpha.32 → 1.0.0-alpha.321

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 (286) hide show
  1. package/package.json +28 -12
  2. package/transpiled/abandon.d.ts +9 -0
  3. package/transpiled/abandon.js +37 -0
  4. package/transpiled/abandon.js.map +1 -0
  5. package/transpiled/assignment.d.ts +6 -0
  6. package/transpiled/assignment.js +25 -0
  7. package/transpiled/assignment.js.map +1 -0
  8. package/transpiled/call.d.ts +10 -0
  9. package/transpiled/call.js +187 -0
  10. package/transpiled/call.js.map +1 -0
  11. package/transpiled/cascade.d.ts +7 -0
  12. package/transpiled/cascade.js +28 -0
  13. package/transpiled/cascade.js.map +1 -0
  14. package/transpiled/component.d.ts +17 -0
  15. package/transpiled/component.js +151 -0
  16. package/transpiled/component.js.map +1 -0
  17. package/transpiled/composition.d.ts +6 -0
  18. package/transpiled/composition.js +20 -0
  19. package/transpiled/composition.js.map +1 -0
  20. package/transpiled/connector.d.ts +71 -0
  21. package/transpiled/connector.js +248 -0
  22. package/transpiled/connector.js.map +1 -0
  23. package/transpiled/context.d.ts +25 -0
  24. package/transpiled/context.js +55 -0
  25. package/transpiled/context.js.map +1 -0
  26. package/transpiled/contract/component.d.ts +37 -0
  27. package/transpiled/contract/component.js +94 -0
  28. package/transpiled/contract/component.js.map +1 -0
  29. package/transpiled/contract/contract.d.ts +10 -0
  30. package/transpiled/contract/contract.js +14 -0
  31. package/transpiled/contract/contract.js.map +1 -0
  32. package/transpiled/contract/index.d.ts +4 -0
  33. package/transpiled/contract/index.js +5 -0
  34. package/transpiled/contract/index.js.map +1 -0
  35. package/transpiled/contract/reply.d.ts +7 -0
  36. package/transpiled/contract/reply.js +48 -0
  37. package/transpiled/contract/reply.js.map +1 -0
  38. package/transpiled/contract/request.d.ts +49 -0
  39. package/transpiled/contract/request.js +152 -0
  40. package/transpiled/contract/request.js.map +1 -0
  41. package/transpiled/contract/schemas.d.ts +4 -0
  42. package/transpiled/contract/schemas.js +38 -0
  43. package/transpiled/contract/schemas.js.map +1 -0
  44. package/transpiled/contract/system.d.ts +33 -0
  45. package/transpiled/contract/system.js +76 -0
  46. package/transpiled/contract/system.js.map +1 -0
  47. package/transpiled/deliveries.d.ts +22 -0
  48. package/transpiled/deliveries.js +31 -0
  49. package/transpiled/deliveries.js.map +1 -0
  50. package/transpiled/effect.d.ts +7 -0
  51. package/transpiled/effect.js +13 -0
  52. package/transpiled/effect.js.map +1 -0
  53. package/transpiled/emission.d.ts +10 -0
  54. package/transpiled/emission.js +16 -0
  55. package/transpiled/emission.js.map +1 -0
  56. package/transpiled/encoded.d.ts +16 -0
  57. package/transpiled/encoded.js +25 -0
  58. package/transpiled/encoded.js.map +1 -0
  59. package/transpiled/entities/changeset.d.ts +10 -0
  60. package/transpiled/entities/changeset.js +27 -0
  61. package/transpiled/entities/changeset.js.map +1 -0
  62. package/transpiled/entities/entity.d.ts +19 -0
  63. package/transpiled/entities/entity.js +137 -0
  64. package/transpiled/entities/entity.js.map +1 -0
  65. package/transpiled/entities/factory.d.ts +27 -0
  66. package/transpiled/entities/factory.js +38 -0
  67. package/transpiled/entities/factory.js.map +1 -0
  68. package/transpiled/entities/index.d.ts +5 -0
  69. package/transpiled/entities/index.js +6 -0
  70. package/transpiled/entities/index.js.map +1 -0
  71. package/transpiled/entities/newid.d.ts +11 -0
  72. package/transpiled/entities/newid.js +41 -0
  73. package/transpiled/entities/newid.js.map +1 -0
  74. package/transpiled/entities/set.d.ts +10 -0
  75. package/transpiled/entities/set.js +19 -0
  76. package/transpiled/entities/set.js.map +1 -0
  77. package/transpiled/event.d.ts +20 -0
  78. package/transpiled/event.js +65 -0
  79. package/transpiled/event.js.map +1 -0
  80. package/transpiled/exceptions.d.ts +110 -0
  81. package/transpiled/exceptions.js +215 -0
  82. package/transpiled/exceptions.js.map +1 -0
  83. package/transpiled/gate.d.ts +40 -0
  84. package/transpiled/gate.js +84 -0
  85. package/transpiled/gate.js.map +1 -0
  86. package/transpiled/guard.d.ts +7 -0
  87. package/transpiled/guard.js +12 -0
  88. package/transpiled/guard.js.map +1 -0
  89. package/transpiled/halting.d.ts +16 -0
  90. package/transpiled/halting.js +25 -0
  91. package/transpiled/halting.js.map +1 -0
  92. package/transpiled/index.d.ts +45 -0
  93. package/transpiled/index.js +37 -0
  94. package/transpiled/index.js.map +1 -0
  95. package/transpiled/instance.d.ts +10 -0
  96. package/transpiled/instance.js +30 -0
  97. package/transpiled/instance.js.map +1 -0
  98. package/transpiled/locator.d.ts +12 -0
  99. package/transpiled/locator.js +32 -0
  100. package/transpiled/locator.js.map +1 -0
  101. package/transpiled/measurements.d.ts +20 -0
  102. package/transpiled/measurements.js +40 -0
  103. package/transpiled/measurements.js.map +1 -0
  104. package/transpiled/observation.d.ts +7 -0
  105. package/transpiled/observation.js +14 -0
  106. package/transpiled/observation.js.map +1 -0
  107. package/transpiled/operation.d.ts +77 -0
  108. package/transpiled/operation.js +216 -0
  109. package/transpiled/operation.js.map +1 -0
  110. package/transpiled/outbox.d.ts +45 -0
  111. package/transpiled/outbox.js +448 -0
  112. package/transpiled/outbox.js.map +1 -0
  113. package/transpiled/outbox.measurements.d.ts +4 -0
  114. package/transpiled/outbox.measurements.js +38 -0
  115. package/transpiled/outbox.measurements.js.map +1 -0
  116. package/transpiled/parts.d.ts +20 -0
  117. package/transpiled/parts.js +23 -0
  118. package/transpiled/parts.js.map +1 -0
  119. package/transpiled/query/criteria.d.ts +6 -0
  120. package/transpiled/query/criteria.js +177 -0
  121. package/transpiled/query/criteria.js.map +1 -0
  122. package/transpiled/query/options.d.ts +3 -0
  123. package/transpiled/query/options.js +34 -0
  124. package/transpiled/query/options.js.map +1 -0
  125. package/transpiled/query.d.ts +9 -0
  126. package/transpiled/query.js +57 -0
  127. package/transpiled/query.js.map +1 -0
  128. package/transpiled/receiver.d.ts +20 -0
  129. package/transpiled/receiver.js +113 -0
  130. package/transpiled/receiver.js.map +1 -0
  131. package/transpiled/reflection.d.ts +9 -0
  132. package/transpiled/reflection.js +13 -0
  133. package/transpiled/reflection.js.map +1 -0
  134. package/transpiled/regional.d.ts +22 -0
  135. package/transpiled/regional.js +55 -0
  136. package/transpiled/regional.js.map +1 -0
  137. package/transpiled/remote.d.ts +10 -0
  138. package/transpiled/remote.js +11 -0
  139. package/transpiled/remote.js.map +1 -0
  140. package/transpiled/rendering.d.ts +13 -0
  141. package/transpiled/rendering.js +21 -0
  142. package/transpiled/rendering.js.map +1 -0
  143. package/transpiled/safety.d.ts +5 -0
  144. package/transpiled/safety.js +26 -0
  145. package/transpiled/safety.js.map +1 -0
  146. package/transpiled/state.d.ts +36 -0
  147. package/transpiled/state.js +131 -0
  148. package/transpiled/state.js.map +1 -0
  149. package/transpiled/trail.d.ts +78 -0
  150. package/transpiled/trail.js +112 -0
  151. package/transpiled/trail.js.map +1 -0
  152. package/transpiled/transition.d.ts +14 -0
  153. package/transpiled/transition.js +51 -0
  154. package/transpiled/transition.js.map +1 -0
  155. package/transpiled/transmission.d.ts +8 -0
  156. package/transpiled/transmission.js +30 -0
  157. package/transpiled/transmission.js.map +1 -0
  158. package/transpiled/types/atomicity.d.ts +58 -0
  159. package/transpiled/types/atomicity.js +2 -0
  160. package/transpiled/types/atomicity.js.map +1 -0
  161. package/transpiled/types/bindings.d.ts +82 -0
  162. package/transpiled/types/bindings.js +2 -0
  163. package/transpiled/types/bindings.js.map +1 -0
  164. package/transpiled/types/bridges.d.ts +41 -0
  165. package/transpiled/types/bridges.js +2 -0
  166. package/transpiled/types/bridges.js.map +1 -0
  167. package/transpiled/types/extensions.d.ts +121 -0
  168. package/transpiled/types/extensions.js +2 -0
  169. package/transpiled/types/extensions.js.map +1 -0
  170. package/transpiled/types/inbox.d.ts +27 -0
  171. package/transpiled/types/inbox.js +2 -0
  172. package/transpiled/types/inbox.js.map +1 -0
  173. package/transpiled/types/index.d.ts +14 -0
  174. package/transpiled/types/index.js +9 -0
  175. package/transpiled/types/index.js.map +1 -0
  176. package/transpiled/types/message.d.ts +16 -0
  177. package/transpiled/types/message.js +2 -0
  178. package/transpiled/types/message.js.map +1 -0
  179. package/transpiled/types/operations.d.ts +15 -0
  180. package/transpiled/types/operations.js +2 -0
  181. package/transpiled/types/operations.js.map +1 -0
  182. package/transpiled/types/outbox.d.ts +93 -0
  183. package/transpiled/types/outbox.js +2 -0
  184. package/transpiled/types/outbox.js.map +1 -0
  185. package/transpiled/types/receiver.d.ts +9 -0
  186. package/transpiled/types/receiver.js +2 -0
  187. package/transpiled/types/receiver.js.map +1 -0
  188. package/transpiled/types/request.d.ts +119 -0
  189. package/transpiled/types/request.js +2 -0
  190. package/transpiled/types/request.js.map +1 -0
  191. package/transpiled/types/state.d.ts +9 -0
  192. package/transpiled/types/state.js +2 -0
  193. package/transpiled/types/state.js.map +1 -0
  194. package/transpiled/types/storages.d.ts +158 -0
  195. package/transpiled/types/storages.js +2 -0
  196. package/transpiled/types/storages.js.map +1 -0
  197. package/transpiled/unmanaged.d.ts +5 -0
  198. package/transpiled/unmanaged.js +7 -0
  199. package/transpiled/unmanaged.js.map +1 -0
  200. package/src/assignment.js +0 -31
  201. package/src/call.js +0 -42
  202. package/src/cascade.js +0 -35
  203. package/src/component.js +0 -41
  204. package/src/composition.js +0 -25
  205. package/src/connector.js +0 -183
  206. package/src/context.js +0 -55
  207. package/src/contract/conditions.js +0 -21
  208. package/src/contract/index.js +0 -7
  209. package/src/contract/reply.js +0 -25
  210. package/src/contract/request.js +0 -67
  211. package/src/contract/schemas/error.yaml +0 -9
  212. package/src/contract/schemas/index.js +0 -7
  213. package/src/contract/schemas/query.yaml +0 -30
  214. package/src/discovery.js +0 -44
  215. package/src/emission.js +0 -23
  216. package/src/entities/changeset.js +0 -38
  217. package/src/entities/entity.js +0 -74
  218. package/src/entities/factory.js +0 -33
  219. package/src/entities/index.js +0 -5
  220. package/src/entities/set.js +0 -15
  221. package/src/event.js +0 -40
  222. package/src/exceptions.js +0 -100
  223. package/src/exposition.js +0 -27
  224. package/src/index.js +0 -47
  225. package/src/locator.js +0 -54
  226. package/src/observation.js +0 -20
  227. package/src/operation.js +0 -69
  228. package/src/query/criteria.js +0 -41
  229. package/src/query/options.js +0 -40
  230. package/src/query.js +0 -41
  231. package/src/receiver.js +0 -61
  232. package/src/reflection.js +0 -28
  233. package/src/remote.js +0 -17
  234. package/src/state.js +0 -99
  235. package/src/transition.js +0 -67
  236. package/src/transmission.js +0 -33
  237. package/test/call.fixtures.js +0 -27
  238. package/test/call.test.js +0 -46
  239. package/test/component.fixtures.js +0 -21
  240. package/test/component.test.js +0 -40
  241. package/test/connector.fixtures.js +0 -40
  242. package/test/connector.test.js +0 -176
  243. package/test/context.fixtures.js +0 -18
  244. package/test/context.test.js +0 -29
  245. package/test/contract/conditions.test.js +0 -26
  246. package/test/contract/contract.fixtures.js +0 -33
  247. package/test/contract/request.test.js +0 -112
  248. package/test/emission.fixtures.js +0 -17
  249. package/test/emission.test.js +0 -35
  250. package/test/entities/entity.fixtures.js +0 -29
  251. package/test/entities/entity.test.js +0 -65
  252. package/test/entities/factory.fixtures.js +0 -18
  253. package/test/entities/factory.test.js +0 -48
  254. package/test/entities/set.fixtures.js +0 -11
  255. package/test/entities/set.test.js +0 -12
  256. package/test/event.fixtures.js +0 -29
  257. package/test/event.test.js +0 -118
  258. package/test/locator.test.js +0 -113
  259. package/test/query.fixtures.js +0 -100
  260. package/test/query.test.js +0 -86
  261. package/test/receiver.fixtures.js +0 -23
  262. package/test/receiver.test.js +0 -95
  263. package/test/reflection.test.js +0 -30
  264. package/test/state.fixtures.js +0 -47
  265. package/test/state.test.js +0 -46
  266. package/test/transmission.fixtures.js +0 -15
  267. package/test/transmission.test.js +0 -46
  268. package/types/bindings.d.ts +0 -40
  269. package/types/bridges.ts +0 -30
  270. package/types/component.d.ts +0 -9
  271. package/types/connector.d.ts +0 -18
  272. package/types/context.d.ts +0 -21
  273. package/types/entity.d.ts +0 -46
  274. package/types/event.d.ts +0 -11
  275. package/types/exception.d.ts +0 -4
  276. package/types/extensions.d.ts +0 -29
  277. package/types/index.ts +0 -14
  278. package/types/locator.d.ts +0 -13
  279. package/types/message.d.ts +0 -3
  280. package/types/operations.d.ts +0 -2
  281. package/types/query.d.ts +0 -15
  282. package/types/receiver.d.ts +0 -12
  283. package/types/reflection.d.ts +0 -14
  284. package/types/request.d.ts +0 -23
  285. package/types/state.d.ts +0 -35
  286. package/types/storages.d.ts +0 -71
@@ -0,0 +1,40 @@
1
+ import { registry } from 'openspan';
2
+ /**
3
+ * What core measures, declared once for the process.
4
+ *
5
+ * An invocation and a call are two metrics rather than one with a `kind` label: a `Remote` is a
6
+ * `Component` too and names the very endpoint the callee does, so a single name would hold two
7
+ * quantities — the callee's own work, and the caller's round trip with the transport in it — and
8
+ * would count every remote call twice, once in each process.
9
+ */
10
+ const meters = registry();
11
+ const COMPONENT = { component: null };
12
+ const ENDPOINT = { component: null, operation: null };
13
+ /** Prometheus' own ladder, in seconds: from five milliseconds to ten seconds. */
14
+ export const DURATIONS = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];
15
+ export const operation = {
16
+ duration: meters.histogram('toa.operation.duration', { buckets: DURATIONS, unit: 's' }, ENDPOINT),
17
+ /** a refusal the operation chose: the operation working */
18
+ errors: meters.counter('toa.operation.errors', {
19
+ ...ENDPOINT,
20
+ code: null
21
+ }),
22
+ /** a failure nobody chose; `outcome` says whether another attempt could pass */
23
+ exceptions: meters.counter('toa.operation.exceptions', {
24
+ ...ENDPOINT,
25
+ code: null,
26
+ outcome: null
27
+ }),
28
+ inflight: meters.gauge('toa.operation.inflight', COMPONENT)
29
+ };
30
+ export const call = {
31
+ duration: meters.histogram('toa.call.duration', { buckets: DURATIONS, unit: 's' }, ENDPOINT),
32
+ /** only what the transmission raised: what the callee sent back is counted where it happened */
33
+ exceptions: meters.counter('toa.call.exceptions', { ...ENDPOINT, code: null }),
34
+ /** callers waiting, which is held for the whole round trip and not only while one runs */
35
+ inflight: meters.gauge('toa.call.inflight', COMPONENT)
36
+ };
37
+ export const event = {
38
+ publish: meters.histogram('toa.event.publish.duration', { buckets: DURATIONS, unit: 's' }, { event: null })
39
+ };
40
+ //# sourceMappingURL=measurements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measurements.js","sourceRoot":"","sources":["../source/measurements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAEnC;;;;;;;GAOG;AACH,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAA;AAEzB,MAAM,SAAS,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;AACrC,MAAM,QAAQ,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;AAErD,iFAAiF;AACjF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;AAElF,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC,SAAS,CACxB,wBAAwB,EACxB,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,EACjC,QAAQ,CACT;IAED,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE;QAC7C,GAAG,QAAQ;QACX,IAAI,EAAE,IAAI;KACX,CAAC;IAEF,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,0BAA0B,EAAE;QACrD,GAAG,QAAQ;QACX,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,IAAI;KACd,CAAC;IAEF,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,SAAS,CAAC;CAC5D,CAAA;AAED,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC,SAAS,CACxB,mBAAmB,EACnB,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,EACjC,QAAQ,CACT;IAED,gGAAgG;IAChG,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAE9E,0FAA0F;IAC1F,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,SAAS,CAAC;CACvD,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,OAAO,EAAE,MAAM,CAAC,SAAS,CACvB,4BAA4B,EAC5B,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,EACjC,EAAE,KAAK,EAAE,IAAI,EAAE,CAChB;CACF,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { Operation } from './operation.ts';
2
+ import type { Store } from './operation.ts';
3
+ export declare class Observation extends Operation {
4
+ /** an observation answers what it read, and writes none of it back */
5
+ protected projects: boolean;
6
+ protected run(store: Store): Promise<void>;
7
+ }
@@ -0,0 +1,14 @@
1
+ import { Operation } from './operation.js';
2
+ export class Observation extends Operation {
3
+ /** an observation answers what it read, and writes none of it back */
4
+ projects = true;
5
+ async run(store) {
6
+ const scope = store.scope;
7
+ if (scope === null ||
8
+ (scope?.deleted === true && store.request.query?.options?.deleted !== true))
9
+ store.reply = null;
10
+ else
11
+ await super.run(store);
12
+ }
13
+ }
14
+ //# sourceMappingURL=observation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation.js","sourceRoot":"","sources":["../source/observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAI1C,MAAM,OAAO,WAAY,SAAQ,SAAS;IACxC,sEAAsE;IACnD,QAAQ,GAAY,IAAI,CAAA;IAExB,KAAK,CAAC,GAAG,CAAC,KAAY;QACvC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAsB,CAAA;QAE1C,IACE,KAAK,KAAK,IAAI;YACd,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,IAAK,KAAK,CAAC,OAAO,CAAC,KAAa,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;YAEpF,KAAK,CAAC,KAAK,GAAG,IAAI,CAAA;;YACf,MAAM,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;CACF"}
@@ -0,0 +1,77 @@
1
+ import { Readable } from 'node:stream';
2
+ import { Connector } from './connector.ts';
3
+ import type { Cascade } from './cascade.ts';
4
+ import type { State } from './state.ts';
5
+ import type { Query as Translator } from './query.ts';
6
+ import type { Contract } from './contract/contract.ts';
7
+ import type { Entity } from './entities/entity.ts';
8
+ import type { EntitySet } from './entities/set.ts';
9
+ import type { Changeset } from './entities/changeset.ts';
10
+ import type { scope as Scope } from './types/operations.ts';
11
+ import type { Call } from './types/inbox.ts';
12
+ import type { Envelope, Query } from './types/request.ts';
13
+ /** What an operation acquires for the algorithm to run against. */
14
+ export type Scoped = Entity | EntitySet | Changeset | Readable | null;
15
+ /** What one invocation carries from step to step. */
16
+ export interface Store {
17
+ request: Envelope;
18
+ scope?: Scoped;
19
+ state?: any;
20
+ reply?: any;
21
+ /** set by a transition, which is the only operation that runs its steps again */
22
+ retry?: () => Promise<any>;
23
+ }
24
+ export interface Contracts {
25
+ request: Contract;
26
+ reply: Contract;
27
+ }
28
+ export interface Definition {
29
+ scope: Scope;
30
+ concurrency?: string;
31
+ /**
32
+ * Whether the same call arriving twice changes state once; see `documentation/inbox.md`. A
33
+ * number is how many seconds a call is remembered, where the deployment's window is not the
34
+ * one its callers retry within.
35
+ */
36
+ once?: boolean | number;
37
+ /** every call begins a chain of its own; see `documentation/cycles.md` */
38
+ unchained?: boolean;
39
+ }
40
+ export declare class Operation extends Connector {
41
+ #private;
42
+ scope: State;
43
+ /** whether every call begins a chain of its own, which `Component.invoke` reads */
44
+ readonly unchained: boolean;
45
+ /**
46
+ * Whether what this operation acquires may be modified and committed. Only a
47
+ * transition commits, and only a commit needs the pre-image an entity keeps
48
+ * to diff the new state against.
49
+ *
50
+ * @protected
51
+ */
52
+ protected mutable: boolean;
53
+ /** whether a query of this operation may name the properties its storage reads */
54
+ protected projects: boolean;
55
+ constructor(cascade: Cascade, scope: State, contracts: Contracts, query: Translator, definition: Definition);
56
+ invoke(request: Envelope): Promise<any>;
57
+ /**
58
+ * The call, once. What it answered is recorded with what it changed, in one transaction, so a
59
+ * second arrival of the same identity finds the key taken, changes nothing, and is answered
60
+ * with what the first one answered.
61
+ *
62
+ * The read in front of it is not what makes that true — the key is — but it is what keeps the
63
+ * ordinary duplicate from running the algorithm at all, and the ordinary duplicate is a
64
+ * retransmission that arrives after the first call has finished.
65
+ */
66
+ protected once(store: Store): Promise<any>;
67
+ /**
68
+ * What is recorded with the write. Read where the write is made, which is after the algorithm
69
+ * has run, because the reply is what a duplicate is answered with.
70
+ */
71
+ protected call(store: Store): Call | undefined;
72
+ protected process(store: Store): Promise<any>;
73
+ protected acquire(store: Store): Promise<void>;
74
+ protected run(store: Store): Promise<void>;
75
+ protected commit(_store: Store): Promise<void>;
76
+ protected query(query?: Query): Promise<Scoped>;
77
+ }
@@ -0,0 +1,216 @@
1
+ import { Readable, Transform, pipeline } from 'node:stream';
2
+ import { Connector } from './connector.js';
3
+ import { codes, SystemException, RequestContractException } from './exceptions.js';
4
+ import * as parts from './parts.js';
5
+ import { environment } from '@toa.io/generic';
6
+ export class Operation extends Connector {
7
+ scope;
8
+ /** whether every call begins a chain of its own, which `Component.invoke` reads */
9
+ unchained;
10
+ /**
11
+ * Whether what this operation acquires may be modified and committed. Only a
12
+ * transition commits, and only a commit needs the pre-image an entity keeps
13
+ * to diff the new state against.
14
+ *
15
+ * @protected
16
+ */
17
+ mutable = false;
18
+ /** whether a query of this operation may name the properties its storage reads */
19
+ projects = false;
20
+ #cascade;
21
+ #contracts;
22
+ #query;
23
+ #scope;
24
+ #once;
25
+ /** what this operation states of how long a call is remembered; the deployment's where absent */
26
+ #retention;
27
+ /** a reply is validated only on local environments, which are set before an operation is built */
28
+ #local;
29
+ // eslint-disable-next-line max-params
30
+ constructor(cascade, scope, contracts, query, definition) {
31
+ super();
32
+ this.scope = scope;
33
+ this.unchained = definition.unchained === true;
34
+ this.#cascade = cascade;
35
+ this.#contracts = contracts;
36
+ this.#query = query;
37
+ this.#scope = definition.scope;
38
+ this.#once = definition.once === true || typeof definition.once === 'number';
39
+ this.#retention = typeof definition.once === 'number' ? definition.once : undefined;
40
+ this.#local = environment.get('TOA_ENV') === 'local';
41
+ this.depends(cascade);
42
+ }
43
+ async invoke(request) {
44
+ try {
45
+ /*
46
+ * A projection is what a storage reads, and only an observation's read is never written
47
+ * back: a transition replaces the record it read, an assignment's event carries the record
48
+ * it changed, and an effect reads for what it does next. Refused here rather than by the
49
+ * contract alone, because an authentic request skips the contract.
50
+ */
51
+ if (!this.projects && request.query?.projection !== undefined)
52
+ throw new RequestContractException('`projection` is read by an observation alone');
53
+ if (request.authentic !== true)
54
+ this.#contracts.request.fit(request);
55
+ // the request carries the query onward in its parsed form: what a storage is given,
56
+ // not what the caller sent
57
+ if ('query' in request)
58
+ request.query = this.#query.parse(request.query);
59
+ // validate entity
60
+ if ('entity' in request)
61
+ this.scope.fit(request.entity);
62
+ const store = { request };
63
+ const reply = this.#once ? await this.once(store) : await this.process(store);
64
+ return restrict(reply, request.output);
65
+ }
66
+ catch (e) {
67
+ const exception = e instanceof Error ? new SystemException(e) : e;
68
+ return { exception };
69
+ }
70
+ }
71
+ /**
72
+ * The call, once. What it answered is recorded with what it changed, in one transaction, so a
73
+ * second arrival of the same identity finds the key taken, changes nothing, and is answered
74
+ * with what the first one answered.
75
+ *
76
+ * The read in front of it is not what makes that true — the key is — but it is what keeps the
77
+ * ordinary duplicate from running the algorithm at all, and the ordinary duplicate is a
78
+ * retransmission that arrives after the first call has finished.
79
+ */
80
+ async once(store) {
81
+ const { id } = store.request;
82
+ if (id === undefined)
83
+ throw new RequestContractException('a request to an operation declared `once` carries no id');
84
+ const recalled = await this.scope.recall(id);
85
+ if (recalled !== null)
86
+ return recalled;
87
+ try {
88
+ return await this.process(store);
89
+ }
90
+ catch (exception) {
91
+ if (exception?.code !== codes.DuplicateCall)
92
+ throw exception;
93
+ /*
94
+ * It was made between the read and the write — a duplicate that arrived while the first
95
+ * was still running, and lost. Nothing of this one was committed, so what is answered is
96
+ * the other one's reply. Absent only if the record expired in between, which is the
97
+ * window closing on a call nobody is waiting on any more.
98
+ */
99
+ return (await this.scope.recall(id)) ?? { exception };
100
+ }
101
+ }
102
+ /**
103
+ * What is recorded with the write. Read where the write is made, which is after the algorithm
104
+ * has run, because the reply is what a duplicate is answered with.
105
+ */
106
+ call(store) {
107
+ if (!this.#once)
108
+ return undefined;
109
+ /*
110
+ * A copy: an assignment fills its output in after the write it is recorded by returns, and
111
+ * what is recorded must be what was known when the record was made rather than whatever the
112
+ * reply became afterwards.
113
+ */
114
+ const call = { id: store.request.id, reply: { ...store.reply } };
115
+ if (this.#retention !== undefined)
116
+ call.retention = this.#retention;
117
+ return call;
118
+ }
119
+ async process(store) {
120
+ await this.acquire(store);
121
+ await this.run(store);
122
+ await this.commit(store);
123
+ return store.reply;
124
+ }
125
+ async acquire(store) {
126
+ if (this.#scope === 'none')
127
+ return;
128
+ const scope = await this.query(store.request.query);
129
+ const raw = scope === null || scope instanceof Readable;
130
+ store.scope = scope;
131
+ store.state = raw ? scope : scope.get();
132
+ }
133
+ async run(store) {
134
+ const { request, state } = store;
135
+ const reply = await this.#cascade.run(request.input, state);
136
+ if (this.#local && !(reply instanceof Readable))
137
+ this.#contracts.reply.fit(reply);
138
+ store.reply = reply;
139
+ }
140
+ async commit(_store) { }
141
+ async query(query) {
142
+ if (query === undefined)
143
+ throw new RequestContractException('Request query is required');
144
+ const acquire = this.scope[this.#scope];
145
+ return acquire.call(this.scope, query, this.mutable);
146
+ }
147
+ }
148
+ /**
149
+ * What a caller receives of the output it asked for: each object of it keeps the properties the
150
+ * request named, in the order the object holds them, and an empty list leaves no output at all.
151
+ * A system property is one of them: a caller that reads `VERSION` asks for it. An object is one
152
+ * the output is, one of an array it is, or one a stream it is yields. An error, an exception and
153
+ * a value that is not an object are answered as they are.
154
+ */
155
+ function restrict(reply, output) {
156
+ if (output === undefined || reply === null || typeof reply !== 'object')
157
+ return reply;
158
+ // a stream is answered bare, where anything else is answered in `output`
159
+ if (reply instanceof Readable)
160
+ return restrict({ output: reply }, output).output ?? {};
161
+ const answered = reply.output;
162
+ if (answered === undefined || answered === null)
163
+ return reply;
164
+ if (output.length === 0) {
165
+ // nobody reads it, and what it holds open — a cursor, a reply pipe — is let go now
166
+ if (answered instanceof Readable)
167
+ answered.destroy();
168
+ delete reply.output;
169
+ return reply;
170
+ }
171
+ if (typeof answered !== 'object')
172
+ return reply;
173
+ const allowed = new Set(output);
174
+ // a stream of bytes is a value, as a primitive is: there is no property of it to leave out
175
+ if (answered instanceof Readable)
176
+ reply.output = answered.readableObjectMode ? restricted(answered, allowed) : answered;
177
+ else if (Array.isArray(answered))
178
+ reply.output = answered.map((value) => fitted(value, allowed));
179
+ else
180
+ reply.output = fit(answered, allowed);
181
+ return reply;
182
+ }
183
+ /**
184
+ * A stream of what `fitted` makes of each value. Joined by `pipeline`, so that a failure of
185
+ * either side reaches the other: the source's error is the reader's, and a reader that stops
186
+ * reading closes the source.
187
+ */
188
+ function restricted(source, allowed) {
189
+ const transform = new Transform({
190
+ objectMode: true,
191
+ transform(value, _, callback) {
192
+ callback(null, fitted(value, allowed));
193
+ }
194
+ });
195
+ return pipeline(source, transform, noop);
196
+ }
197
+ function fitted(value, allowed) {
198
+ // what a part carries of the set is its entry; a removal and a token are not the entity's
199
+ if (parts.is(value))
200
+ return 'entry' in value ? { entry: fit(value.entry, allowed) } : value;
201
+ return value !== null && typeof value === 'object' && !ArrayBuffer.isView(value)
202
+ ? fit(value, allowed)
203
+ : value;
204
+ }
205
+ // what `pipeline` reports is what each stream already carries to its reader
206
+ function noop() { }
207
+ /** Runs per entity of a collection, hence the set and the absence of intermediates. */
208
+ function fit(entity, allowed) {
209
+ const output = {};
210
+ // the entity's own keys, so that what is answered keeps the order it was built in
211
+ for (const key of Object.keys(entity))
212
+ if (allowed.has(key))
213
+ output[key] = entity[key];
214
+ return output;
215
+ }
216
+ //# sourceMappingURL=operation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation.js","sourceRoot":"","sources":["../source/operation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { Connector } from './connector.ts';
2
+ import type { Atom } from './types/atomicity.ts';
3
+ import type { Storage } from './types/storages.ts';
4
+ import type { Destination, Row } from './types/outbox.ts';
5
+ import type { Event } from './types/state.ts';
6
+ export interface Options {
7
+ interval?: number;
8
+ batch?: number;
9
+ gap?: number;
10
+ }
11
+ /**
12
+ * Owns the intent to publish. A row is built before the write so that the storage can commit
13
+ * it in the same transaction as the entity; publication then happens off the operation's path,
14
+ * and anything that fails to publish is recovered from the row.
15
+ *
16
+ * The mechanism is a safety net: in a healthy system the row is written, published within
17
+ * milliseconds by the same process, and marked published on that process's next tick.
18
+ *
19
+ * A storage that cannot commit a row atomically has no outbox, and this degrades to the
20
+ * inline emission it replaces.
21
+ */
22
+ export declare class Outbox extends Connector {
23
+ #private;
24
+ constructor(destinations: Destination[], storage: Storage | undefined, atom: Atom, options?: Options);
25
+ /** whether the storage can commit a row atomically with the entity */
26
+ get durable(): boolean;
27
+ /**
28
+ * An assignment's images are the write's own, so it hands over an event with neither, and
29
+ * the storage fills them in.
30
+ */
31
+ row(event: Partial<Event>): Row;
32
+ /**
33
+ * Hands a committed row over. Awaited by the caller only on the legacy path — with an
34
+ * outbox this returns at once and the broker leaves the operation's path.
35
+ */
36
+ publish(row: Row): Promise<void> | void;
37
+ protected open(): Promise<void>;
38
+ protected close(): Promise<void>;
39
+ }
40
+ /**
41
+ * Constant, never configuration: rows carry their lane, so lowering this would leave rows in
42
+ * lanes nobody reads any more. It is also the ceiling on replicas of one component, and a
43
+ * power of two so that the common replica counts divide evenly.
44
+ */
45
+ export declare const LANES = 128;