@effect-app/infra 0.25.7 → 0.25.9
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 +17 -0
- package/_cjs/api/defaultErrorHandler.cjs +11 -16
- package/_cjs/api/defaultErrorHandler.cjs.map +1 -1
- package/_cjs/services/QueueMaker/errors.cjs +24 -12
- package/_cjs/services/QueueMaker/errors.cjs.map +1 -1
- package/_cjs/services/QueueMaker/memQueue.cjs +10 -25
- package/_cjs/services/QueueMaker/memQueue.cjs.map +1 -1
- package/_cjs/services/QueueMaker/sbqueue.cjs +19 -20
- package/_cjs/services/QueueMaker/sbqueue.cjs.map +1 -1
- package/_src/api/defaultErrorHandler.ts +12 -29
- package/_src/services/QueueMaker/errors.ts +22 -11
- package/_src/services/QueueMaker/memQueue.ts +18 -31
- package/_src/services/QueueMaker/sbqueue.ts +27 -32
- package/dist/api/defaultErrorHandler.d.ts +2 -2
- package/dist/api/defaultErrorHandler.d.ts.map +1 -1
- package/dist/api/defaultErrorHandler.js +12 -17
- package/dist/services/QueueMaker/errors.d.ts +6 -4
- package/dist/services/QueueMaker/errors.d.ts.map +1 -1
- package/dist/services/QueueMaker/errors.js +19 -9
- package/dist/services/QueueMaker/memQueue.d.ts +1 -3
- package/dist/services/QueueMaker/memQueue.d.ts.map +1 -1
- package/dist/services/QueueMaker/memQueue.js +9 -23
- package/dist/services/QueueMaker/sbqueue.d.ts +1 -2
- package/dist/services/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/services/QueueMaker/sbqueue.js +15 -18
- package/dist/services/simpledb/cosmosdb.d.ts +2 -2
- package/dist/services/simpledb/diskdb.d.ts +2 -2
- package/dist/services/simpledb/memdb.d.ts +2 -2
- package/dist/services/simpledb/mongodb.d.ts +2 -2
- package/dist/services/simpledb/redisdb.d.ts +2 -2
- package/dist/services/simpledb/simpledb.d.ts +3 -3
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @effect-app/infra
|
|
2
2
|
|
|
3
|
+
## 0.25.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8da4c8fc: Add match and improve error handling
|
|
8
|
+
- Updated dependencies [8da4c8fc]
|
|
9
|
+
- @effect-app/core@0.23.1
|
|
10
|
+
- @effect-app/infra-adapters@0.20.5
|
|
11
|
+
- @effect-app/prelude@0.21.5
|
|
12
|
+
- @effect-app/schema@0.18.4
|
|
13
|
+
|
|
14
|
+
## 0.25.8
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- ba26d2fc: Fix Queue error reporting and request semantics
|
|
19
|
+
|
|
3
20
|
## 0.25.7
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -14,29 +14,24 @@ var _reportError = require("./reportError.cjs");
|
|
|
14
14
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
15
15
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
16
16
|
function defaultBasicErrorHandler(_req, res, _requestContext, r2) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}))
|
|
17
|
+
const sendError = code => body => tsplus_module_1.sync(() => res.status(code).send(body));
|
|
18
|
+
return tsplus_module_4.untraced(() => tsplus_module_1.catchAll(tsplus_module_1.catchTag(tsplus_module_1.tapErrorCause(r2, cause => tsplus_module_2.isFailure(cause) ? (0, _reportError.logRequestError)(cause) : tsplus_module_3.unit), "ValidationError", err => sendError(400)(err.errors))
|
|
20
19
|
// final catch all; expecting never so that unhandled known errors will show up
|
|
21
20
|
, err => tsplus_module_1.flatMap(tsplus_module_1.map(tsplus_module_1.logError("Program error, compiler probably silenced, got an unsupported Error in Error Channel of Effect" + err), () => err), tsplus_module_1.die)));
|
|
22
21
|
}
|
|
23
22
|
const optimisticConcurrencySchedule = tsplus_module_5.intersect(tsplus_module_5.recurWhile(a => a._tag === "OptimisticConcurrencyException"))(tsplus_module_5.once());
|
|
24
23
|
function defaultErrorHandler(req, res, _, r2) {
|
|
25
24
|
const r3 = req.method === "PATCH" ? tsplus_module_1.retry(r2, optimisticConcurrencySchedule) : r2;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
res.status(403).send(err);
|
|
34
|
-
})), "InvalidStateError", err => tsplus_module_1.sync(() => {
|
|
35
|
-
res.status(422).send(err);
|
|
36
|
-
})), "OptimisticConcurrencyException", err => tsplus_module_1.sync(() => {
|
|
25
|
+
const sendError = code => body => tsplus_module_1.sync(() => res.status(code).send(body));
|
|
26
|
+
return tsplus_module_4.untraced(() => tsplus_module_1.catchAll(tsplus_module_1.catchTags(tsplus_module_1.tapErrorCause(r3, cause => tsplus_module_2.isFailure(cause) ? (0, _reportError.logRequestError)(cause) : tsplus_module_3.unit), {
|
|
27
|
+
"ValidationError": err => sendError(400)(err.errors),
|
|
28
|
+
"NotFoundError": sendError(404),
|
|
29
|
+
"NotLoggedInError": sendError(401),
|
|
30
|
+
"UnauthorizedError": sendError(403),
|
|
31
|
+
"InvalidStateError": sendError(422),
|
|
37
32
|
// 412 or 409.. https://stackoverflow.com/questions/19122088/which-http-status-code-to-use-to-reject-a-put-due-to-optimistic-locking-failure
|
|
38
|
-
|
|
39
|
-
})
|
|
33
|
+
"OptimisticConcurrencyException": sendError(412)
|
|
34
|
+
})
|
|
40
35
|
// final catch all; expecting never so that unhandled known errors will show up
|
|
41
36
|
, err => tsplus_module_1.flatMap(tsplus_module_1.map(tsplus_module_1.logError("Program error, compiler probably silenced, got an unsupported Error in Error Channel of Effect" + err), () => err), tsplus_module_1.die)));
|
|
42
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultErrorHandler.cjs","mappings":";;;;;;;;;;;;AAUA;AAAkD;AAAA;AAE5C,SAAUA,wBAAwB,CACtCC,IAAqB,EACrBC,GAAqB,EACrBC,eAA+B,EAC/BC,EAAoC;EAEpC,
|
|
1
|
+
{"version":3,"file":"defaultErrorHandler.cjs","mappings":";;;;;;;;;;;;AAUA;AAAkD;AAAA;AAE5C,SAAUA,wBAAwB,CACtCC,IAAqB,EACrBC,GAAqB,EACrBC,eAA+B,EAC/BC,EAAoC;EAEpC,MAAMC,SAAS,GAAIC,IAAY,IAAMC,IAAa,IAAKC,2BAAON,GAAG,CAACO,MAAM,CAACH,IAAI,CAAC,CAACI,IAAI,CAACH,IAAI,CAAC,CAAC;EAC1F,OAAOI,yBAAe,MACpBH,kFAAE,EACeI,KAAK,IAAIC,+BAAK,CAAY,GAAG,gCAAe,EAACD,KAAK,CAAC,GAAEE,oBAAY,CAAC,EACvE,iBAAiB,EAAEC,GAAG,IAAIV,SAAS,CAAC,GAAG,CAAC,CAACU,GAAG,CAACC,MAAM,CAAC;EAC9D;EAAA,EACWD,GAAU,IACnBP,qEACE,gGAAgG,GAAGO,GAAG,CACvG,EACM,MAAMA,GAAc,CAAC,sBACN,CACvB,CACJ;AACH;AAEA,MAAME,6BAA6B,6BACjCC,2BAAqCC,CAAC,IAAIA,CAAC,CAACC,IAAI,KAAK,gCAAgC,CAAC,EADlDF,sBAAe,CACmC;AAElF,SAAUG,mBAAmB,CACjCC,GAAoB,EACpBpB,GAAqB,EACrBqB,CAAiB,EACjBnB,EAAoC;EAEpC,MAAMoB,EAAE,GAAGF,GAAG,CAACG,MAAM,KAAK,OAAO,GAC7BjB,wBAAE,EAAOS,6BAA6B,CAAC,GACvCb,EAAE;EACN,MAAMC,SAAS,GAAIC,IAAY,IAAMC,IAAa,IAAKC,2BAAON,GAAG,CAACO,MAAM,CAACH,IAAI,CAAC,CAACI,IAAI,CAACH,IAAI,CAAC,CAAC;EAC1F,OAAOI,yBAAe,MACpBH,mFAAE,EACeI,KAAK,IAAIC,+BAAK,CAAY,GAAG,gCAAe,EAACD,KAAK,CAAC,GAAEE,oBAAY,CAAC,EACtE;IACT,iBAAiB,EAAEC,GAAG,IAAIV,SAAS,CAAC,GAAG,CAAC,CAACU,GAAG,CAACC,MAAM,CAAC;IACpD,eAAe,EAAEX,SAAS,CAAC,GAAG,CAAC;IAC/B,kBAAkB,EAAEA,SAAS,CAAC,GAAG,CAAC;IAClC,mBAAmB,EAAEA,SAAS,CAAC,GAAG,CAAC;IACnC,mBAAmB,EAAEA,SAAS,CAAC,GAAG,CAAC;IACnC;IACA,gCAAgC,EAAEA,SAAS,CAAC,GAAG;GAChD;EACD;EAAA,EACWU,GAAU,IACnBP,qEACE,gGAAgG,GAAGO,GAAG,CACvG,EACM,MAAMA,GAAc,CAAC,sBACN,CACvB,CACJ;AACH","names":["defaultBasicErrorHandler","_req","res","_requestContext","r2","sendError","code","body","tsplus_module_1","status","send","tsplus_module_4","cause","tsplus_module_2","tsplus_module_3","err","errors","optimisticConcurrencySchedule","tsplus_module_5","a","_tag","defaultErrorHandler","req","_","r3","method"],"sourceRoot":"","sources":["../../_src/api/defaultErrorHandler.ts"],"sourcesContent":[null]}
|
|
@@ -5,11 +5,16 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.MessageException = exports.FatalQueueException = void 0;
|
|
7
7
|
exports.forkDaemonReportQueue = forkDaemonReportQueue;
|
|
8
|
-
exports.
|
|
9
|
-
exports.
|
|
10
|
-
|
|
8
|
+
exports.reportFatalQueueError = void 0;
|
|
9
|
+
exports.reportNonInterruptedFailure = reportNonInterruptedFailure;
|
|
10
|
+
exports.reportNonInterruptedFailureCause = reportNonInterruptedFailureCause;
|
|
11
|
+
exports.reportQueueError = void 0;
|
|
12
|
+
var tsplus_module_1 = _interopRequireWildcard(require("@effect-app/core/Option"));
|
|
11
13
|
var tsplus_module_2 = _interopRequireWildcard(require("@effect-app/infra/RequestContext"));
|
|
12
|
-
var tsplus_module_3 = _interopRequireWildcard(require("@effect
|
|
14
|
+
var tsplus_module_3 = _interopRequireWildcard(require("@effect/data/Context"));
|
|
15
|
+
var tsplus_module_4 = _interopRequireWildcard(require("@effect/io/Effect"));
|
|
16
|
+
var tsplus_module_5 = _interopRequireWildcard(require("@effect/io/Exit"));
|
|
17
|
+
var tsplus_module_6 = _interopRequireWildcard(require("@effect/io/Cause"));
|
|
13
18
|
var _errorReporter = require("@effect-app/infra/errorReporter");
|
|
14
19
|
var _errors = require("@effect-app/infra/errors");
|
|
15
20
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
@@ -27,10 +32,10 @@ class FatalQueueException extends _errors.CauseException {
|
|
|
27
32
|
}
|
|
28
33
|
exports.FatalQueueException = FatalQueueException;
|
|
29
34
|
const reportQueueError_ = (0, _errorReporter.reportError)(cause => new MessageException(cause));
|
|
30
|
-
const reportQueueError = (cause, context) =>
|
|
31
|
-
requestContext,
|
|
35
|
+
const reportQueueError = (cause, context) => tsplus_module_4.flatMap(tsplus_module_4.contextWith(_ => tsplus_module_3.getOption(_, tsplus_module_2.tag)), requestContext => reportQueueError_(cause, {
|
|
36
|
+
requestContext: tsplus_module_1.getOrUndefined(requestContext),
|
|
32
37
|
...context
|
|
33
|
-
}))
|
|
38
|
+
}));
|
|
34
39
|
/**
|
|
35
40
|
* Forks the effect into a new fiber attached to the global scope. Because the
|
|
36
41
|
* new fiber is attached to the global scope, when the fiber executing the
|
|
@@ -42,13 +47,20 @@ const reportQueueError = (cause, context) => tsplus_module_1.serviceWithEffect(t
|
|
|
42
47
|
*/
|
|
43
48
|
exports.reportQueueError = reportQueueError;
|
|
44
49
|
function forkDaemonReportQueue(self) {
|
|
45
|
-
return
|
|
50
|
+
return tsplus_module_4.daemonChildren(tsplus_module_4.fork(tsplus_module_4.tapErrorCause(self, reportNonInterruptedFailureCause({}))));
|
|
46
51
|
}
|
|
47
52
|
const reportFatalQueueError = (0, _errorReporter.reportError)(cause => new FatalQueueException(cause));
|
|
48
53
|
exports.reportFatalQueueError = reportFatalQueueError;
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
function reportNonInterruptedFailure(context) {
|
|
55
|
+
const report = reportNonInterruptedFailureCause(context);
|
|
56
|
+
return inp => tsplus_module_4.flatMap(tsplus_module_4.exit(inp), result => tsplus_module_5.match(result, cause => tsplus_module_4.map(report(cause), () => result), () => tsplus_module_4.sync(() => result)));
|
|
57
|
+
}
|
|
58
|
+
function reportNonInterruptedFailureCause(context) {
|
|
59
|
+
return cause => {
|
|
60
|
+
if (tsplus_module_6.isInterrupted(cause)) {
|
|
61
|
+
return tsplus_module_4.failCause(cause);
|
|
62
|
+
}
|
|
63
|
+
return reportQueueError(cause, context);
|
|
64
|
+
};
|
|
53
65
|
}
|
|
54
66
|
//# sourceMappingURL=errors.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.cjs","mappings":"
|
|
1
|
+
{"version":3,"file":"errors.cjs","mappings":";;;;;;;;;;;;;;;;;AAAA;AACA;AAAyD;AAAA;AAGnD,MAAOA,gBAAoB,SAAQC,sBAAiB;EACxDC,YAAYC,KAAe;IACzB,KAAK,CAACA,KAAK,EAAE,SAAS,CAAC;EACzB;;AACD;AAEK,MAAOC,mBAAuB,SAAQH,sBAAiB;EAC3DC,YAAYC,KAAe;IACzB,KAAK,CAACA,KAAK,EAAE,SAAS,CAAC;EACzB;;AACD;AAED,MAAME,iBAAiB,GAAG,8BAAW,EAACF,KAAK,IAAI,IAAIH,gBAAgB,CAACG,KAAK,CAAC,CAAC;AAEpE,MAAMG,gBAAgB,GAAG,CAAIH,KAAe,EAAEI,OAA6C,KAChGC,oDAAoBC,CAAiB,IAAKC,0BAAkBD,CAAC,sBAAqB,CAAC,EACxEE,cAAc,IAAIN,iBAAiB,CAACF,KAAK,EAAE;EAAEQ,cAAc,iCAAEA,cAAc,CAAM;EAAE,GAAGJ;AAAO,CAAE,CAAC,CAAC;AAE9G;;;;;;;;;AAAA;AASM,SAAUK,qBAAqB,CAAUC,IAAqB;EAClE,2DAAOL,kCAAI,EAAeM,gCAAgC,CAAC,EAAE,CAAC,CAAC;AACjE;AAEO,MAAMC,qBAAqB,GAAG,8BAAW,EAC9CZ,KAAK,IAAI,IAAIC,mBAAmB,CAACD,KAAK,CAAC,CACxC;AAAA;AAEK,SAAUa,2BAA2B,CAACT,OAAiC;EAC3E,MAAMU,MAAM,GAAGH,gCAAgC,CAACP,OAAO,CAAC;EACxD,OAAiBW,GAAoB,IACnCV,gDAAG,GACQW,MAAM,IACbC,4BAAM,EACJjB,KAAK,IAAIK,0BAAM,CAACL,KAAK,CAAC,EAAK,MAAMgB,MAAM,CAAC,EACxC,MAAMX,2BAAOW,MAAM,CAAC,CACrB,CACF;AACP;AAEM,SAAUL,gCAAgC,CAACP,OAAiC;EAChF,OAAWJ,KAAe,IAAgC;IACxD,IAAIkB,mCAAK,CAAgB,EAAE;MACzB,iCAAQlB,KAAsB;;IAEhC,OAAOG,gBAAgB,CAACH,KAAK,EAAEI,OAAO,CAAC;EACzC,CAAC;AACH","names":["MessageException","CauseException","constructor","cause","FatalQueueException","reportQueueError_","reportQueueError","context","tsplus_module_4","_","tsplus_module_3","requestContext","forkDaemonReportQueue","self","reportNonInterruptedFailureCause","reportFatalQueueError","reportNonInterruptedFailure","report","inp","result","tsplus_module_5","tsplus_module_6"],"sourceRoot":"","sources":["../../../_src/services/QueueMaker/errors.ts"],"sourcesContent":[null]}
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.makeMemQueue = makeMemQueue;
|
|
7
|
-
exports.silence = silence;
|
|
8
7
|
var tsplus_module_1 = _interopRequireWildcard(require("@effect/io/Effect"));
|
|
9
8
|
var tsplus_module_2 = _interopRequireWildcard(require("@effect-app/infra/RequestContext"));
|
|
10
9
|
var tsplus_module_3 = _interopRequireWildcard(require("@effect-app/core/_ext/Iterable"));
|
|
@@ -13,10 +12,6 @@ var tsplus_module_5 = _interopRequireWildcard(require("@effect-app/prelude/utils
|
|
|
13
12
|
var tsplus_module_6 = _interopRequireWildcard(require("@effect-app/prelude/_ext/misc"));
|
|
14
13
|
var tsplus_module_7 = _interopRequireWildcard(require("@effect-app/prelude/schema"));
|
|
15
14
|
var tsplus_module_8 = _interopRequireWildcard(require("@effect/io/Fiber"));
|
|
16
|
-
var tsplus_module_9 = _interopRequireWildcard(require("@effect-app/infra/api/setupRequest"));
|
|
17
|
-
var tsplus_module_10 = _interopRequireWildcard(require("@effect/io/Cause"));
|
|
18
|
-
var tsplus_module_11 = _interopRequireWildcard(require("@effect-app/core/Effect"));
|
|
19
|
-
var tsplus_module_12 = _interopRequireWildcard(require("@effect/io/Exit"));
|
|
20
15
|
var _memQueue = require("@effect-app/infra-adapters/memQueue");
|
|
21
16
|
var _Memory = require("../Store/Memory.cjs");
|
|
22
17
|
var _errors2 = require("./errors.cjs");
|
|
@@ -29,7 +24,7 @@ function makeMemQueue(queueName, queueDrainName, encoder, makeHandleEvent, provi
|
|
|
29
24
|
return tsplus_module_1.gen(function* ($) {
|
|
30
25
|
const mem = yield* $(tsplus_module_1.service(_memQueue.MemQueue));
|
|
31
26
|
const q = yield* $(mem.getOrCreateQueue(queueName));
|
|
32
|
-
const
|
|
27
|
+
const qDrain = yield* $(mem.getOrCreateQueue(queueDrainName));
|
|
33
28
|
return {
|
|
34
29
|
publish: (...messages) => tsplus_module_1.gen(function* ($) {
|
|
35
30
|
const requestContext = yield* $(tsplus_module_1.service(tsplus_module_2.tag));
|
|
@@ -44,6 +39,9 @@ function makeMemQueue(queueName, queueDrainName, encoder, makeHandleEvent, provi
|
|
|
44
39
|
}),
|
|
45
40
|
drain: tsplus_module_1.gen(function* ($) {
|
|
46
41
|
const handleEvent = yield* $(makeHandleEvent);
|
|
42
|
+
const silenceAndReportError = (0, _errors2.reportNonInterruptedFailure)({
|
|
43
|
+
name: "MemQueue.drain." + queueDrainName
|
|
44
|
+
});
|
|
47
45
|
const processMessage = msg =>
|
|
48
46
|
// we JSON parse, because that is what the wire also does, and it reveals holes in e.g unknown encoders (Date->String)
|
|
49
47
|
tsplus_module_1.flatMap(tsplus_module_1.orDie(tsplus_module_1.flatMap(tsplus_module_1.sync(() => JSON.parse(msg)), parseDrain)), ({
|
|
@@ -53,29 +51,16 @@ function makeMemQueue(queueName, queueDrainName, encoder, makeHandleEvent, provi
|
|
|
53
51
|
id: body.id,
|
|
54
52
|
locale: "en",
|
|
55
53
|
name: tsplus_module_7.ReasonableString(body._tag)
|
|
56
|
-
}))(tsplus_module_1.zipRight(tsplus_module_1.tap(tsplus_module_6.logAnnotates({
|
|
54
|
+
}))(silenceAndReportError(tsplus_module_1.zipRight(tsplus_module_1.tap(tsplus_module_6.logAnnotates({
|
|
57
55
|
body: tsplus_module_5.RecordPretty(tsplus_module_5.object$(body)),
|
|
58
56
|
meta: tsplus_module_5.RecordPretty(tsplus_module_5.object$(meta))
|
|
59
|
-
})(tsplus_module_1.logDebug(`$$ [${queueDrainName}] Processing incoming message`)), () => _Memory.restoreFromRequestContext),
|
|
60
|
-
return yield* $(tsplus_module_1.forkScoped(tsplus_module_1.forever(
|
|
57
|
+
})(tsplus_module_1.logDebug(`$$ [${queueDrainName}] Processing incoming message`)), () => _Memory.restoreFromRequestContext), handleEvent(body)))));
|
|
58
|
+
return yield* $(tsplus_module_1.forkScoped(tsplus_module_1.forever(silenceAndReportError(tsplus_module_1.flatMap(qDrain.take(), x => tsplus_module_1.flatMap(tsplus_module_1.fork(tsplus_module_1.uninterruptible(processMessage(x))), _ => tsplus_module_8.join(_)))
|
|
59
|
+
// TODO: normally a failed item would be returned to the queue and retried up to X times.
|
|
60
|
+
// .flatMap(_ => _._tag === "Failure" && !isInterrupted ? qDrain.offer(x) : Effect.unit) // TODO: retry count tracking and max retries.
|
|
61
|
+
))));
|
|
61
62
|
})
|
|
62
63
|
};
|
|
63
64
|
});
|
|
64
65
|
}
|
|
65
|
-
// We want the Queue to continue processing even on errors per messages
|
|
66
|
-
// must make sure that the errors are processed/handled beforehand.
|
|
67
|
-
function silence(inp) {
|
|
68
|
-
return tsplus_module_1.flatMap(tsplus_module_1.exit(inp), result => tsplus_module_1.gen(function* ($) {
|
|
69
|
-
const requestContext = yield* $(tsplus_module_1.service(tsplus_module_2.tag));
|
|
70
|
-
return yield* $(tsplus_module_12.match(result, cause => {
|
|
71
|
-
if (tsplus_module_10.isInterrupted(cause)) {
|
|
72
|
-
return tsplus_module_1.failCause(cause);
|
|
73
|
-
}
|
|
74
|
-
(0, _errors2.reportQueueError)(cause, {
|
|
75
|
-
requestContext
|
|
76
|
-
});
|
|
77
|
-
return tsplus_module_11.unit;
|
|
78
|
-
}, () => tsplus_module_11.unit));
|
|
79
|
-
}));
|
|
80
|
-
}
|
|
81
66
|
//# sourceMappingURL=memQueue.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memQueue.cjs","mappings":"
|
|
1
|
+
{"version":3,"file":"memQueue.cjs","mappings":";;;;;;;;;;;;;;AAAA;AAGA;AACA;AAAyD;AAAA;AAGzD;;;AAGM,SAAUA,YAAY,CAQ1BC,SAAiB,EACjBC,cAAsB,EACtBC,OAAyD,EACzDC,eAAwF,EACxFC,cAEwD,EACxDC,UAGmF;EAEnF,OAAOC,oBAAW,WAAUC,CAAC;IAC3B,MAAMC,GAAG,GAAG,OAAOD,CAAC,yBAACE,kBAAQ,EAAQ;IACrC,MAAMC,CAAC,GAAG,OAAOH,CAAC,CAACC,GAAG,CAACG,gBAAgB,CAACX,SAAS,CAAC,CAAC;IACnD,MAAMY,MAAM,GAAG,OAAOL,CAAC,CAACC,GAAG,CAACG,gBAAgB,CAACV,cAAc,CAAC,CAAC;IAE7D,OAAO;MACLY,OAAO,EAAE,CAAC,GAAGC,QAAQ,KACnBR,oBAAW,WAAUC,CAAC;QACpB,MAAMQ,cAAc,GAAG,OAAOR,CAAC,8CAA2B;QAC1D,OAAO,OAAOA,CAAC,uCACbS,oCAAQ,EAAeC,CAAC,IAAGX;QACzB;QACAA,mDACEY,IAAI,CAACC,SAAS,CACZjB,OAAO,CAAC;UAAEkB,IAAI,EAAEH,CAAC;UAAEI,IAAI,EAAEN;QAAc,CAAE,CAAC,CAC3C;QAED;QAAA,EACSO,CAAC,IAAIZ,CAAC,CAACa,KAAK,CAACD,CAAC,CAAC,CAAC,CAClB,CACV,EAEF;MACH,CAAC,CAAC;MACJE,KAAK,EAAElB,oBAAW,WAAUC,CAAC;QAC3B,MAAMkB,WAAW,GAAG,OAAOlB,CAAC,CAACJ,eAAe,CAAC;QAC7C,MAAMuB,qBAAqB,GAAG,wCAA2B,EAAC;UAAEC,IAAI,EAAE,iBAAiB,GAAG1B;QAAc,CAAE,CAAC;QACvG,MAAM2B,cAAc,GAAIC,GAAW;QACjC;QACAvB,iGAAOY,IAAI,CAACY,KAAK,CAACD,GAAG,CAAC,CAAC,EACZxB,UAAU,CAAC,GAEX,CAAC;UAAEe,IAAI;UAAEC;QAAI,CAAE,KAQlBjB,cAAc,CACZ2B,8BAAc,CAACC,OAAO,CAACX,IAAI,EAAE;UAC3BY,EAAE,EAAEb,IAAI,CAACa,EAAE;UACXC,MAAM,EAAE,IAAa;UACrBP,IAAI,EAAEQ,gCAAgB,CAACf,IAAI,CAACgB,IAAI;SACjC,CAAC,CACH,CARIV,qBAAqB,CAL9BpB,6CAES+B,6BAAoB;UAAEjB,IAAI,uDAAEA,IAAI,EAAU;UAAEC,IAAI,uDAAEA,IAAI;QAAU,CAAE,CAAC,CAF5Ef,yBACY,OAAOL,cAAc,+BAA+B,CAAC,GAE1D,MAAMqC,iCAAyB,CAAC,EAC3Bb,WAAW,CAACL,IAAI,CAAC,CAAC,EAU3B,CACJ;QACL,OAAO,OAAOb,CAAC,oDAKJmB,qBAAqB,CAJ9BpB,8BAAM,CAACiC,IAAI,EAAE,EACFC,CAAC,IAAIlC,2FAAc,CAACkC,CAAC,CAAC,IAA8BlB,CAAC,IAAGmB,qBAACnB,CAAC,CAAK,CAAC;QACzE;QACA;QAAA,IAIH;MACH,CAAC;KAC+B;EACpC,CAAC,CAAC;AACJ","names":["makeMemQueue","queueName","queueDrainName","encoder","makeHandleEvent","provideContext","parseDrain","tsplus_module_1","$","mem","MemQueue","q","getOrCreateQueue","qDrain","publish","messages","requestContext","tsplus_module_3","m","JSON","stringify","body","meta","_","offer","drain","handleEvent","silenceAndReportError","name","processMessage","msg","parse","RequestContext","inherit","id","locale","tsplus_module_7","_tag","tsplus_module_6","restoreFromRequestContext","take","x","tsplus_module_8"],"sourceRoot":"","sources":["../../../_src/services/QueueMaker/memQueue.ts"],"sourcesContent":[null]}
|
|
@@ -10,10 +10,9 @@ var tsplus_module_2 = _interopRequireWildcard(require("@effect-app/core/Tag"));
|
|
|
10
10
|
var tsplus_module_3 = _interopRequireWildcard(require("@effect-app/prelude/utils"));
|
|
11
11
|
var tsplus_module_4 = _interopRequireWildcard(require("@effect-app/prelude/_ext/misc"));
|
|
12
12
|
var tsplus_module_5 = _interopRequireWildcard(require("@effect-app/prelude/schema"));
|
|
13
|
-
var tsplus_module_6 = _interopRequireWildcard(require("@effect-app/infra/
|
|
14
|
-
var tsplus_module_7 = _interopRequireWildcard(require("@effect-app/infra/
|
|
15
|
-
var tsplus_module_8 = _interopRequireWildcard(require("@effect
|
|
16
|
-
var tsplus_module_9 = _interopRequireWildcard(require("@effect/io/Layer"));
|
|
13
|
+
var tsplus_module_6 = _interopRequireWildcard(require("@effect-app/infra/RequestContext"));
|
|
14
|
+
var tsplus_module_7 = _interopRequireWildcard(require("@effect-app/infra/services/QueueMaker/errors"));
|
|
15
|
+
var tsplus_module_8 = _interopRequireWildcard(require("@effect/io/Layer"));
|
|
17
16
|
var _ServiceBus = require("@effect-app/infra-adapters/ServiceBus");
|
|
18
17
|
var _errorReporter = require("@effect-app/infra/errorReporter");
|
|
19
18
|
var _Memory = require("../Store/Memory.cjs");
|
|
@@ -28,31 +27,39 @@ function makeServiceBusQueue(_queueName, queueDrainName, encoder, makeHandleEven
|
|
|
28
27
|
const s = yield* $(tsplus_module_1.service(_ServiceBus.Sender));
|
|
29
28
|
const receiver = yield* $(tsplus_module_1.service(_ServiceBus.Receiver));
|
|
30
29
|
const receiverLayer = tsplus_module_2.makeLayer(_ServiceBus.Receiver, receiver);
|
|
30
|
+
const silenceAndReportError = (0, _errors2.reportNonInterruptedFailure)({
|
|
31
|
+
name: "ServiceBusQueue.drain." + queueDrainName
|
|
32
|
+
});
|
|
33
|
+
const reportError = (0, _errors2.reportNonInterruptedFailureCause)({
|
|
34
|
+
name: "ServiceBusQueue.drain." + queueDrainName
|
|
35
|
+
});
|
|
31
36
|
return {
|
|
32
37
|
drain: tsplus_module_1.gen(function* ($) {
|
|
33
38
|
const handleEvent = yield* $(makeHandleEvent);
|
|
34
39
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
40
|
function processMessage(messageBody) {
|
|
36
|
-
return tsplus_module_1.
|
|
41
|
+
return tsplus_module_1.tapErrorCause(tsplus_module_1.flatMap(tsplus_module_1.orDie(tsplus_module_1.flatMap(tsplus_module_1.sync(() => JSON.parse(messageBody)), x => parseDrain(x))), ({
|
|
37
42
|
body,
|
|
38
43
|
meta
|
|
39
|
-
}) => provideContext(
|
|
44
|
+
}) => provideContext(tsplus_module_6.RequestContext.inherit(meta, {
|
|
40
45
|
id: body.id,
|
|
41
46
|
locale: "en",
|
|
42
47
|
name: tsplus_module_5.ReasonableString(body._tag)
|
|
43
|
-
}))(tsplus_module_1.
|
|
48
|
+
}))(silenceAndReportError(tsplus_module_1.orDie(tsplus_module_1.zipRight(tsplus_module_1.tap(tsplus_module_4.logAnnotates({
|
|
44
49
|
body: tsplus_module_3.RecordPretty(tsplus_module_3.object$(body)),
|
|
45
50
|
meta: tsplus_module_3.RecordPretty(tsplus_module_3.object$(meta))
|
|
46
|
-
})(tsplus_module_1.logDebug(`$$ [${queueDrainName}] Processing incoming message`)), () => _Memory.restoreFromRequestContext), handleEvent(body))
|
|
51
|
+
})(tsplus_module_1.logDebug(`$$ [${queueDrainName}] Processing incoming message`)), () => _Memory.restoreFromRequestContext), handleEvent(body))))))
|
|
52
|
+
// we reportError here, so that we report the error only, and keep flowing
|
|
53
|
+
, reportError);
|
|
47
54
|
}
|
|
48
55
|
return yield* $(tsplus_module_1.provideSomeLayer((0, _ServiceBus.subscribe)({
|
|
49
|
-
processMessage: x => tsplus_module_1.uninterruptible(processMessage(x.body)),
|
|
56
|
+
processMessage: x => tsplus_module_1.flatMap(tsplus_module_1.uninterruptible(processMessage(x.body)), _ => tsplus_module_1.done(_)),
|
|
50
57
|
processError: err => tsplus_module_1.sync(() => (0, _errorReporter.captureException)(err.error))
|
|
51
58
|
}), receiverLayer));
|
|
52
59
|
}),
|
|
53
60
|
publish: (...messages) => tsplus_module_1.gen(function* ($) {
|
|
54
|
-
const requestContext = yield* $(tsplus_module_1.service(
|
|
55
|
-
return yield* $(
|
|
61
|
+
const requestContext = yield* $(tsplus_module_1.service(tsplus_module_6.tag));
|
|
62
|
+
return yield* $(tsplus_module_7.forkDaemonReportQueue(tsplus_module_1.promise(() => s.sendMessages(messages.map(x => ({
|
|
56
63
|
body: JSON.stringify(encoder({
|
|
57
64
|
body: x,
|
|
58
65
|
meta: requestContext
|
|
@@ -68,14 +75,6 @@ function makeServiceBusQueue(_queueName, queueDrainName, encoder, makeHandleEven
|
|
|
68
75
|
* @tsplus static QueueMaker.Ops makeServiceBusLayers
|
|
69
76
|
*/
|
|
70
77
|
function makeServiceBusLayers(url, queueName, queueDrainName) {
|
|
71
|
-
return
|
|
72
|
-
}
|
|
73
|
-
function report(cause) {
|
|
74
|
-
return tsplus_module_1.gen(function* ($) {
|
|
75
|
-
const requestContext = yield* $(tsplus_module_1.service(tsplus_module_7.tag));
|
|
76
|
-
return (0, _errors2.reportQueueError)(cause, {
|
|
77
|
-
requestContext
|
|
78
|
-
});
|
|
79
|
-
});
|
|
78
|
+
return tsplus_module_8.provide(tsplus_module_8.merge((0, _ServiceBus.LiveSender)(queueName))((0, _ServiceBus.LiveReceiver)(queueDrainName)))((0, _ServiceBus.LiveServiceBusClient)(url));
|
|
80
79
|
}
|
|
81
80
|
//# sourceMappingURL=sbqueue.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sbqueue.cjs","mappings":"
|
|
1
|
+
{"version":3,"file":"sbqueue.cjs","mappings":"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","names":["makeServiceBusQueue","_queueName","queueDrainName","encoder","makeHandleEvent","provideContext","parseDrain","tsplus_module_1","$","s","Sender","receiver","Receiver","receiverLayer","tsplus_module_2","silenceAndReportError","name","reportError","drain","handleEvent","processMessage","messageBody","JSON","parse","x","body","meta","RequestContext","inherit","id","locale","tsplus_module_5","_tag","tsplus_module_4","restoreFromRequestContext","_","processError","err","error","publish","messages","requestContext","sendMessages","map","stringify","messageId","contentType","makeServiceBusLayers","url","queueName","tsplus_module_8"],"sourceRoot":"","sources":["../../../_src/services/QueueMaker/sbqueue.ts"],"sourcesContent":[null]}
|
|
@@ -16,13 +16,11 @@ export function defaultBasicErrorHandler<R>(
|
|
|
16
16
|
_requestContext: RequestContext,
|
|
17
17
|
r2: Effect<R, ValidationError, void>
|
|
18
18
|
) {
|
|
19
|
+
const sendError = (code: number) => (body: unknown) => Effect(res.status(code).send(body))
|
|
19
20
|
return Debug.untraced(() =>
|
|
20
21
|
r2
|
|
21
22
|
.tapErrorCause(cause => cause.isFailure() ? logRequestError(cause) : Effect.unit)
|
|
22
|
-
.catchTag("ValidationError", err =>
|
|
23
|
-
Effect.sync(() => {
|
|
24
|
-
res.status(400).send(err.errors)
|
|
25
|
-
}))
|
|
23
|
+
.catchTag("ValidationError", err => sendError(400)(err.errors))
|
|
26
24
|
// final catch all; expecting never so that unhandled known errors will show up
|
|
27
25
|
.catchAll((err: never) =>
|
|
28
26
|
Effect.logError(
|
|
@@ -46,34 +44,19 @@ export function defaultErrorHandler<R>(
|
|
|
46
44
|
const r3 = req.method === "PATCH"
|
|
47
45
|
? r2.retry(optimisticConcurrencySchedule)
|
|
48
46
|
: r2
|
|
47
|
+
const sendError = (code: number) => (body: unknown) => Effect(res.status(code).send(body))
|
|
49
48
|
return Debug.untraced(() =>
|
|
50
49
|
r3
|
|
51
50
|
.tapErrorCause(cause => cause.isFailure() ? logRequestError(cause) : Effect.unit)
|
|
52
|
-
.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
Effect.sync(() => {
|
|
62
|
-
res.status(401).send(err)
|
|
63
|
-
}))
|
|
64
|
-
.catchTag("UnauthorizedError", err =>
|
|
65
|
-
Effect.sync(() => {
|
|
66
|
-
res.status(403).send(err)
|
|
67
|
-
}))
|
|
68
|
-
.catchTag("InvalidStateError", err =>
|
|
69
|
-
Effect.sync(() => {
|
|
70
|
-
res.status(422).send(err)
|
|
71
|
-
}))
|
|
72
|
-
.catchTag("OptimisticConcurrencyException", err =>
|
|
73
|
-
Effect.sync(() => {
|
|
74
|
-
// 412 or 409.. https://stackoverflow.com/questions/19122088/which-http-status-code-to-use-to-reject-a-put-due-to-optimistic-locking-failure
|
|
75
|
-
res.status(412).send(err)
|
|
76
|
-
}))
|
|
51
|
+
.catchTags({
|
|
52
|
+
"ValidationError": err => sendError(400)(err.errors),
|
|
53
|
+
"NotFoundError": sendError(404),
|
|
54
|
+
"NotLoggedInError": sendError(401),
|
|
55
|
+
"UnauthorizedError": sendError(403),
|
|
56
|
+
"InvalidStateError": sendError(422),
|
|
57
|
+
// 412 or 409.. https://stackoverflow.com/questions/19122088/which-http-status-code-to-use-to-reject-a-put-due-to-optimistic-locking-failure
|
|
58
|
+
"OptimisticConcurrencyException": sendError(412)
|
|
59
|
+
})
|
|
77
60
|
// final catch all; expecting never so that unhandled known errors will show up
|
|
78
61
|
.catchAll((err: never) =>
|
|
79
62
|
Effect.logError(
|
|
@@ -17,9 +17,8 @@ export class FatalQueueException<E> extends CauseException<E> {
|
|
|
17
17
|
const reportQueueError_ = reportError(cause => new MessageException(cause))
|
|
18
18
|
|
|
19
19
|
export const reportQueueError = <E>(cause: Cause<E>, context?: Record<string, unknown> | undefined) =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
)
|
|
20
|
+
Effect.contextWith((_: Context<never>) => Context.getOption(_, RequestContext.Tag))
|
|
21
|
+
.flatMap(requestContext => reportQueueError_(cause, { requestContext: requestContext.value, ...context }))
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
24
|
* Forks the effect into a new fiber attached to the global scope. Because the
|
|
@@ -31,18 +30,30 @@ export const reportQueueError = <E>(cause: Cause<E>, context?: Record<string, un
|
|
|
31
30
|
* @tsplus getter effect/io/Effect forkDaemonReportQueue
|
|
32
31
|
*/
|
|
33
32
|
export function forkDaemonReportQueue<R, E, A>(self: Effect<R, E, A>) {
|
|
34
|
-
return self.tapErrorCause(
|
|
33
|
+
return self.tapErrorCause(reportNonInterruptedFailureCause({})).fork.daemonChildren
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
export const reportFatalQueueError = reportError(
|
|
38
37
|
cause => new FatalQueueException(cause)
|
|
39
38
|
)
|
|
40
39
|
|
|
41
|
-
export function
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
export function reportNonInterruptedFailure(context?: Record<string, unknown>) {
|
|
41
|
+
const report = reportNonInterruptedFailureCause(context)
|
|
42
|
+
return <R, E, A>(inp: Effect<R, E, A>): Effect<R, never, Exit<E, A>> =>
|
|
43
|
+
inp.exit
|
|
44
|
+
.flatMap(result =>
|
|
45
|
+
result.match(
|
|
46
|
+
cause => report(cause).map(() => result),
|
|
47
|
+
() => Effect(result)
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function reportNonInterruptedFailureCause(context?: Record<string, unknown>) {
|
|
53
|
+
return <E>(cause: Cause<E>): Effect<never, never, void> => {
|
|
54
|
+
if (cause.isInterrupted()) {
|
|
55
|
+
return (cause as Cause<never>).failCause
|
|
56
|
+
}
|
|
57
|
+
return reportQueueError(cause, context)
|
|
58
|
+
}
|
|
48
59
|
}
|
|
@@ -2,20 +2,27 @@ import { MemQueue } from "@effect-app/infra-adapters/memQueue"
|
|
|
2
2
|
import { RequestContext } from "@effect-app/infra/RequestContext"
|
|
3
3
|
import type { CustomSchemaException } from "@effect-app/prelude/schema"
|
|
4
4
|
import { restoreFromRequestContext } from "../Store/Memory.js"
|
|
5
|
-
import {
|
|
5
|
+
import { reportNonInterruptedFailure } from "./errors.js"
|
|
6
6
|
import type { QueueBase } from "./service.js"
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @tsplus static QueueMaker.Ops makeMem
|
|
10
10
|
*/
|
|
11
|
-
export function makeMemQueue<
|
|
11
|
+
export function makeMemQueue<
|
|
12
|
+
DrainR,
|
|
13
|
+
Evt,
|
|
14
|
+
DrainEvt extends { id: StringId; _tag: string },
|
|
15
|
+
RContext,
|
|
16
|
+
EvtE,
|
|
17
|
+
DrainE
|
|
18
|
+
>(
|
|
12
19
|
queueName: string,
|
|
13
20
|
queueDrainName: string,
|
|
14
21
|
encoder: (e: { body: Evt; meta: RequestContext }) => EvtE,
|
|
15
22
|
makeHandleEvent: Effect<DrainR, never, (ks: DrainEvt) => Effect<RContext, DrainE, void>>,
|
|
16
23
|
provideContext: (context: RequestContext) => <R, E, A>(
|
|
17
24
|
eff: Effect<RContext | R, E, A>
|
|
18
|
-
) => Effect<Exclude<R, RContext>, E, A>,
|
|
25
|
+
) => Effect<Exclude<R, RContext | RequestContext>, E, A>,
|
|
19
26
|
parseDrain: (
|
|
20
27
|
a: unknown,
|
|
21
28
|
env?: Parser.ParserEnv | undefined
|
|
@@ -24,7 +31,7 @@ export function makeMemQueue<DrainR, Evt, DrainEvt extends { id: StringId; _tag:
|
|
|
24
31
|
return Effect.gen(function*($) {
|
|
25
32
|
const mem = yield* $(MemQueue.access)
|
|
26
33
|
const q = yield* $(mem.getOrCreateQueue(queueName))
|
|
27
|
-
const
|
|
34
|
+
const qDrain = yield* $(mem.getOrCreateQueue(queueDrainName))
|
|
28
35
|
|
|
29
36
|
return {
|
|
30
37
|
publish: (...messages) =>
|
|
@@ -47,6 +54,7 @@ export function makeMemQueue<DrainR, Evt, DrainEvt extends { id: StringId; _tag:
|
|
|
47
54
|
}),
|
|
48
55
|
drain: Effect.gen(function*($) {
|
|
49
56
|
const handleEvent = yield* $(makeHandleEvent)
|
|
57
|
+
const silenceAndReportError = reportNonInterruptedFailure({ name: "MemQueue.drain." + queueDrainName })
|
|
50
58
|
const processMessage = (msg: string) =>
|
|
51
59
|
// we JSON parse, because that is what the wire also does, and it reveals holes in e.g unknown encoders (Date->String)
|
|
52
60
|
Effect(JSON.parse(msg))
|
|
@@ -57,7 +65,8 @@ export function makeMemQueue<DrainR, Evt, DrainEvt extends { id: StringId; _tag:
|
|
|
57
65
|
.logDebug(`$$ [${queueDrainName}] Processing incoming message`)
|
|
58
66
|
.apply(Effect.logAnnotates({ body: body.$$.pretty, meta: meta.$$.pretty }))
|
|
59
67
|
.tap(() => restoreFromRequestContext)
|
|
60
|
-
.zipRight(
|
|
68
|
+
.zipRight(handleEvent(body))
|
|
69
|
+
.apply(silenceAndReportError)
|
|
61
70
|
.apply(
|
|
62
71
|
provideContext(
|
|
63
72
|
RequestContext.inherit(meta, {
|
|
@@ -69,11 +78,11 @@ export function makeMemQueue<DrainR, Evt, DrainEvt extends { id: StringId; _tag:
|
|
|
69
78
|
)
|
|
70
79
|
)
|
|
71
80
|
return yield* $(
|
|
72
|
-
|
|
81
|
+
qDrain.take()
|
|
73
82
|
.flatMap(x => processMessage(x).uninterruptible.fork.flatMap(_ => _.join))
|
|
74
|
-
.
|
|
75
|
-
//
|
|
76
|
-
.
|
|
83
|
+
// TODO: normally a failed item would be returned to the queue and retried up to X times.
|
|
84
|
+
// .flatMap(_ => _._tag === "Failure" && !isInterrupted ? qDrain.offer(x) : Effect.unit) // TODO: retry count tracking and max retries.
|
|
85
|
+
.apply(silenceAndReportError)
|
|
77
86
|
.forever
|
|
78
87
|
.forkScoped
|
|
79
88
|
)
|
|
@@ -81,25 +90,3 @@ export function makeMemQueue<DrainR, Evt, DrainEvt extends { id: StringId; _tag:
|
|
|
81
90
|
} satisfies QueueBase<DrainR, Evt>
|
|
82
91
|
})
|
|
83
92
|
}
|
|
84
|
-
|
|
85
|
-
// We want the Queue to continue processing even on errors per messages
|
|
86
|
-
// must make sure that the errors are processed/handled beforehand.
|
|
87
|
-
export function silence<R, E, A>(inp: Effect<R, E, A>) {
|
|
88
|
-
return inp.exit.flatMap(result =>
|
|
89
|
-
Effect.gen(function*($) {
|
|
90
|
-
const requestContext = yield* $(RequestContext.Tag.access)
|
|
91
|
-
return yield* $(
|
|
92
|
-
result.match(
|
|
93
|
-
cause => {
|
|
94
|
-
if (cause.isInterrupted()) {
|
|
95
|
-
return (cause as Cause<never>).failCause
|
|
96
|
-
}
|
|
97
|
-
reportQueueError(cause, { requestContext })
|
|
98
|
-
return Effect.unit
|
|
99
|
-
},
|
|
100
|
-
() => Effect.unit
|
|
101
|
-
)
|
|
102
|
-
)
|
|
103
|
-
})
|
|
104
|
-
)
|
|
105
|
-
}
|