@effect-app/infra 3.9.0 → 4.0.0-beta.0

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 (231) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/_check.sh +3 -0
  3. package/dist/CUPS.d.ts +22 -12
  4. package/dist/CUPS.d.ts.map +1 -1
  5. package/dist/CUPS.js +28 -29
  6. package/dist/Emailer/Sendgrid.js +13 -12
  7. package/dist/Emailer/service.d.ts +3 -13
  8. package/dist/Emailer/service.d.ts.map +1 -1
  9. package/dist/Emailer/service.js +3 -3
  10. package/dist/MainFiberSet.d.ts +18 -41
  11. package/dist/MainFiberSet.d.ts.map +1 -1
  12. package/dist/MainFiberSet.js +10 -10
  13. package/dist/Model/Repository/ext.d.ts.map +1 -1
  14. package/dist/Model/Repository/ext.js +13 -10
  15. package/dist/Model/Repository/internal/internal.d.ts +5 -5
  16. package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
  17. package/dist/Model/Repository/internal/internal.js +52 -42
  18. package/dist/Model/Repository/legacy.d.ts +9 -9
  19. package/dist/Model/Repository/legacy.d.ts.map +1 -1
  20. package/dist/Model/Repository/makeRepo.d.ts +4 -4
  21. package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
  22. package/dist/Model/Repository/makeRepo.js +1 -1
  23. package/dist/Model/Repository/service.d.ts +11 -11
  24. package/dist/Model/Repository/service.d.ts.map +1 -1
  25. package/dist/Model/Repository/validation.d.ts +17 -47
  26. package/dist/Model/Repository/validation.d.ts.map +1 -1
  27. package/dist/Model/Repository/validation.js +2 -2
  28. package/dist/Model/query/dsl.d.ts +22 -22
  29. package/dist/Model/query/dsl.d.ts.map +1 -1
  30. package/dist/Model/query/dsl.js +1 -1
  31. package/dist/Model/query/new-kid-interpreter.d.ts +1 -1
  32. package/dist/Model/query/new-kid-interpreter.js +7 -7
  33. package/dist/Operations.d.ts +22 -63
  34. package/dist/Operations.d.ts.map +1 -1
  35. package/dist/Operations.js +14 -14
  36. package/dist/OperationsRepo.d.ts +23 -7
  37. package/dist/OperationsRepo.d.ts.map +1 -1
  38. package/dist/OperationsRepo.js +4 -5
  39. package/dist/QueueMaker/SQLQueue.d.ts +6 -8
  40. package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
  41. package/dist/QueueMaker/SQLQueue.js +20 -24
  42. package/dist/QueueMaker/errors.js +1 -1
  43. package/dist/QueueMaker/memQueue.d.ts +2 -5
  44. package/dist/QueueMaker/memQueue.d.ts.map +1 -1
  45. package/dist/QueueMaker/memQueue.js +22 -26
  46. package/dist/QueueMaker/sbqueue.d.ts +2 -5
  47. package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
  48. package/dist/QueueMaker/sbqueue.js +24 -28
  49. package/dist/RequestContext.d.ts +28 -41
  50. package/dist/RequestContext.d.ts.map +1 -1
  51. package/dist/RequestContext.js +4 -4
  52. package/dist/RequestFiberSet.d.ts +23 -50
  53. package/dist/RequestFiberSet.d.ts.map +1 -1
  54. package/dist/RequestFiberSet.js +14 -14
  55. package/dist/Store/ContextMapContainer.d.ts +4 -4
  56. package/dist/Store/ContextMapContainer.d.ts.map +1 -1
  57. package/dist/Store/ContextMapContainer.js +5 -5
  58. package/dist/Store/Cosmos.d.ts.map +1 -1
  59. package/dist/Store/Cosmos.js +21 -28
  60. package/dist/Store/Disk.d.ts.map +1 -1
  61. package/dist/Store/Disk.js +12 -16
  62. package/dist/Store/Memory.d.ts +2 -2
  63. package/dist/Store/Memory.d.ts.map +1 -1
  64. package/dist/Store/Memory.js +25 -33
  65. package/dist/Store/index.js +2 -2
  66. package/dist/Store/service.d.ts +9 -34
  67. package/dist/Store/service.d.ts.map +1 -1
  68. package/dist/Store/service.js +4 -4
  69. package/dist/Store/utils.d.ts.map +1 -1
  70. package/dist/Store/utils.js +10 -2
  71. package/dist/adapters/SQL/Model.d.ts +106 -162
  72. package/dist/adapters/SQL/Model.d.ts.map +1 -1
  73. package/dist/adapters/SQL/Model.js +92 -130
  74. package/dist/adapters/ServiceBus.d.ts +13 -44
  75. package/dist/adapters/ServiceBus.d.ts.map +1 -1
  76. package/dist/adapters/ServiceBus.js +13 -15
  77. package/dist/adapters/cosmos-client.d.ts +7 -3
  78. package/dist/adapters/cosmos-client.d.ts.map +1 -1
  79. package/dist/adapters/cosmos-client.js +5 -4
  80. package/dist/adapters/logger.d.ts +1 -1
  81. package/dist/adapters/logger.d.ts.map +1 -1
  82. package/dist/adapters/memQueue.d.ts +8 -21
  83. package/dist/adapters/memQueue.d.ts.map +1 -1
  84. package/dist/adapters/memQueue.js +4 -4
  85. package/dist/adapters/mongo-client.d.ts +6 -6
  86. package/dist/adapters/mongo-client.d.ts.map +1 -1
  87. package/dist/adapters/mongo-client.js +5 -4
  88. package/dist/adapters/redis-client.d.ts +14 -4
  89. package/dist/adapters/redis-client.d.ts.map +1 -1
  90. package/dist/adapters/redis-client.js +19 -18
  91. package/dist/api/ContextProvider.d.ts +10 -15
  92. package/dist/api/ContextProvider.d.ts.map +1 -1
  93. package/dist/api/ContextProvider.js +8 -8
  94. package/dist/api/codec.d.ts +1 -1
  95. package/dist/api/codec.d.ts.map +1 -1
  96. package/dist/api/codec.js +1 -1
  97. package/dist/api/internal/RequestContextMiddleware.d.ts +1 -1
  98. package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
  99. package/dist/api/internal/auth.d.ts +3 -3
  100. package/dist/api/internal/auth.d.ts.map +1 -1
  101. package/dist/api/internal/auth.js +8 -8
  102. package/dist/api/internal/events.d.ts +2 -2
  103. package/dist/api/internal/events.d.ts.map +1 -1
  104. package/dist/api/internal/events.js +9 -9
  105. package/dist/api/internal/health.d.ts +1 -1
  106. package/dist/api/internal/health.d.ts.map +1 -1
  107. package/dist/api/internal/health.js +2 -2
  108. package/dist/api/layerUtils.d.ts +14 -14
  109. package/dist/api/layerUtils.d.ts.map +1 -1
  110. package/dist/api/layerUtils.js +5 -5
  111. package/dist/api/middlewares.d.ts +0 -75
  112. package/dist/api/middlewares.d.ts.map +1 -1
  113. package/dist/api/middlewares.js +6 -51
  114. package/dist/api/reportError.js +4 -4
  115. package/dist/api/routing/middleware/RouterMiddleware.d.ts +4 -4
  116. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
  117. package/dist/api/routing/middleware/middleware.d.ts +6 -7
  118. package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
  119. package/dist/api/routing/middleware/middleware.js +9 -13
  120. package/dist/api/routing/schema/jwt.d.ts +1 -1
  121. package/dist/api/routing/schema/jwt.d.ts.map +1 -1
  122. package/dist/api/routing/schema/jwt.js +5 -4
  123. package/dist/api/routing/utils.d.ts +2 -2
  124. package/dist/api/routing/utils.d.ts.map +1 -1
  125. package/dist/api/routing/utils.js +10 -8
  126. package/dist/api/routing.d.ts +39 -37
  127. package/dist/api/routing.d.ts.map +1 -1
  128. package/dist/api/routing.js +17 -21
  129. package/dist/api/setupRequest.d.ts +4 -6
  130. package/dist/api/setupRequest.d.ts.map +1 -1
  131. package/dist/api/setupRequest.js +10 -9
  132. package/dist/arbs.d.ts +3 -3
  133. package/dist/arbs.d.ts.map +1 -1
  134. package/dist/arbs.js +2 -2
  135. package/dist/errorReporter.d.ts +1 -1
  136. package/dist/errorReporter.d.ts.map +1 -1
  137. package/dist/errorReporter.js +12 -12
  138. package/dist/fileUtil.d.ts +6 -6
  139. package/dist/fileUtil.d.ts.map +1 -1
  140. package/dist/logger/jsonLogger.d.ts.map +1 -1
  141. package/dist/logger/jsonLogger.js +19 -18
  142. package/dist/logger/logFmtLogger.d.ts.map +1 -1
  143. package/dist/logger/logFmtLogger.js +11 -13
  144. package/dist/logger/shared.d.ts +2 -2
  145. package/dist/logger/shared.d.ts.map +1 -1
  146. package/dist/logger/shared.js +7 -9
  147. package/dist/logger.d.ts +1 -1
  148. package/dist/logger.d.ts.map +1 -1
  149. package/dist/rateLimit.d.ts +2 -2
  150. package/dist/rateLimit.d.ts.map +1 -1
  151. package/dist/rateLimit.js +5 -5
  152. package/dist/test.d.ts +2 -2
  153. package/dist/test.d.ts.map +1 -1
  154. package/dist/test.js +6 -24
  155. package/package.json +24 -27
  156. package/src/CUPS.ts +15 -14
  157. package/src/Emailer/Sendgrid.ts +15 -13
  158. package/src/Emailer/service.ts +3 -3
  159. package/src/MainFiberSet.ts +16 -12
  160. package/src/Model/Repository/ext.ts +18 -16
  161. package/src/Model/Repository/internal/internal.ts +80 -69
  162. package/src/Model/Repository/legacy.ts +9 -9
  163. package/src/Model/Repository/makeRepo.ts +5 -5
  164. package/src/Model/Repository/service.ts +12 -12
  165. package/src/Model/Repository/validation.ts +1 -1
  166. package/src/Model/query/dsl.ts +13 -13
  167. package/src/Model/query/new-kid-interpreter.ts +8 -8
  168. package/src/Operations.ts +17 -14
  169. package/src/OperationsRepo.ts +3 -4
  170. package/src/QueueMaker/SQLQueue.ts +86 -89
  171. package/src/QueueMaker/errors.ts +1 -1
  172. package/src/QueueMaker/memQueue.ts +90 -91
  173. package/src/QueueMaker/sbqueue.ts +90 -92
  174. package/src/RequestContext.ts +3 -3
  175. package/src/RequestFiberSet.ts +17 -15
  176. package/src/Store/ContextMapContainer.ts +4 -4
  177. package/src/Store/Cosmos.ts +20 -27
  178. package/src/Store/Disk.ts +13 -17
  179. package/src/Store/Memory.ts +28 -34
  180. package/src/Store/index.ts +1 -1
  181. package/src/Store/service.ts +4 -4
  182. package/src/Store/utils.ts +9 -5
  183. package/src/adapters/SQL/Model.ts +255 -268
  184. package/src/adapters/ServiceBus.ts +17 -20
  185. package/src/adapters/cosmos-client.ts +5 -5
  186. package/src/adapters/memQueue.ts +3 -3
  187. package/src/adapters/mongo-client.ts +5 -5
  188. package/src/adapters/redis-client.ts +25 -19
  189. package/src/api/ContextProvider.ts +24 -34
  190. package/src/api/codec.ts +1 -1
  191. package/src/api/internal/auth.ts +11 -13
  192. package/src/api/internal/events.ts +11 -11
  193. package/src/api/internal/health.ts +1 -1
  194. package/src/api/layerUtils.ts +20 -20
  195. package/src/api/middlewares.ts +0 -97
  196. package/src/api/reportError.ts +3 -3
  197. package/src/api/routing/middleware/RouterMiddleware.ts +5 -6
  198. package/src/api/routing/middleware/middleware.ts +13 -25
  199. package/src/api/routing/schema/jwt.ts +9 -7
  200. package/src/api/routing/utils.ts +12 -10
  201. package/src/api/routing.ts +77 -79
  202. package/src/api/setupRequest.ts +9 -8
  203. package/src/arbs.ts +3 -3
  204. package/src/errorReporter.ts +12 -12
  205. package/src/logger/jsonLogger.ts +18 -17
  206. package/src/logger/logFmtLogger.ts +10 -12
  207. package/src/logger/shared.ts +6 -8
  208. package/src/rateLimit.ts +7 -7
  209. package/src/test.ts +7 -29
  210. package/test/contextProvider.test.ts +77 -70
  211. package/test/controller.test.ts +51 -39
  212. package/test/dist/contextProvider.test.d.ts.map +1 -1
  213. package/test/dist/controller.test.d.ts.map +1 -1
  214. package/test/dist/fixtures.d.ts +33 -81
  215. package/test/dist/fixtures.d.ts.map +1 -1
  216. package/test/dist/fixtures.js +9 -8
  217. package/test/dist/query.test.d.ts.map +1 -1
  218. package/test/dist/rawQuery.test.d.ts.map +1 -1
  219. package/test/dist/requires.test.d.ts.map +1 -1
  220. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  221. package/test/fixtures.ts +9 -7
  222. package/test/query.test.ts +49 -41
  223. package/test/rawQuery.test.ts +44 -40
  224. package/test/requires.test.ts +40 -31
  225. package/test/rpc-multi-middleware.test.ts +13 -14
  226. package/test/validateSample.test.ts +2 -2
  227. package/tsconfig.json +1 -25
  228. package/dist/api/internal/middlewares.d.ts +0 -15
  229. package/dist/api/internal/middlewares.d.ts.map +0 -1
  230. package/dist/api/internal/middlewares.js +0 -168
  231. package/src/api/internal/middlewares.ts +0 -279
@@ -1,10 +1,12 @@
1
1
  import { Cause, Tracer } from "effect"
2
2
  import { Effect, Fiber, flow, S } from "effect-app"
3
+ import * as Q from "effect/Queue"
3
4
  import { pretty } from "effect-app/utils"
4
5
  import { MemQueue } from "../adapters/memQueue.js"
5
6
  import { getRequestContext, setupRequestContextWithCustomSpan } from "../api/setupRequest.js"
6
7
  import { InfraLogger } from "../logger.js"
7
8
  import { reportNonInterruptedFailure, reportNonInterruptedFailureCause } from "./errors.js"
9
+ import type { NonEmptyReadonlyArray } from "effect-app"
8
10
  import { type QueueBase, QueueMeta } from "./service.js"
9
11
 
10
12
  export function makeMemQueue<
@@ -15,8 +17,8 @@ export function makeMemQueue<
15
17
  >(
16
18
  queueName: string,
17
19
  queueDrainName: string,
18
- schema: S.Schema<Evt, EvtE>,
19
- drainSchema: S.Schema<DrainEvt, DrainEvtE>
20
+ schema: S.Codec<Evt, EvtE>,
21
+ drainSchema: S.Codec<DrainEvt, DrainEvtE>
20
22
  ) {
21
23
  return Effect.gen(function*() {
22
24
  const mem = yield* MemQueue
@@ -25,108 +27,105 @@ export function makeMemQueue<
25
27
 
26
28
  const wireSchema = S.Struct({ body: schema, meta: QueueMeta })
27
29
  const drainW = S.Struct({ body: drainSchema, meta: QueueMeta })
28
- const parseDrain = flow(S.decodeUnknown(drainW), Effect.orDie)
30
+ const parseDrain = flow(S.decodeUnknownEffect(drainW), Effect.orDie)
29
31
 
30
- return {
31
- publish: (...messages) =>
32
- Effect
33
- .gen(function*() {
34
- const requestContext = yield* getRequestContext
35
- return yield* Effect
36
- .forEach(messages, (m) =>
37
- // we JSON encode, because that is what the wire also does, and it reveals holes in e.g unknown encoders (Date->String)
38
- S.encode(wireSchema)({ body: m, meta: requestContext }).pipe(
39
- Effect.orDie,
40
- Effect
41
- .andThen(JSON.stringify),
42
- // .tap((msg) => info("Publishing Mem Message: " + utils.inspect(msg)))
43
- Effect.flatMap((_) => q.offer(_))
44
- ), { discard: true })
45
- })
32
+ const queue = {
33
+ publish: (...messages: NonEmptyReadonlyArray<Evt>) =>
34
+ getRequestContext
46
35
  .pipe(
36
+ Effect.flatMap((requestContext) =>
37
+ Effect
38
+ .forEach(messages, (m) =>
39
+ // we JSON encode, because that is what the wire also does, and it reveals holes in e.g unknown encoders (Date->String)
40
+ S.encodeEffect(wireSchema)({ body: m, meta: requestContext }).pipe(
41
+ Effect.orDie,
42
+ Effect
43
+ .map(JSON.stringify),
44
+ // .tap((msg) => info("Publishing Mem Message: " + utils.inspect(msg)))
45
+ Effect.flatMap((_) => Q.offer(q, _))
46
+ ), { discard: true })
47
+ ),
47
48
  Effect.withSpan("queue.publish: " + queueName, {
48
- captureStackTrace: false,
49
49
  kind: "producer",
50
50
  attributes: { "message_tags": messages.map((_) => _._tag) }
51
- })
51
+ }, { captureStackTrace: false })
52
52
  ),
53
53
  drain: <DrainE, DrainR>(
54
54
  handleEvent: (ks: DrainEvt) => Effect.Effect<void, DrainE, DrainR>,
55
55
  sessionId?: string
56
- ) =>
57
- Effect.gen(function*() {
58
- const silenceAndReportError = reportNonInterruptedFailure({ name: "MemQueue.drain." + queueDrainName })
59
- const reportError = reportNonInterruptedFailureCause({ name: "MemQueue.drain." + queueDrainName })
60
- const processMessage = (msg: string) =>
61
- // we JSON parse, because that is what the wire also does, and it reveals holes in e.g unknown encoders (Date->String)
62
- Effect
63
- .sync(() => JSON.parse(msg))
64
- .pipe(
65
- Effect.flatMap(parseDrain),
66
- Effect.orDie,
67
- Effect
68
- .flatMap(({ body, meta }) => {
69
- let effect = InfraLogger
70
- .logDebug(`[${queueDrainName}] Processing incoming message`)
71
- .pipe(
72
- Effect.annotateLogs({ body: pretty(body), meta: pretty(meta) }),
73
- Effect.zipRight(handleEvent(body)),
74
- silenceAndReportError,
75
- (_) =>
76
- setupRequestContextWithCustomSpan(
77
- _,
78
- meta,
79
- `queue.drain: ${queueDrainName}.${body._tag}`,
80
- {
81
- captureStackTrace: false,
82
- kind: "consumer",
83
- attributes: {
84
- "queue.name": queueDrainName,
85
- "queue.sessionId": sessionId,
86
- "queue.input": body
87
- }
88
- }
89
- )
90
- )
91
- if (meta.span) {
92
- effect = Effect.withParentSpan(effect, Tracer.externalSpan(meta.span))
93
- }
94
- return effect
95
- })
96
- )
97
- return yield* qDrain
98
- .take
56
+ ) => {
57
+ const silenceAndReportError = reportNonInterruptedFailure({ name: "MemQueue.drain." + queueDrainName })
58
+ const reportError = reportNonInterruptedFailureCause({ name: "MemQueue.drain." + queueDrainName })
59
+ const processMessage = (msg: string) =>
60
+ // we JSON parse, because that is what the wire also does, and it reveals holes in e.g unknown encoders (Date->String)
61
+ Effect
62
+ .sync(() => JSON.parse(msg))
99
63
  .pipe(
64
+ Effect.flatMap(parseDrain),
65
+ Effect.orDie,
100
66
  Effect
101
- .flatMap((x) =>
102
- processMessage(x).pipe(
103
- Effect.uninterruptible,
104
- Effect.fork,
105
- Effect.flatMap(Fiber.join),
106
- // normally a failed item would be returned to the queue and retried up to X times.
107
- Effect.flatMap((_) =>
108
- _._tag === "Failure" && !Cause.isInterruptedOnly(_.cause)
109
- ? qDrain.offer(x).pipe(
110
- // TODO: retry count tracking and max retries.
111
- Effect.delay("5 seconds"),
112
- Effect.tapErrorCause(reportError),
113
- Effect.forkDaemon
67
+ .flatMap(({ body, meta }) => {
68
+ let effect = InfraLogger
69
+ .logDebug(`[${queueDrainName}] Processing incoming message`)
70
+ .pipe(
71
+ Effect.annotateLogs({ body: pretty(body), meta: pretty(meta) }),
72
+ Effect.andThen(handleEvent(body)),
73
+ silenceAndReportError,
74
+ (_) =>
75
+ setupRequestContextWithCustomSpan(
76
+ _,
77
+ meta,
78
+ `queue.drain: ${queueDrainName}.${body._tag}`,
79
+ {
80
+ captureStackTrace: false,
81
+ kind: "consumer",
82
+ attributes: {
83
+ "queue.name": queueDrainName,
84
+ "queue.sessionId": sessionId,
85
+ "queue.input": body
86
+ }
87
+ }
114
88
  )
115
- : Effect.void
116
89
  )
117
- )
118
- ),
119
- silenceAndReportError,
120
- Effect.withSpan(`queue.drain: ${queueDrainName}`, {
121
- attributes: {
122
- "queue.type": "mem",
123
- "queue.name": queueDrainName,
124
- "queue.sessionId": sessionId
125
- }
126
- }),
127
- Effect.forever
90
+ if (meta.span) {
91
+ effect = Effect.withParentSpan(effect, Tracer.externalSpan(meta.span))
92
+ }
93
+ return effect
94
+ })
128
95
  )
129
- })
130
- } satisfies QueueBase<Evt, DrainEvt>
96
+ return Q.take(qDrain)
97
+ .pipe(
98
+ Effect
99
+ .flatMap((x) =>
100
+ processMessage(x).pipe(
101
+ Effect.uninterruptible,
102
+ Effect.forkChild,
103
+ Effect.flatMap(Fiber.join),
104
+ // normally a failed item would be returned to the queue and retried up to X times.
105
+ Effect.flatMap((_) =>
106
+ _._tag === "Failure" && !Cause.hasInterruptsOnly(_.cause)
107
+ ? Q.offer(qDrain, x).pipe(
108
+ // TODO: retry count tracking and max retries.
109
+ Effect.delay("5 seconds"),
110
+ Effect.tapCause(reportError),
111
+ Effect.forkDetach
112
+ )
113
+ : Effect.void
114
+ )
115
+ )
116
+ ),
117
+ silenceAndReportError,
118
+ Effect.withSpan(`queue.drain: ${queueDrainName}`, {
119
+ attributes: {
120
+ "queue.type": "mem",
121
+ "queue.name": queueDrainName,
122
+ "queue.sessionId": sessionId
123
+ }
124
+ }),
125
+ Effect.forever
126
+ )
127
+ }
128
+ }
129
+ return queue as QueueBase<Evt, DrainEvt>
131
130
  })
132
131
  }
@@ -6,6 +6,7 @@ import { Receiver, Sender } from "../adapters/ServiceBus.js"
6
6
  import { getRequestContext, setupRequestContextWithCustomSpan } from "../api/setupRequest.js"
7
7
  import { InfraLogger } from "../logger.js"
8
8
  import { reportNonInterruptedFailure, reportNonInterruptedFailureCause, reportQueueError } from "./errors.js"
9
+ import type { NonEmptyReadonlyArray } from "effect-app"
9
10
  import { type QueueBase, QueueMeta } from "./service.js"
10
11
 
11
12
  export function makeServiceBusQueue<
@@ -14,15 +15,15 @@ export function makeServiceBusQueue<
14
15
  EvtE,
15
16
  DrainEvtE
16
17
  >(
17
- schema: S.Schema<Evt, EvtE>,
18
- drainSchema: S.Schema<DrainEvt, DrainEvtE>
18
+ schema: S.Codec<Evt, EvtE>,
19
+ drainSchema: S.Codec<DrainEvt, DrainEvtE>
19
20
  ) {
20
21
  const wireSchema = S.Struct({
21
22
  body: schema,
22
23
  meta: QueueMeta
23
24
  })
24
25
  const drainW = S.Struct({ body: drainSchema, meta: QueueMeta })
25
- const parseDrain = flow(S.decodeUnknown(drainW), Effect.orDie)
26
+ const parseDrain = flow(S.decodeUnknownEffect(drainW), Effect.orDie)
26
27
 
27
28
  return Effect.gen(function*() {
28
29
  const sender = yield* Sender
@@ -34,103 +35,100 @@ export function makeServiceBusQueue<
34
35
  // This will make sure that the host receives the error (MainFiberSet.join), who will then interrupt everything and commence a shutdown and restart of app
35
36
  // const deferred = yield* Deferred.make<never, ServiceBusError | Error>()
36
37
 
37
- return {
38
+ const queue = {
38
39
  drain: <DrainE, DrainR>(
39
40
  handleEvent: (ks: DrainEvt) => Effect.Effect<void, DrainE, DrainR>,
40
41
  sessionId?: string
41
- ) =>
42
- Effect
43
- .gen(function*() {
44
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
- function processMessage(messageBody: any) {
46
- return Effect
47
- .sync(() => JSON.parse(messageBody))
48
- .pipe(
49
- Effect.flatMap((x) => parseDrain(x)),
50
- Effect.orDie,
51
- Effect
52
- .flatMap(({ body, meta }) => {
53
- let effect = InfraLogger
54
- .logDebug(`[${receiver.name}] Processing incoming message`)
55
- .pipe(
56
- Effect.annotateLogs({
57
- body: pretty(body),
58
- meta: pretty(meta)
59
- }),
60
- Effect.zipRight(handleEvent(body)),
61
- Effect.orDie
42
+ ) => {
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ function processMessage(messageBody: any) {
45
+ return Effect
46
+ .sync(() => JSON.parse(messageBody))
47
+ .pipe(
48
+ Effect.flatMap((x) => parseDrain(x)),
49
+ Effect.orDie,
50
+ Effect
51
+ .flatMap(({ body, meta }) => {
52
+ let effect = InfraLogger
53
+ .logDebug(`[${receiver.name}] Processing incoming message`)
54
+ .pipe(
55
+ Effect.annotateLogs({
56
+ body: pretty(body),
57
+ meta: pretty(meta)
58
+ }),
59
+ Effect.andThen(handleEvent(body)),
60
+ Effect.orDie
61
+ )
62
+ // we silenceAndReportError here, so that the error is reported, and moves into the Exit.
63
+ .pipe(
64
+ silenceAndReportError,
65
+ (_) =>
66
+ setupRequestContextWithCustomSpan(
67
+ _,
68
+ meta,
69
+ `queue.drain: ${receiver.name}${sessionId ? `#${sessionId}` : ""}.${body._tag}`,
70
+ {
71
+ captureStackTrace: false,
72
+ kind: "consumer",
73
+ attributes: {
74
+ "queue.name": receiver.name,
75
+ "queue.sessionId": sessionId,
76
+ "queue.input": body
77
+ }
78
+ }
62
79
  )
63
- // we silenceAndReportError here, so that the error is reported, and moves into the Exit.
64
- .pipe(
65
- silenceAndReportError,
66
- (_) =>
67
- setupRequestContextWithCustomSpan(
68
- _,
69
- meta,
70
- `queue.drain: ${receiver.name}${sessionId ? `#${sessionId}` : ""}.${body._tag}`,
71
- {
72
- captureStackTrace: false,
73
- kind: "consumer",
74
- attributes: {
75
- "queue.name": receiver.name,
76
- "queue.sessionId": sessionId,
77
- "queue.input": body
78
- }
79
- }
80
- )
81
- )
82
- if (meta.span) {
83
- effect = Effect.withParentSpan(effect, Tracer.externalSpan(meta.span))
84
- }
85
- return effect
86
- }),
87
- Effect
88
- // we reportError here, so that we report the error only, and keep flowing
89
- .tapErrorCause(reportError),
90
- // we still need to flatten the Exit.
91
- Effect.flatMap((_) => _)
92
- )
93
- }
80
+ )
81
+ if (meta.span) {
82
+ effect = Effect.withParentSpan(effect, Tracer.externalSpan(meta.span))
83
+ }
84
+ return effect
85
+ }),
86
+ Effect
87
+ // we reportError here, so that we report the error only, and keep flowing
88
+ .tapCause(reportError),
89
+ // we still need to flatten the Exit.
90
+ Effect.flatMap((_) => _)
91
+ )
92
+ }
94
93
 
95
- return yield* receiver
96
- .subscribe({
97
- processMessage: (x) => processMessage(x.body).pipe(Effect.uninterruptible),
98
- processError: (err) => reportQueueError(Cause.fail(err.error))
99
- // Deferred.completeWith(
100
- // deferred,
101
- // reportFatalQueueError(Cause.fail(err.error))
102
- // .pipe(Effect.andThen(Effect.fail(err.error)))
103
- // )
104
- }, sessionId)
105
- })
94
+ return receiver
95
+ .subscribe({
96
+ processMessage: (x) => processMessage(x.body).pipe(Effect.uninterruptible),
97
+ processError: (err) => reportQueueError(Cause.fail(err.error))
98
+ // Deferred.completeWith(
99
+ // deferred,
100
+ // reportFatalQueueError(Cause.fail(err.error))
101
+ // .pipe(Effect.andThen(Effect.fail(err.error)))
102
+ // )
103
+ }, sessionId)
106
104
  // .pipe(Effect.andThen(Deferred.await(deferred).pipe(Effect.orDie))),
107
105
  .pipe(
108
106
  Effect.andThen(Effect.never)
109
- ),
107
+ )
108
+ },
110
109
 
111
- publish: (...messages) =>
112
- Effect
113
- .gen(function*() {
114
- const requestContext = yield* getRequestContext
115
- return yield* sender.sendMessages(
116
- messages.map((m) => ({
117
- body: JSON.stringify(
118
- S.encodeSync(wireSchema)({
119
- body: m,
120
- meta: requestContext
121
- })
122
- ),
123
- messageId: m.id, /* correllationid: requestId */
124
- contentType: "application/json",
125
- sessionId: "sessionId" in m ? m.sessionId as string : undefined as unknown as string // TODO: optional
126
- }))
127
- )
128
- })
129
- .pipe(Effect.withSpan("queue.publish: " + sender.name, {
130
- captureStackTrace: false,
131
- kind: "producer",
132
- attributes: { "message_tags": messages.map((_) => _._tag) }
133
- }))
134
- } satisfies QueueBase<Evt, DrainEvt>
110
+ publish: (...messages: NonEmptyReadonlyArray<Evt>) =>
111
+ getRequestContext
112
+ .pipe(
113
+ Effect.flatMap((requestContext) =>
114
+ Effect.forEach(messages, (m) =>
115
+ S.encodeEffect(wireSchema)({
116
+ body: m,
117
+ meta: requestContext
118
+ }).pipe(Effect.orDie, Effect.map((encoded) => ({
119
+ body: JSON.stringify(encoded),
120
+ messageId: m.id, /* correllationid: requestId */
121
+ contentType: "application/json",
122
+ sessionId: "sessionId" in m ? m.sessionId as string : undefined as unknown as string // TODO: optional
123
+ }))))
124
+ .pipe(Effect.flatMap((msgs) => sender.sendMessages(msgs)))
125
+ ),
126
+ Effect.withSpan("queue.publish: " + sender.name, {
127
+ kind: "producer",
128
+ attributes: { "message_tags": messages.map((_) => _._tag) }
129
+ }, { captureStackTrace: false })
130
+ )
131
+ }
132
+ return queue as QueueBase<Evt, DrainEvt>
135
133
  })
136
134
  }
@@ -1,11 +1,11 @@
1
- import { Context, S } from "effect-app"
1
+ import { S, ServiceMap } from "effect-app"
2
2
  import { UserProfileId } from "effect-app/ids"
3
3
  import { NonEmptyString255 } from "effect-app/Schema"
4
4
 
5
5
  export const Locale = S.Literal("en", "de")
6
6
  export type Locale = typeof Locale.Type
7
7
 
8
- export class LocaleRef extends Context.Reference<LocaleRef>()("Locale", { defaultValue: (): Locale => "en" }) {}
8
+ export class LocaleRef extends ServiceMap.Reference("Locale", { defaultValue: (): Locale => "en" }) {}
9
9
 
10
10
  export class RequestContext extends S.ExtendedClass<
11
11
  RequestContext,
@@ -23,7 +23,7 @@ export class RequestContext extends S.ExtendedClass<
23
23
  /** @deprecated */
24
24
  userProfile: S.optional(S.Struct({ sub: UserProfileId })) //
25
25
  }) {
26
- // static Tag = Context.Tag<RequestContext>()
26
+ // static Tag = ServiceMap.Tag<RequestContext>()
27
27
 
28
28
  static toMonitoring(this: void, self: RequestContext) {
29
29
  return {
@@ -1,15 +1,15 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { Context, Effect, Fiber, FiberSet, Option, type Tracer } from "effect-app"
2
+ import { Effect, Fiber, FiberSet, Layer, ServiceMap, type Tracer } from "effect-app"
3
3
  import { reportRequestError, reportUnknownRequestError } from "./api/reportError.js"
4
4
  import { InfraLogger } from "./logger.js"
5
5
 
6
6
  const getRootParentSpan = Effect.gen(function*() {
7
7
  let span: Tracer.AnySpan | null = yield* Effect.currentSpan.pipe(
8
- Effect.catchTag("NoSuchElementException", () => Effect.succeed(null))
8
+ Effect.catchTag("NoSuchElementError", () => Effect.succeed(null))
9
9
  )
10
10
  if (!span) return span
11
- while (span._tag === "Span" && Option.isSome(span.parent)) {
12
- span = span.parent.value
11
+ while (span._tag === "Span" && span.parent !== undefined) {
12
+ span = span.parent
13
13
  }
14
14
  return span
15
15
  })
@@ -19,17 +19,17 @@ export const setRootParentSpan = <A, E, R>(self: Effect.Effect<A, E, R>) =>
19
19
 
20
20
  const make = Effect.gen(function*() {
21
21
  const set = yield* FiberSet.make<any, any>()
22
- const add = (...fibers: Fiber.RuntimeFiber<any, any>[]) =>
23
- Effect.sync(() => fibers.forEach((_) => FiberSet.unsafeAdd(set, _)))
24
- const addAll = (fibers: readonly Fiber.RuntimeFiber<any, any>[]) =>
25
- Effect.sync(() => fibers.forEach((_) => FiberSet.unsafeAdd(set, _)))
22
+ const add = (...fibers: Fiber.Fiber<any, any>[]) =>
23
+ Effect.sync(() => fibers.forEach((_) => FiberSet.addUnsafe(set, _)))
24
+ const addAll = (fibers: readonly Fiber.Fiber<any, any>[]) =>
25
+ Effect.sync(() => fibers.forEach((_) => FiberSet.addUnsafe(set, _)))
26
26
  const join = FiberSet.size(set).pipe(
27
27
  Effect.andThen((count) => InfraLogger.logInfo(`Joining ${count} current fibers on the RequestFiberSet`)),
28
28
  Effect.andThen(FiberSet.join(set))
29
29
  )
30
30
  const run = FiberSet.run(set)
31
31
  const register = <A, E, R>(self: Effect.Effect<A, E, R>) =>
32
- self.pipe(Effect.fork, Effect.tap(add), Effect.andThen(Fiber.join))
32
+ self.pipe(Effect.forkChild, Effect.tap(add), Effect.andThen(Fiber.join))
33
33
 
34
34
  // const waitUntilEmpty = Effect.gen(function*() {
35
35
  // const currentSize = yield* FiberSet.size(set)
@@ -92,12 +92,14 @@ const make = Effect.gen(function*() {
92
92
  * Whenever you fork a fiber for a Request, and you want to prevent dependent services to close prematurely on interruption,
93
93
  * like the ServiceBus Sender, you should register these fibers in this FiberSet.
94
94
  */
95
- export class RequestFiberSet extends Context.TagMakeId("RequestFiberSet", make)<RequestFiberSet>() {
96
- static readonly Live = this.toLayerScoped()
97
- static readonly register = <A, E, R>(self: Effect.Effect<A, E, R>) => this.use((_) => _.register(self))
98
- static readonly run = <A, E, R>(self: Effect.Effect<A, E, R>) => this.use((_) => _.run(self))
95
+ export class RequestFiberSet extends ServiceMap.Service<RequestFiberSet>()("RequestFiberSet", { make }) {
96
+ static readonly Live = Layer.effect(this, this.make)
97
+ static readonly register = <A, E, R>(self: Effect.Effect<A, E, R>) =>
98
+ this.asEffect().pipe(Effect.andThen((_) => _.register(self)))
99
+ static readonly run = <A, E, R>(self: Effect.Effect<A, E, R>) =>
100
+ this.asEffect().pipe(Effect.andThen((_) => _.run(self)))
99
101
  static readonly forkDaemonReport = <R, E, A>(self: Effect.Effect<A, E, R>) =>
100
- this.use((_) => _.forkDaemonReport(self))
102
+ this.asEffect().pipe(Effect.andThen((_) => _.forkDaemonReport(self)))
101
103
  static readonly forkDaemonReportUnexpected = <R, E, A>(self: Effect.Effect<A, E, R>) =>
102
- this.use((_) => _.forkDaemonReportUnexpected(self))
104
+ this.asEffect().pipe(Effect.andThen((_) => _.forkDaemonReportUnexpected(self)))
103
105
  }
@@ -1,4 +1,4 @@
1
- import { Context, Data, Effect, Layer } from "effect-app"
1
+ import { Data, Effect, Layer, ServiceMap } from "effect-app"
2
2
  import { ContextMap } from "./service.js"
3
3
 
4
4
  // TODO: we have to create a new contextmap on every request.
@@ -7,14 +7,14 @@ import { ContextMap } from "./service.js"
7
7
  // we can call another start after startup. but it would be even better if we could Die on accessing rootmap
8
8
  // we could also make the ContextMap optional, and when missing, issue a warning instead?
9
9
 
10
- export class ContextMapContainer extends Context.Reference<ContextMapContainer>()("ContextMapContainer", {
10
+ export class ContextMapContainer extends ServiceMap.Reference("ContextMapContainer", {
11
11
  defaultValue: (): ContextMap | "root" => "root"
12
12
  }) {
13
- static readonly layer = Layer.effect(this, ContextMap.make)
13
+ static readonly layer = Layer.effect(this, ContextMap.make.pipe(Effect.map(ContextMap.of)))
14
14
  }
15
15
 
16
16
  export class ContextMapNotStartedError extends Data.TaggedError("ContextMapNotStartedError") {}
17
17
 
18
- export const getContextMap = ContextMapContainer.pipe(
18
+ export const getContextMap = ContextMapContainer.asEffect().pipe(
19
19
  Effect.filterOrFail((_) => _ !== "root", () => new ContextMapNotStartedError())
20
20
  )