@effect-app/infra 3.10.0 → 4.0.0-beta.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.
- package/CHANGELOG.md +19 -0
- package/_check.sh +3 -0
- package/dist/CUPS.d.ts +22 -12
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/CUPS.js +28 -29
- package/dist/Emailer/Sendgrid.js +13 -12
- package/dist/Emailer/service.d.ts +3 -13
- package/dist/Emailer/service.d.ts.map +1 -1
- package/dist/Emailer/service.js +3 -3
- package/dist/MainFiberSet.d.ts +18 -41
- package/dist/MainFiberSet.d.ts.map +1 -1
- package/dist/MainFiberSet.js +10 -10
- package/dist/Model/Repository/ext.d.ts.map +1 -1
- package/dist/Model/Repository/ext.js +13 -10
- package/dist/Model/Repository/internal/internal.d.ts +5 -5
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +52 -42
- package/dist/Model/Repository/legacy.d.ts +9 -9
- package/dist/Model/Repository/legacy.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.d.ts +4 -4
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.js +1 -1
- package/dist/Model/Repository/service.d.ts +11 -11
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/Model/Repository/validation.d.ts +17 -47
- package/dist/Model/Repository/validation.d.ts.map +1 -1
- package/dist/Model/Repository/validation.js +2 -2
- package/dist/Model/query/dsl.d.ts +22 -22
- package/dist/Model/query/dsl.d.ts.map +1 -1
- package/dist/Model/query/dsl.js +1 -1
- package/dist/Model/query/new-kid-interpreter.d.ts +1 -1
- package/dist/Model/query/new-kid-interpreter.js +7 -7
- package/dist/Operations.d.ts +22 -63
- package/dist/Operations.d.ts.map +1 -1
- package/dist/Operations.js +14 -14
- package/dist/OperationsRepo.d.ts +23 -7
- package/dist/OperationsRepo.d.ts.map +1 -1
- package/dist/OperationsRepo.js +4 -5
- package/dist/QueueMaker/SQLQueue.d.ts +6 -8
- package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
- package/dist/QueueMaker/SQLQueue.js +20 -24
- package/dist/QueueMaker/errors.js +1 -1
- package/dist/QueueMaker/memQueue.d.ts +2 -5
- package/dist/QueueMaker/memQueue.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.js +22 -26
- package/dist/QueueMaker/sbqueue.d.ts +2 -5
- package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/QueueMaker/sbqueue.js +24 -28
- package/dist/RequestContext.d.ts +28 -41
- package/dist/RequestContext.d.ts.map +1 -1
- package/dist/RequestContext.js +4 -4
- package/dist/RequestFiberSet.d.ts +23 -50
- package/dist/RequestFiberSet.d.ts.map +1 -1
- package/dist/RequestFiberSet.js +14 -14
- package/dist/Store/ContextMapContainer.d.ts +4 -4
- package/dist/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/Store/ContextMapContainer.js +5 -5
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +21 -28
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +12 -16
- package/dist/Store/Memory.d.ts +2 -2
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +25 -33
- package/dist/Store/index.js +2 -2
- package/dist/Store/service.d.ts +9 -34
- package/dist/Store/service.d.ts.map +1 -1
- package/dist/Store/service.js +4 -4
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +10 -2
- package/dist/adapters/SQL/Model.d.ts +106 -162
- package/dist/adapters/SQL/Model.d.ts.map +1 -1
- package/dist/adapters/SQL/Model.js +92 -130
- package/dist/adapters/ServiceBus.d.ts +13 -44
- package/dist/adapters/ServiceBus.d.ts.map +1 -1
- package/dist/adapters/ServiceBus.js +13 -15
- package/dist/adapters/cosmos-client.d.ts +7 -3
- package/dist/adapters/cosmos-client.d.ts.map +1 -1
- package/dist/adapters/cosmos-client.js +5 -4
- package/dist/adapters/logger.d.ts +1 -1
- package/dist/adapters/logger.d.ts.map +1 -1
- package/dist/adapters/memQueue.d.ts +8 -21
- package/dist/adapters/memQueue.d.ts.map +1 -1
- package/dist/adapters/memQueue.js +4 -4
- package/dist/adapters/mongo-client.d.ts +6 -6
- package/dist/adapters/mongo-client.d.ts.map +1 -1
- package/dist/adapters/mongo-client.js +5 -4
- package/dist/adapters/redis-client.d.ts +14 -4
- package/dist/adapters/redis-client.d.ts.map +1 -1
- package/dist/adapters/redis-client.js +19 -18
- package/dist/api/ContextProvider.d.ts +10 -15
- package/dist/api/ContextProvider.d.ts.map +1 -1
- package/dist/api/ContextProvider.js +8 -8
- package/dist/api/codec.d.ts +1 -1
- package/dist/api/codec.d.ts.map +1 -1
- package/dist/api/codec.js +1 -1
- package/dist/api/internal/RequestContextMiddleware.d.ts +1 -1
- package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
- package/dist/api/internal/auth.d.ts +3 -3
- package/dist/api/internal/auth.d.ts.map +1 -1
- package/dist/api/internal/auth.js +8 -8
- package/dist/api/internal/events.d.ts +2 -2
- package/dist/api/internal/events.d.ts.map +1 -1
- package/dist/api/internal/events.js +9 -9
- package/dist/api/internal/health.d.ts +1 -1
- package/dist/api/internal/health.d.ts.map +1 -1
- package/dist/api/internal/health.js +2 -2
- package/dist/api/layerUtils.d.ts +14 -14
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +5 -5
- package/dist/api/middlewares.d.ts +0 -75
- package/dist/api/middlewares.d.ts.map +1 -1
- package/dist/api/middlewares.js +6 -51
- package/dist/api/reportError.js +4 -4
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +4 -4
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.d.ts +6 -7
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +9 -13
- package/dist/api/routing/schema/jwt.d.ts +1 -1
- package/dist/api/routing/schema/jwt.d.ts.map +1 -1
- package/dist/api/routing/schema/jwt.js +5 -4
- package/dist/api/routing/utils.d.ts +2 -2
- package/dist/api/routing/utils.d.ts.map +1 -1
- package/dist/api/routing/utils.js +10 -8
- package/dist/api/routing.d.ts +39 -37
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +17 -21
- package/dist/api/setupRequest.d.ts +4 -6
- package/dist/api/setupRequest.d.ts.map +1 -1
- package/dist/api/setupRequest.js +10 -9
- package/dist/arbs.d.ts +3 -3
- package/dist/arbs.d.ts.map +1 -1
- package/dist/arbs.js +2 -2
- package/dist/errorReporter.d.ts +1 -1
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +12 -12
- package/dist/fileUtil.d.ts +6 -6
- package/dist/fileUtil.d.ts.map +1 -1
- package/dist/logger/jsonLogger.d.ts.map +1 -1
- package/dist/logger/jsonLogger.js +19 -18
- package/dist/logger/logFmtLogger.d.ts.map +1 -1
- package/dist/logger/logFmtLogger.js +11 -13
- package/dist/logger/shared.d.ts +2 -2
- package/dist/logger/shared.d.ts.map +1 -1
- package/dist/logger/shared.js +7 -9
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/rateLimit.d.ts +2 -2
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +5 -5
- package/dist/test.d.ts +2 -2
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +6 -24
- package/package.json +19 -22
- package/src/CUPS.ts +15 -14
- package/src/Emailer/Sendgrid.ts +15 -13
- package/src/Emailer/service.ts +3 -3
- package/src/MainFiberSet.ts +16 -12
- package/src/Model/Repository/ext.ts +18 -16
- package/src/Model/Repository/internal/internal.ts +80 -69
- package/src/Model/Repository/legacy.ts +9 -9
- package/src/Model/Repository/makeRepo.ts +5 -5
- package/src/Model/Repository/service.ts +12 -12
- package/src/Model/Repository/validation.ts +1 -1
- package/src/Model/query/dsl.ts +13 -13
- package/src/Model/query/new-kid-interpreter.ts +8 -8
- package/src/Operations.ts +17 -14
- package/src/OperationsRepo.ts +3 -4
- package/src/QueueMaker/SQLQueue.ts +86 -89
- package/src/QueueMaker/errors.ts +1 -1
- package/src/QueueMaker/memQueue.ts +90 -91
- package/src/QueueMaker/sbqueue.ts +90 -92
- package/src/RequestContext.ts +3 -3
- package/src/RequestFiberSet.ts +17 -15
- package/src/Store/ContextMapContainer.ts +4 -4
- package/src/Store/Cosmos.ts +20 -27
- package/src/Store/Disk.ts +13 -17
- package/src/Store/Memory.ts +28 -34
- package/src/Store/index.ts +1 -1
- package/src/Store/service.ts +4 -4
- package/src/Store/utils.ts +9 -5
- package/src/adapters/SQL/Model.ts +255 -268
- package/src/adapters/ServiceBus.ts +17 -20
- package/src/adapters/cosmos-client.ts +5 -5
- package/src/adapters/memQueue.ts +3 -3
- package/src/adapters/mongo-client.ts +5 -5
- package/src/adapters/redis-client.ts +25 -19
- package/src/api/ContextProvider.ts +24 -34
- package/src/api/codec.ts +1 -1
- package/src/api/internal/auth.ts +11 -13
- package/src/api/internal/events.ts +11 -11
- package/src/api/internal/health.ts +1 -1
- package/src/api/layerUtils.ts +20 -20
- package/src/api/middlewares.ts +0 -97
- package/src/api/reportError.ts +3 -3
- package/src/api/routing/middleware/RouterMiddleware.ts +5 -6
- package/src/api/routing/middleware/middleware.ts +13 -25
- package/src/api/routing/schema/jwt.ts +9 -7
- package/src/api/routing/utils.ts +12 -10
- package/src/api/routing.ts +77 -79
- package/src/api/setupRequest.ts +9 -8
- package/src/arbs.ts +3 -3
- package/src/errorReporter.ts +12 -12
- package/src/logger/jsonLogger.ts +18 -17
- package/src/logger/logFmtLogger.ts +10 -12
- package/src/logger/shared.ts +6 -8
- package/src/rateLimit.ts +7 -7
- package/src/test.ts +7 -29
- package/test/contextProvider.test.ts +77 -70
- package/test/controller.test.ts +51 -39
- package/test/dist/contextProvider.test.d.ts.map +1 -1
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/fixtures.d.ts +33 -81
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +9 -8
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/dist/rawQuery.test.d.ts.map +1 -1
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
- package/test/fixtures.ts +9 -7
- package/test/query.test.ts +49 -41
- package/test/rawQuery.test.ts +44 -40
- package/test/requires.test.ts +40 -31
- package/test/rpc-multi-middleware.test.ts +13 -14
- package/test/validateSample.test.ts +2 -2
- package/tsconfig.json +1 -27
- package/dist/api/internal/middlewares.d.ts +0 -15
- package/dist/api/internal/middlewares.d.ts.map +0 -1
- package/dist/api/internal/middlewares.js +0 -168
- package/src/api/internal/middlewares.ts +0 -279
package/src/Model/query/dsl.ts
CHANGED
|
@@ -115,7 +115,7 @@ export class Initial<TFieldValues extends FieldValues> extends Data.TaggedClass(
|
|
|
115
115
|
constructor() {
|
|
116
116
|
super({ value: "initial" as const })
|
|
117
117
|
}
|
|
118
|
-
pipe() {
|
|
118
|
+
override pipe() {
|
|
119
119
|
// eslint-disable-next-line prefer-rest-params
|
|
120
120
|
return Pipeable.pipeArguments(this, arguments)
|
|
121
121
|
}
|
|
@@ -129,7 +129,7 @@ export class Where<TFieldValues extends FieldValues> extends Data.TaggedClass("w
|
|
|
129
129
|
}> implements QueryWhere<TFieldValues> {
|
|
130
130
|
readonly [QId]!: any
|
|
131
131
|
|
|
132
|
-
pipe() {
|
|
132
|
+
override pipe() {
|
|
133
133
|
// eslint-disable-next-line prefer-rest-params
|
|
134
134
|
return Pipeable.pipeArguments(this, arguments)
|
|
135
135
|
}
|
|
@@ -141,7 +141,7 @@ export class And<TFieldValues extends FieldValues> extends Data.TaggedClass("and
|
|
|
141
141
|
relation: RelationDirection
|
|
142
142
|
}> implements QueryWhere<TFieldValues> {
|
|
143
143
|
readonly [QId]!: any
|
|
144
|
-
pipe() {
|
|
144
|
+
override pipe() {
|
|
145
145
|
// eslint-disable-next-line prefer-rest-params
|
|
146
146
|
return Pipeable.pipeArguments(this, arguments)
|
|
147
147
|
}
|
|
@@ -153,7 +153,7 @@ export class Or<TFieldValues extends FieldValues> extends Data.TaggedClass("or")
|
|
|
153
153
|
relation: RelationDirection
|
|
154
154
|
}> implements QueryWhere<TFieldValues> {
|
|
155
155
|
readonly [QId]!: any
|
|
156
|
-
pipe() {
|
|
156
|
+
override pipe() {
|
|
157
157
|
// eslint-disable-next-line prefer-rest-params
|
|
158
158
|
return Pipeable.pipeArguments(this, arguments)
|
|
159
159
|
}
|
|
@@ -165,7 +165,7 @@ export class Page<TFieldValues extends FieldValues> extends Data.TaggedClass("pa
|
|
|
165
165
|
skip?: number | undefined
|
|
166
166
|
}> implements QueryEnd<TFieldValues> {
|
|
167
167
|
readonly [QId]!: any
|
|
168
|
-
pipe() {
|
|
168
|
+
override pipe() {
|
|
169
169
|
// eslint-disable-next-line prefer-rest-params
|
|
170
170
|
return Pipeable.pipeArguments(this, arguments)
|
|
171
171
|
}
|
|
@@ -175,7 +175,7 @@ export class One<TFieldValues extends FieldValues> extends Data.TaggedClass("one
|
|
|
175
175
|
current: Query<TFieldValues> | QueryWhere<any, TFieldValues> | QueryEnd<TFieldValues>
|
|
176
176
|
}> implements QueryEnd<TFieldValues, "one"> {
|
|
177
177
|
readonly [QId]!: any
|
|
178
|
-
pipe() {
|
|
178
|
+
override pipe() {
|
|
179
179
|
// eslint-disable-next-line prefer-rest-params
|
|
180
180
|
return Pipeable.pipeArguments(this, arguments)
|
|
181
181
|
}
|
|
@@ -185,7 +185,7 @@ export class Count<TFieldValues extends FieldValues> extends Data.TaggedClass("c
|
|
|
185
185
|
current: Query<TFieldValues> | QueryWhere<any, TFieldValues> | QueryEnd<TFieldValues>
|
|
186
186
|
}> implements QueryEnd<TFieldValues, "count"> {
|
|
187
187
|
readonly [QId]!: any
|
|
188
|
-
pipe() {
|
|
188
|
+
override pipe() {
|
|
189
189
|
// eslint-disable-next-line prefer-rest-params
|
|
190
190
|
return Pipeable.pipeArguments(this, arguments)
|
|
191
191
|
}
|
|
@@ -200,7 +200,7 @@ export class Order<TFieldValues extends FieldValues, TFieldName extends FieldPat
|
|
|
200
200
|
implements QueryEnd<TFieldValues>
|
|
201
201
|
{
|
|
202
202
|
readonly [QId]!: any
|
|
203
|
-
pipe() {
|
|
203
|
+
override pipe() {
|
|
204
204
|
// eslint-disable-next-line prefer-rest-params
|
|
205
205
|
return Pipeable.pipeArguments(this, arguments)
|
|
206
206
|
}
|
|
@@ -209,13 +209,13 @@ export class Order<TFieldValues extends FieldValues, TFieldName extends FieldPat
|
|
|
209
209
|
export class Project<A, TFieldValues extends FieldValues, R, TType extends "one" | "many" = "many">
|
|
210
210
|
extends Data.TaggedClass("project")<{
|
|
211
211
|
current: Query<TFieldValues> | QueryWhere<any, TFieldValues> | QueryEnd<TFieldValues, TType>
|
|
212
|
-
schema: S.
|
|
212
|
+
schema: S.Codec<A, TFieldValues, R>
|
|
213
213
|
mode: "collect" | "project" | "transform"
|
|
214
214
|
}>
|
|
215
215
|
implements QueryProjection<TFieldValues, A, R>
|
|
216
216
|
{
|
|
217
217
|
readonly [QId]!: any
|
|
218
|
-
pipe() {
|
|
218
|
+
override pipe() {
|
|
219
219
|
// eslint-disable-next-line prefer-rest-params
|
|
220
220
|
return Pipeable.pipeArguments(this, arguments)
|
|
221
221
|
}
|
|
@@ -307,7 +307,7 @@ export const project: {
|
|
|
307
307
|
R = never,
|
|
308
308
|
E extends boolean = ExtractExclusiveness<Q>
|
|
309
309
|
>(
|
|
310
|
-
schema: S.
|
|
310
|
+
schema: S.Codec<
|
|
311
311
|
Option.Option<A>,
|
|
312
312
|
{
|
|
313
313
|
[K in keyof I]: K extends keyof ExtractFieldValuesRefined<Q> ? I[K] : never
|
|
@@ -326,7 +326,7 @@ export const project: {
|
|
|
326
326
|
R = never,
|
|
327
327
|
E extends boolean = ExtractExclusiveness<Q>
|
|
328
328
|
>(
|
|
329
|
-
schema: S.
|
|
329
|
+
schema: S.Codec<
|
|
330
330
|
A,
|
|
331
331
|
{
|
|
332
332
|
[K in keyof I]: K extends keyof ExtractFieldValuesRefined<Q> ? I[K] : never
|
|
@@ -344,7 +344,7 @@ export const project: {
|
|
|
344
344
|
R = never,
|
|
345
345
|
E extends boolean = ExtractExclusiveness<Q>
|
|
346
346
|
>(
|
|
347
|
-
schema: S.
|
|
347
|
+
schema: S.Codec<
|
|
348
348
|
A,
|
|
349
349
|
{
|
|
350
350
|
[K in keyof I]: K extends keyof ExtractFieldValuesRefined<Q> ? I[K] : never
|
|
@@ -10,7 +10,7 @@ import { make, type Q, type QAll } from "../query/dsl.js"
|
|
|
10
10
|
|
|
11
11
|
type Result<TFieldValues extends FieldValues, A = TFieldValues, R = never> = {
|
|
12
12
|
filter: FilterResult[]
|
|
13
|
-
schema: S.
|
|
13
|
+
schema: S.Codec<A, TFieldValues, R> | undefined
|
|
14
14
|
limit: number | undefined
|
|
15
15
|
skip: number | undefined
|
|
16
16
|
order: { key: FieldPath<TFieldValues>; direction: "ASC" | "DESC" }[]
|
|
@@ -144,9 +144,9 @@ const interpret = <
|
|
|
144
144
|
return data
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
const walkTransformation = (t: S.AST.AST) => {
|
|
148
|
-
if (S.AST.
|
|
149
|
-
return walkTransformation(t.
|
|
147
|
+
const walkTransformation = (t: S.AST.AST): S.AST.AST => {
|
|
148
|
+
if (S.AST.isDeclaration(t) && t.typeParameters.length > 0) {
|
|
149
|
+
return walkTransformation(t.typeParameters[0]!)
|
|
150
150
|
}
|
|
151
151
|
return t
|
|
152
152
|
}
|
|
@@ -166,10 +166,10 @@ export const toFilter = <
|
|
|
166
166
|
// TODO: support more complex (nested) schemas?
|
|
167
167
|
if (schema) {
|
|
168
168
|
const t = walkTransformation(schema.ast)
|
|
169
|
-
if (S.AST.
|
|
169
|
+
if (S.AST.isObjects(t)) {
|
|
170
170
|
select = t.propertySignatures.map((_) => _.name as string)
|
|
171
171
|
for (const prop of t.propertySignatures) {
|
|
172
|
-
if (S.AST.
|
|
172
|
+
if (S.AST.isArrays(prop.type)) {
|
|
173
173
|
// make sure we only select when there are actually type literals in the tuple...
|
|
174
174
|
// otherwise we might be dealing with strings etc.
|
|
175
175
|
// TODO; be more strict, can't support arrays with unions that have non TypeLiteral members etc..
|
|
@@ -178,8 +178,8 @@ export const toFilter = <
|
|
|
178
178
|
subKeys: Array.flatMap(
|
|
179
179
|
prop.type.rest,
|
|
180
180
|
(x) => {
|
|
181
|
-
const t = walkTransformation(x
|
|
182
|
-
return S.AST.
|
|
181
|
+
const t = walkTransformation(x)
|
|
182
|
+
return S.AST.isObjects(t) ? t.propertySignatures.map((y) => y.name as string) : []
|
|
183
183
|
}
|
|
184
184
|
)
|
|
185
185
|
}
|
package/src/Operations.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { reportError } from "@effect-app/infra/errorReporter"
|
|
2
2
|
import { subHours } from "date-fns"
|
|
3
|
-
import { Cause,
|
|
3
|
+
import { Cause, copy, Duration, Effect, Exit, type Fiber, Layer, Option, S, Schedule, ServiceMap } from "effect-app"
|
|
4
4
|
import { annotateLogscoped } from "effect-app/Effect"
|
|
5
5
|
import { dual, pipe } from "effect-app/Function"
|
|
6
6
|
import { Operation, OperationFailure, OperationId, type OperationProgress, OperationSuccess } from "effect-app/Operations"
|
|
@@ -52,12 +52,12 @@ const make = Effect.gen(function*() {
|
|
|
52
52
|
result: Exit.isSuccess(exit)
|
|
53
53
|
? new OperationSuccess()
|
|
54
54
|
: new OperationFailure({
|
|
55
|
-
message: Cause.
|
|
55
|
+
message: Cause.hasInterruptsOnly(exit.cause)
|
|
56
56
|
? NonEmptyString2k("Interrupted")
|
|
57
|
-
: Cause.
|
|
57
|
+
: Cause.hasDies(exit.cause)
|
|
58
58
|
? NonEmptyString2k("Unknown error")
|
|
59
59
|
: Cause
|
|
60
|
-
.
|
|
60
|
+
.findErrorOption(exit.cause)
|
|
61
61
|
.pipe(
|
|
62
62
|
Option.flatMap((_) =>
|
|
63
63
|
typeof _ === "object" && _ !== null && "message" in _ && S.is(NonEmptyString2k)(_.message)
|
|
@@ -93,11 +93,11 @@ const make = Effect.gen(function*() {
|
|
|
93
93
|
(scope) =>
|
|
94
94
|
register(title)
|
|
95
95
|
.pipe(
|
|
96
|
-
Scope.
|
|
96
|
+
Scope.provide(scope),
|
|
97
97
|
Effect.flatMap((id) =>
|
|
98
98
|
reqFiberSet
|
|
99
99
|
.forkDaemonReportUnexpected(Scope.use(
|
|
100
|
-
self(id).pipe(Effect.withSpan(title, { captureStackTrace: false })),
|
|
100
|
+
self(id).pipe(Effect.withSpan(title, {}, { captureStackTrace: false })),
|
|
101
101
|
scope
|
|
102
102
|
))
|
|
103
103
|
.pipe(Effect.map((fiber): RunningOperation<A, E> => ({ fiber, id })))
|
|
@@ -105,7 +105,7 @@ const make = Effect.gen(function*() {
|
|
|
105
105
|
Effect.tap(({ id }) =>
|
|
106
106
|
Effect.interruptible(fnc(id)).pipe(
|
|
107
107
|
Effect.forkScoped,
|
|
108
|
-
Scope.
|
|
108
|
+
Scope.provide(scope)
|
|
109
109
|
)
|
|
110
110
|
)
|
|
111
111
|
)
|
|
@@ -128,12 +128,12 @@ const make = Effect.gen(function*() {
|
|
|
128
128
|
(scope) =>
|
|
129
129
|
register(title)
|
|
130
130
|
.pipe(
|
|
131
|
-
Scope.
|
|
131
|
+
Scope.provide(scope),
|
|
132
132
|
Effect
|
|
133
133
|
.flatMap((id) =>
|
|
134
134
|
reqFiberSet
|
|
135
135
|
.forkDaemonReportUnexpected(Scope.use(
|
|
136
|
-
self(id).pipe(Effect.withSpan(title, { captureStackTrace: false })),
|
|
136
|
+
self(id).pipe(Effect.withSpan(title, {}, { captureStackTrace: false })),
|
|
137
137
|
scope
|
|
138
138
|
))
|
|
139
139
|
.pipe(Effect.map((fiber): RunningOperation<A, E> => ({ fiber, id })))
|
|
@@ -158,12 +158,12 @@ const make = Effect.gen(function*() {
|
|
|
158
158
|
(scope) =>
|
|
159
159
|
register(title)
|
|
160
160
|
.pipe(
|
|
161
|
-
Scope.
|
|
161
|
+
Scope.provide(scope),
|
|
162
162
|
Effect
|
|
163
163
|
.flatMap((id) =>
|
|
164
164
|
reqFiberSet
|
|
165
165
|
.forkDaemonReportUnexpected(Scope.use(
|
|
166
|
-
self.pipe(Effect.withSpan(title, { captureStackTrace: false })),
|
|
166
|
+
self.pipe(Effect.withSpan(title, {}, { captureStackTrace: false })),
|
|
167
167
|
scope
|
|
168
168
|
))
|
|
169
169
|
.pipe(Effect.map((fiber): RunningOperation<A, E> => ({ fiber, id })))
|
|
@@ -189,7 +189,7 @@ const make = Effect.gen(function*() {
|
|
|
189
189
|
}
|
|
190
190
|
})
|
|
191
191
|
|
|
192
|
-
export class Operations extends
|
|
192
|
+
export class Operations extends ServiceMap.Opaque<Operations>()("effect-app/Operations", { make }) {
|
|
193
193
|
private static readonly CleanupLive = this
|
|
194
194
|
.use((_) =>
|
|
195
195
|
_.cleanup.pipe(
|
|
@@ -209,7 +209,10 @@ export class Operations extends Context.TagMakeId("effect-app/Operations", make)
|
|
|
209
209
|
)
|
|
210
210
|
.pipe(Layer.effectDiscard, Layer.provide(MainFiberSet.Live))
|
|
211
211
|
|
|
212
|
-
static readonly Live = this.CleanupLive.pipe(
|
|
212
|
+
static readonly Live = this.CleanupLive.pipe(
|
|
213
|
+
Layer.provideMerge(this.toLayer(this.make)),
|
|
214
|
+
Layer.provide(RequestFiberSet.Live)
|
|
215
|
+
)
|
|
213
216
|
|
|
214
217
|
static readonly forkOperation = (title: NonEmptyString2k) => <R, E, A>(self: Effect.Effect<A, E, R>) =>
|
|
215
218
|
this.use((_) => _.forkOperation(self, title))
|
|
@@ -228,5 +231,5 @@ export class Operations extends Context.TagMakeId("effect-app/Operations", make)
|
|
|
228
231
|
|
|
229
232
|
export interface RunningOperation<A, E> {
|
|
230
233
|
id: OperationId
|
|
231
|
-
fiber: Fiber.
|
|
234
|
+
fiber: Fiber.Fiber<A, E>
|
|
232
235
|
}
|
package/src/OperationsRepo.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { Effect } from "effect-app"
|
|
1
|
+
import { Effect, ServiceMap } from "effect-app"
|
|
2
2
|
import { Operation } from "effect-app/Operations"
|
|
3
3
|
import { makeRepo } from "./Model.js"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
export class OperationsRepo extends Effect.Service<OperationsRepo>()(
|
|
5
|
+
export class OperationsRepo extends ServiceMap.Service<OperationsRepo>()(
|
|
7
6
|
"OperationRepo",
|
|
8
7
|
{
|
|
9
|
-
|
|
8
|
+
make: Effect.gen(function*() {
|
|
10
9
|
return yield* makeRepo("Operation", Operation, {
|
|
11
10
|
config: {
|
|
12
11
|
allowNamespace: () => true
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { getRequestContext, setupRequestContextWithCustomSpan } from "@effect-app/infra/api/setupRequest"
|
|
2
2
|
import { reportNonInterruptedFailure } from "@effect-app/infra/QueueMaker/errors"
|
|
3
3
|
import { type QueueBase, QueueMeta } from "@effect-app/infra/QueueMaker/service"
|
|
4
|
-
import { SqlClient } from "
|
|
4
|
+
import { SqlClient } from "effect/unstable/sql"
|
|
5
5
|
import { subMinutes } from "date-fns"
|
|
6
6
|
import { Effect, Fiber, Option, S, Tracer } from "effect-app"
|
|
7
7
|
import type { NonEmptyString255 } from "effect-app/Schema"
|
|
8
8
|
import { pretty } from "effect-app/utils"
|
|
9
|
+
import type { NonEmptyReadonlyArray } from "effect-app"
|
|
9
10
|
import { SQLModel } from "../adapters/SQL.js"
|
|
10
11
|
import { InfraLogger } from "../logger.js"
|
|
11
12
|
|
|
@@ -21,8 +22,8 @@ export function makeSQLQueue<
|
|
|
21
22
|
>(
|
|
22
23
|
queueName: NonEmptyString255,
|
|
23
24
|
queueDrainName: NonEmptyString255,
|
|
24
|
-
schema: S.
|
|
25
|
-
drainSchema: S.
|
|
25
|
+
schema: S.Codec<Evt, EvtE>,
|
|
26
|
+
drainSchema: S.Codec<DrainEvt, DrainEvtE>
|
|
26
27
|
) {
|
|
27
28
|
return Effect.gen(function*() {
|
|
28
29
|
const base = {
|
|
@@ -62,7 +63,7 @@ export function makeSQLQueue<
|
|
|
62
63
|
versionColumn: "etag"
|
|
63
64
|
})
|
|
64
65
|
|
|
65
|
-
const decodeDrain = S.
|
|
66
|
+
const decodeDrain = S.decodeEffect(Drain)
|
|
66
67
|
|
|
67
68
|
const drain = Effect
|
|
68
69
|
.sync(() => subMinutes(new Date(), 15))
|
|
@@ -78,16 +79,14 @@ export function makeSQLQueue<
|
|
|
78
79
|
|
|
79
80
|
const q = {
|
|
80
81
|
offer: Effect.fnUntraced(function*(body: Evt, meta: typeof QueueMeta.Type) {
|
|
81
|
-
yield* queueRepo.insertVoid(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
})
|
|
90
|
-
)
|
|
82
|
+
yield* queueRepo.insertVoid({
|
|
83
|
+
body,
|
|
84
|
+
meta,
|
|
85
|
+
name: queueName,
|
|
86
|
+
processingAt: Option.none(),
|
|
87
|
+
finishedAt: Option.none(),
|
|
88
|
+
etag: crypto.randomUUID()
|
|
89
|
+
})
|
|
91
90
|
}),
|
|
92
91
|
take: Effect.gen(function*() {
|
|
93
92
|
while (true) {
|
|
@@ -96,7 +95,7 @@ export function makeSQLQueue<
|
|
|
96
95
|
const dec = yield* decodeDrain(first)
|
|
97
96
|
const { createdAt, updatedAt, ...rest } = dec
|
|
98
97
|
return yield* drainRepo.update(
|
|
99
|
-
|
|
98
|
+
{ ...rest, processingAt: Option.some(new Date()) } // auto in lib , etag: crypto.randomUUID()
|
|
100
99
|
)
|
|
101
100
|
}
|
|
102
101
|
if (first) return first
|
|
@@ -104,90 +103,88 @@ export function makeSQLQueue<
|
|
|
104
103
|
}
|
|
105
104
|
}),
|
|
106
105
|
finish: ({ createdAt, updatedAt, ...q }: Drain) =>
|
|
107
|
-
drainRepo.updateVoid(
|
|
106
|
+
drainRepo.updateVoid({ ...q, finishedAt: Option.some(new Date()) }) // auto in lib , etag: crypto.randomUUID()
|
|
108
107
|
}
|
|
109
|
-
|
|
110
|
-
publish: (...messages) =>
|
|
111
|
-
|
|
112
|
-
.gen(function*() {
|
|
113
|
-
const requestContext = yield* getRequestContext
|
|
114
|
-
return yield* Effect
|
|
115
|
-
.forEach(
|
|
116
|
-
messages,
|
|
117
|
-
(m) => q.offer(m, requestContext),
|
|
118
|
-
{
|
|
119
|
-
discard: true
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
})
|
|
108
|
+
const queue = {
|
|
109
|
+
publish: (...messages: NonEmptyReadonlyArray<Evt>) =>
|
|
110
|
+
getRequestContext
|
|
123
111
|
.pipe(
|
|
112
|
+
Effect.flatMap((requestContext) =>
|
|
113
|
+
Effect
|
|
114
|
+
.forEach(
|
|
115
|
+
messages,
|
|
116
|
+
(m) => q.offer(m, requestContext),
|
|
117
|
+
{
|
|
118
|
+
discard: true
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
),
|
|
124
122
|
Effect.withSpan("queue.publish: " + queueName, {
|
|
125
|
-
captureStackTrace: false,
|
|
126
123
|
kind: "producer",
|
|
127
124
|
attributes: { "message_tags": messages.map((_) => _._tag) }
|
|
128
|
-
})
|
|
125
|
+
}, { captureStackTrace: false })
|
|
129
126
|
),
|
|
130
127
|
drain: <DrainE, DrainR>(
|
|
131
128
|
handleEvent: (ks: DrainEvt) => Effect.Effect<void, DrainE, DrainR>,
|
|
132
129
|
sessionId?: string
|
|
133
|
-
) =>
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
"queue.input": body
|
|
159
|
-
}
|
|
130
|
+
) => {
|
|
131
|
+
const silenceAndReportError = reportNonInterruptedFailure({ name: "MemQueue.drain." + queueDrainName })
|
|
132
|
+
const processMessage = (msg: Drain) =>
|
|
133
|
+
Effect
|
|
134
|
+
.succeed(msg)
|
|
135
|
+
.pipe(Effect
|
|
136
|
+
.flatMap(({ body, meta }) => {
|
|
137
|
+
let effect = InfraLogger
|
|
138
|
+
.logDebug(`[${queueDrainName}] Processing incoming message`)
|
|
139
|
+
.pipe(
|
|
140
|
+
Effect.annotateLogs({ body: pretty(body), meta: pretty(meta) }),
|
|
141
|
+
Effect.andThen(handleEvent(body)),
|
|
142
|
+
silenceAndReportError,
|
|
143
|
+
(_) =>
|
|
144
|
+
setupRequestContextWithCustomSpan(
|
|
145
|
+
_,
|
|
146
|
+
meta,
|
|
147
|
+
`queue.drain: ${queueDrainName}.${body._tag}`,
|
|
148
|
+
{
|
|
149
|
+
captureStackTrace: false,
|
|
150
|
+
kind: "consumer",
|
|
151
|
+
attributes: {
|
|
152
|
+
"queue.name": queueDrainName,
|
|
153
|
+
"queue.sessionId": sessionId,
|
|
154
|
+
"queue.input": body
|
|
160
155
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return effect
|
|
167
|
-
}))
|
|
168
|
-
|
|
169
|
-
return yield* q
|
|
170
|
-
.take
|
|
171
|
-
.pipe(
|
|
172
|
-
Effect.flatMap((x) =>
|
|
173
|
-
processMessage(x).pipe(
|
|
174
|
-
Effect.uninterruptible,
|
|
175
|
-
Effect.fork,
|
|
176
|
-
Effect.flatMap(Fiber.join),
|
|
177
|
-
Effect.tap(q.finish(x))
|
|
178
|
-
)
|
|
179
|
-
),
|
|
180
|
-
silenceAndReportError,
|
|
181
|
-
Effect.withSpan(`queue.drain: ${queueDrainName}`, {
|
|
182
|
-
attributes: {
|
|
183
|
-
"queue.type": "sql",
|
|
184
|
-
"queue.name": queueDrainName,
|
|
185
|
-
"queue.sessionId": sessionId
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
if (meta.span) {
|
|
160
|
+
effect = Effect.withParentSpan(effect, Tracer.externalSpan(meta.span))
|
|
186
161
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
162
|
+
return effect
|
|
163
|
+
}))
|
|
164
|
+
|
|
165
|
+
return q
|
|
166
|
+
.take
|
|
167
|
+
.pipe(
|
|
168
|
+
Effect.flatMap((x) =>
|
|
169
|
+
processMessage(x).pipe(
|
|
170
|
+
Effect.uninterruptible,
|
|
171
|
+
Effect.forkChild,
|
|
172
|
+
Effect.flatMap(Fiber.join),
|
|
173
|
+
Effect.tap(q.finish(x))
|
|
174
|
+
)
|
|
175
|
+
),
|
|
176
|
+
silenceAndReportError,
|
|
177
|
+
Effect.withSpan(`queue.drain: ${queueDrainName}`, {
|
|
178
|
+
attributes: {
|
|
179
|
+
"queue.type": "sql",
|
|
180
|
+
"queue.name": queueDrainName,
|
|
181
|
+
"queue.sessionId": sessionId
|
|
182
|
+
}
|
|
183
|
+
}),
|
|
184
|
+
Effect.forever
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return queue as QueueBase<Evt, DrainEvt>
|
|
192
189
|
})
|
|
193
190
|
}
|
package/src/QueueMaker/errors.ts
CHANGED
|
@@ -22,7 +22,7 @@ export function reportNonInterruptedFailure(context?: Record<string, unknown>) {
|
|
|
22
22
|
|
|
23
23
|
export function reportNonInterruptedFailureCause(context?: Record<string, unknown>) {
|
|
24
24
|
return <E>(cause: Cause.Cause<E>): Effect.Effect<void> => {
|
|
25
|
-
if (Cause.
|
|
25
|
+
if (Cause.hasInterruptsOnly(cause)) {
|
|
26
26
|
return Effect.failCause(cause as Cause.Cause<never>)
|
|
27
27
|
}
|
|
28
28
|
return reportQueueError(cause, context)
|