exisjs 0.5.7 → 0.5.10
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/dist/auth/session.d.ts +4 -1
- package/dist/auth/session.d.ts.map +1 -1
- package/dist/auth/session.js +33 -5
- package/dist/auth/session.js.map +1 -1
- package/dist/cache/store.d.ts +11 -3
- package/dist/cache/store.d.ts.map +1 -1
- package/dist/cache/store.js +87 -19
- package/dist/cache/store.js.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +4 -5
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/middleware/backpressure.d.ts.map +1 -1
- package/dist/middleware/backpressure.js +21 -12
- package/dist/middleware/backpressure.js.map +1 -1
- package/dist/middleware/cache.d.ts +6 -0
- package/dist/middleware/cache.d.ts.map +1 -1
- package/dist/middleware/cache.js +84 -28
- package/dist/middleware/cache.js.map +1 -1
- package/dist/middleware/idempotency.d.ts +4 -1
- package/dist/middleware/idempotency.d.ts.map +1 -1
- package/dist/middleware/idempotency.js +29 -4
- package/dist/middleware/idempotency.js.map +1 -1
- package/dist/middleware/ip-filter.d.ts.map +1 -1
- package/dist/middleware/ip-filter.js +16 -0
- package/dist/middleware/ip-filter.js.map +1 -1
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +29 -12
- package/dist/middleware/rate-limit.js.map +1 -1
- package/dist/queue/drivers/MemoryDriver.d.ts +6 -3
- package/dist/queue/drivers/MemoryDriver.d.ts.map +1 -1
- package/dist/queue/drivers/MemoryDriver.js +76 -23
- package/dist/queue/drivers/MemoryDriver.js.map +1 -1
- package/dist/server/bootstrapper.d.ts +3 -0
- package/dist/server/bootstrapper.d.ts.map +1 -1
- package/dist/server/bootstrapper.js +55 -7
- package/dist/server/bootstrapper.js.map +1 -1
- package/dist/server/bun-adapter.d.ts +2 -0
- package/dist/server/bun-adapter.d.ts.map +1 -1
- package/dist/server/bun-adapter.js +23 -12
- package/dist/server/bun-adapter.js.map +1 -1
- package/dist/server/request-handler.d.ts +0 -2
- package/dist/server/request-handler.d.ts.map +1 -1
- package/dist/server/request-handler.js +2 -24
- package/dist/server/request-handler.js.map +1 -1
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +24 -11
- package/dist/server/request.js.map +1 -1
- package/dist/server/uws-adapter.d.ts +80 -0
- package/dist/server/uws-adapter.d.ts.map +1 -0
- package/dist/server/uws-adapter.js +357 -0
- package/dist/server/uws-adapter.js.map +1 -0
- package/dist/server/ws-orchestrator.d.ts +1 -0
- package/dist/server/ws-orchestrator.d.ts.map +1 -1
- package/dist/server/ws-orchestrator.js +83 -0
- package/dist/server/ws-orchestrator.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/validator/tex.d.ts +21 -16
- package/dist/validator/tex.d.ts.map +1 -1
- package/dist/validator/tex.js.map +1 -1
- package/package.json +4 -3
package/dist/middleware/cache.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.cacheMiddleware = cacheMiddleware;
|
|
4
4
|
const store_1 = require("../cache/store");
|
|
5
|
+
// Global in-flight requests map to prevent Cache Stampedes (Dogpile effect)
|
|
6
|
+
const inFlightRequests = new Map();
|
|
5
7
|
function cacheMiddleware(options) {
|
|
6
8
|
const ttlMs = options.ttlMs;
|
|
7
9
|
if (!options || typeof options.keyGenerator !== 'function') {
|
|
@@ -17,37 +19,74 @@ function cacheMiddleware(options) {
|
|
|
17
19
|
try {
|
|
18
20
|
const cached = await store.get(key);
|
|
19
21
|
if (cached) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
const isStale = ttlMs && Date.now() - cached.createdAt > ttlMs;
|
|
23
|
+
// If it's stale and we have no SWR allowance, we act as a miss
|
|
24
|
+
if (isStale &&
|
|
25
|
+
(!options.swrMs ||
|
|
26
|
+
Date.now() - cached.createdAt > ttlMs + options.swrMs)) {
|
|
27
|
+
// Treated as miss
|
|
22
28
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
else {
|
|
30
|
+
// Handle Buffer reconstruction for Redis
|
|
31
|
+
if (cached.data.contentType) {
|
|
32
|
+
res.set('Content-Type', cached.data.contentType);
|
|
33
|
+
}
|
|
34
|
+
res.set('X-Exis-Cache', isStale ? 'STALE' : 'HIT');
|
|
35
|
+
let bodyToSend = cached.data.body;
|
|
36
|
+
if (typeof cached.data.body === 'string' && cached.data.isBuffer) {
|
|
37
|
+
bodyToSend = Buffer.from(cached.data.body, 'base64');
|
|
38
|
+
}
|
|
39
|
+
if (cached.data.contentType?.includes('application/json') &&
|
|
40
|
+
typeof bodyToSend === 'string') {
|
|
41
|
+
try {
|
|
42
|
+
res.status(cached.data.statusCode).json(JSON.parse(bodyToSend));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
res.status(cached.data.statusCode).send(bodyToSend);
|
|
46
|
+
}
|
|
35
47
|
}
|
|
36
|
-
|
|
37
|
-
// If parsing fails, fall back to send
|
|
48
|
+
else {
|
|
38
49
|
res.status(cached.data.statusCode).send(bodyToSend);
|
|
39
50
|
}
|
|
51
|
+
if (!isStale) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// If it was stale, we returned the response already. Now we fall through
|
|
55
|
+
// to trigger a background revalidation! We MUST NOT return here if stale.
|
|
40
56
|
}
|
|
41
|
-
else {
|
|
42
|
-
res.status(cached.data.statusCode).send(bodyToSend);
|
|
43
|
-
}
|
|
44
|
-
return;
|
|
45
57
|
}
|
|
46
58
|
}
|
|
47
59
|
catch {
|
|
48
60
|
// Fallback to normal execution if cache read fails
|
|
49
61
|
}
|
|
50
|
-
|
|
62
|
+
// --- Cache Stampede Prevention ---
|
|
63
|
+
// If another request is currently resolving this exact same cache key, we just wait for it.
|
|
64
|
+
if (!res.headersSent) {
|
|
65
|
+
if (inFlightRequests.has(key)) {
|
|
66
|
+
res.set('X-Exis-Cache', 'DEDUPED');
|
|
67
|
+
const dedupeResponse = await inFlightRequests.get(key);
|
|
68
|
+
if (dedupeResponse.contentType) {
|
|
69
|
+
res.set('Content-Type', dedupeResponse.contentType);
|
|
70
|
+
}
|
|
71
|
+
if (dedupeResponse.contentType?.includes('application/json') &&
|
|
72
|
+
typeof dedupeResponse.body === 'string') {
|
|
73
|
+
return res
|
|
74
|
+
.status(dedupeResponse.statusCode)
|
|
75
|
+
.json(JSON.parse(dedupeResponse.body));
|
|
76
|
+
}
|
|
77
|
+
return res.status(dedupeResponse.statusCode).send(dedupeResponse.body);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Set headers if not already sent (by SWR)
|
|
81
|
+
if (!res.headersSent) {
|
|
82
|
+
res.set('X-Exis-Cache', 'MISS');
|
|
83
|
+
}
|
|
84
|
+
let resolveInFlight;
|
|
85
|
+
const inFlightPromise = new Promise((resolve) => {
|
|
86
|
+
resolveInFlight = resolve;
|
|
87
|
+
});
|
|
88
|
+
inFlightRequests.set(key, inFlightPromise);
|
|
89
|
+
// --- End Stampede Prevention ---
|
|
51
90
|
// Intercept send/json
|
|
52
91
|
const originalSend = res.send.bind(res);
|
|
53
92
|
const originalJson = res.json.bind(res);
|
|
@@ -60,19 +99,27 @@ function cacheMiddleware(options) {
|
|
|
60
99
|
else if (options.tags) {
|
|
61
100
|
tags = options.tags;
|
|
62
101
|
}
|
|
63
|
-
|
|
64
|
-
Promise.resolve(store.set(key, {
|
|
102
|
+
const payload = {
|
|
65
103
|
body,
|
|
66
104
|
contentType: typeof res.getHeader === 'function'
|
|
67
105
|
? res.getHeader('content-type')
|
|
68
106
|
: undefined,
|
|
69
107
|
statusCode: res.statusCode,
|
|
70
108
|
isBuffer: Buffer.isBuffer(body),
|
|
71
|
-
}
|
|
109
|
+
};
|
|
110
|
+
Promise.resolve(store.set(key, payload, tags, ttlMs)).catch(() => {
|
|
72
111
|
/* noop */
|
|
73
112
|
});
|
|
113
|
+
resolveInFlight(payload);
|
|
114
|
+
inFlightRequests.delete(key);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
resolveInFlight({});
|
|
118
|
+
inFlightRequests.delete(key);
|
|
119
|
+
}
|
|
120
|
+
if (!res.headersSent) {
|
|
121
|
+
return originalSend(body);
|
|
74
122
|
}
|
|
75
|
-
return originalSend(body);
|
|
76
123
|
};
|
|
77
124
|
res.json = function (data) {
|
|
78
125
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
@@ -83,16 +130,25 @@ function cacheMiddleware(options) {
|
|
|
83
130
|
else if (options.tags) {
|
|
84
131
|
tags = options.tags;
|
|
85
132
|
}
|
|
86
|
-
|
|
133
|
+
const payload = {
|
|
87
134
|
body: JSON.stringify(data),
|
|
88
135
|
contentType: 'application/json; charset=utf-8',
|
|
89
136
|
statusCode: res.statusCode,
|
|
90
137
|
isBuffer: false,
|
|
91
|
-
}
|
|
138
|
+
};
|
|
139
|
+
Promise.resolve(store.set(key, payload, tags, ttlMs)).catch(() => {
|
|
92
140
|
/* noop */
|
|
93
141
|
});
|
|
142
|
+
resolveInFlight(payload);
|
|
143
|
+
inFlightRequests.delete(key);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
resolveInFlight({});
|
|
147
|
+
inFlightRequests.delete(key);
|
|
148
|
+
}
|
|
149
|
+
if (!res.headersSent) {
|
|
150
|
+
return originalJson(data);
|
|
94
151
|
}
|
|
95
|
-
return originalJson(data);
|
|
96
152
|
};
|
|
97
153
|
next();
|
|
98
154
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/middleware/cache.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/middleware/cache.ts"],"names":[],"mappings":";;AAwBA,0CA4KC;AAnMD,0CAA+D;AAoB/D,4EAA4E;AAC5E,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAwB,CAAA;AAExD,SAAgB,eAAe,CAAC,OAAqB;IACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;IAC3B,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CACb,qKAAqK,CACtK,CAAA;IACH,CAAC;IACD,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAA;IAEzC,OAAO,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QAC/D,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YACzB,OAAO,IAAI,EAAE,CAAA;QACf,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAA,qBAAa,GAAE,CAAA;QAC9C,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;QAE7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACnC,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,KAAK,CAAA;gBAE9D,+DAA+D;gBAC/D,IACE,OAAO;oBACP,CAAC,CAAC,OAAO,CAAC,KAAK;wBACb,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,EACxD,CAAC;oBACD,kBAAkB;gBACpB,CAAC;qBAAM,CAAC;oBACN,yCAAyC;oBACzC,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;wBAC5B,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;oBAClD,CAAC;oBACD,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;oBAElD,IAAI,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAA;oBACjC,IAAI,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;wBACjE,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;oBACtD,CAAC;oBAED,IACE,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,kBAAkB,CAAC;wBACrD,OAAO,UAAU,KAAK,QAAQ,EAC9B,CAAC;wBACD,IAAI,CAAC;4BACH,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAA;wBACjE,CAAC;wBAAC,MAAM,CAAC;4BACP,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;wBACrD,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACN,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;oBACrD,CAAC;oBAED,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,OAAM;oBACR,CAAC;oBACD,yEAAyE;oBACzE,0EAA0E;gBAC5E,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;QAED,oCAAoC;QACpC,4FAA4F;QAC5F,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAA;gBAClC,MAAM,cAAc,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBAEtD,IAAI,cAAc,CAAC,WAAW,EAAE,CAAC;oBAC/B,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,cAAc,CAAC,WAAW,CAAC,CAAA;gBACrD,CAAC;gBACD,IACE,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,kBAAkB,CAAC;oBACxD,OAAO,cAAc,CAAC,IAAI,KAAK,QAAQ,EACvC,CAAC;oBACD,OAAO,GAAG;yBACP,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC;yBACjC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAA;gBAC1C,CAAC;gBACD,OAAO,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;YACxE,CAAC;QACH,CAAC;QAED,2CAA2C;QAC3C,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;QACjC,CAAC;QAED,IAAI,eAAmC,CAAA;QACvC,MAAM,eAAe,GAAG,IAAI,OAAO,CAAM,CAAC,OAAO,EAAE,EAAE;YACnD,eAAe,GAAG,OAAO,CAAA;QAC3B,CAAC,CAAC,CAAA;QACF,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;QAC1C,kCAAkC;QAElC,sBAAsB;QACtB,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACvC,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAEvC,GAAG,CAAC,IAAI,GAAG,UAAU,IAAqB;YACxC,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;gBAClD,IAAI,IAAI,GAAa,EAAE,CAAA;gBACvB,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBACvC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC1B,CAAC;qBAAM,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;oBACxB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;gBACrB,CAAC;gBAED,MAAM,OAAO,GAAG;oBACd,IAAI;oBACJ,WAAW,EACT,OAAQ,GAAW,CAAC,SAAS,KAAK,UAAU;wBAC1C,CAAC,CAAE,GAAW,CAAC,SAAS,CAAC,cAAc,CAAC;wBACxC,CAAC,CAAC,SAAS;oBACf,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;iBAChC,CAAA;gBAED,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;oBAC/D,UAAU;gBACZ,CAAC,CAAC,CAAA;gBAEF,eAAgB,CAAC,OAAO,CAAC,CAAA;gBACzB,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC;iBAAM,CAAC;gBACN,eAAgB,CAAC,EAAE,CAAC,CAAA;gBACpB,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,OAAO,YAAY,CAAC,IAAI,CAAC,CAAA;YAC3B,CAAC;QACH,CAAC,CAAA;QAED,GAAG,CAAC,IAAI,GAAG,UAAU,IAAa;YAChC,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;gBAClD,IAAI,IAAI,GAAa,EAAE,CAAA;gBACvB,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBACvC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC1B,CAAC;qBAAM,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;oBACxB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;gBACrB,CAAC;gBAED,MAAM,OAAO,GAAG;oBACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;oBAC1B,WAAW,EAAE,iCAAiC;oBAC9C,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,QAAQ,EAAE,KAAK;iBAChB,CAAA;gBAED,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;oBAC/D,UAAU;gBACZ,CAAC,CAAC,CAAA;gBAEF,eAAgB,CAAC,OAAO,CAAC,CAAA;gBACzB,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC;iBAAM,CAAC;gBACN,eAAgB,CAAC,EAAE,CAAC,CAAA;gBACpB,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,OAAO,YAAY,CAAC,IAAI,CAAC,CAAA;YAC3B,CAAC;QACH,CAAC,CAAA;QAED,IAAI,EAAE,CAAA;IACR,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -12,7 +12,10 @@ export interface IdempotencyStore {
|
|
|
12
12
|
}, ttlMs?: number): Promise<void>;
|
|
13
13
|
}
|
|
14
14
|
export declare class MemoryIdempotencyStore implements IdempotencyStore {
|
|
15
|
-
private
|
|
15
|
+
private nativeCache;
|
|
16
|
+
private fallbackCache;
|
|
17
|
+
private isFallback;
|
|
18
|
+
constructor();
|
|
16
19
|
get(key: string): Promise<any>;
|
|
17
20
|
set(key: string, data: any, ttlMs?: number): Promise<void>;
|
|
18
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAIvC,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACxB,UAAU,EAAE,MAAM,CAAA;QAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/B,IAAI,EAAE,GAAG,CAAA;KACV,GAAG,IAAI,CAAC,CAAA;IACT,GAAG,CACD,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAE,EACxE,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAAA;CACjB;AAED,qBAAa,sBAAuB,YAAW,gBAAgB;IAC7D,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAIvC,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACxB,UAAU,EAAE,MAAM,CAAA;QAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/B,IAAI,EAAE,GAAG,CAAA;KACV,GAAG,IAAI,CAAC,CAAA;IACT,GAAG,CACD,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAE,EACxE,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAAA;CACjB;AAED,qBAAa,sBAAuB,YAAW,gBAAgB;IAC7D,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,aAAa,CAAmD;IACxE,OAAO,CAAC,UAAU,CAAQ;;IAapB,GAAG,CAAC,GAAG,EAAE,MAAM;IAoBf,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,SAAW;CAQnD;AAID,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,gBAAgB,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,4FAA4F;IAC5F,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAwEnE;AAED,uDAAuD;AACvD,eAAO,MAAM,UAAU,mBAAa,CAAA"}
|
|
@@ -4,20 +4,45 @@ exports.Idempotent = exports.MemoryIdempotencyStore = void 0;
|
|
|
4
4
|
exports.idempotent = idempotent;
|
|
5
5
|
class MemoryIdempotencyStore {
|
|
6
6
|
constructor() {
|
|
7
|
-
this.
|
|
7
|
+
this.fallbackCache = new Map();
|
|
8
|
+
this.isFallback = false;
|
|
9
|
+
try {
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
11
|
+
const { NativeMemoryCache } = require('@exisjs/rs');
|
|
12
|
+
// Cap at 10,000 concurrent idempotent requests to prevent memory exhaustion
|
|
13
|
+
this.nativeCache = new NativeMemoryCache(10000);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
this.isFallback = true;
|
|
17
|
+
}
|
|
8
18
|
}
|
|
9
19
|
async get(key) {
|
|
10
|
-
|
|
20
|
+
if (!this.isFallback) {
|
|
21
|
+
const dataStr = this.nativeCache.get(key);
|
|
22
|
+
if (!dataStr)
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(dataStr);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const item = this.fallbackCache.get(key);
|
|
11
32
|
if (!item)
|
|
12
33
|
return null;
|
|
13
34
|
if (Date.now() > item.expiry) {
|
|
14
|
-
this.
|
|
35
|
+
this.fallbackCache.delete(key);
|
|
15
36
|
return null;
|
|
16
37
|
}
|
|
17
38
|
return item.data;
|
|
18
39
|
}
|
|
19
40
|
async set(key, data, ttlMs = 86400000) {
|
|
20
|
-
this.
|
|
41
|
+
if (!this.isFallback) {
|
|
42
|
+
this.nativeCache.set(key, JSON.stringify(data), ttlMs);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
this.fallbackCache.set(key, { data, expiry: Date.now() + ttlMs });
|
|
21
46
|
}
|
|
22
47
|
}
|
|
23
48
|
exports.MemoryIdempotencyStore = MemoryIdempotencyStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ip-filter.d.ts","sourceRoot":"","sources":["../../src/middleware/ip-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAmC,MAAM,UAAU,CAAA;AAGxE,MAAM,WAAW,eAAe;IAC9B,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qFAAqF;IACrF,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAuDD,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"ip-filter.d.ts","sourceRoot":"","sources":["../../src/middleware/ip-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAmC,MAAM,UAAU,CAAA;AAGxE,MAAM,WAAW,eAAe;IAC9B,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qFAAqF;IACrF,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAuDD,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CA0CzE"}
|
|
@@ -62,8 +62,24 @@ function ipFilterMiddleware(options = {}) {
|
|
|
62
62
|
const denyRules = options.deny ?? null;
|
|
63
63
|
const message = options.message ?? 'Access Denied';
|
|
64
64
|
const trustProxy = options.trustProxy !== false; // default true
|
|
65
|
+
let nativeFilter = null;
|
|
66
|
+
let isFallback = false;
|
|
67
|
+
try {
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
69
|
+
const { NativeIpFilter } = require('@exisjs/rs');
|
|
70
|
+
nativeFilter = new NativeIpFilter(allowRules, denyRules);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
isFallback = true;
|
|
74
|
+
}
|
|
65
75
|
return (req, res, next) => {
|
|
66
76
|
const ip = resolveIp(req, trustProxy);
|
|
77
|
+
if (!isFallback && nativeFilter) {
|
|
78
|
+
if (!nativeFilter.check(ip)) {
|
|
79
|
+
return next(errors_1.HttpError.forbidden(message));
|
|
80
|
+
}
|
|
81
|
+
return next();
|
|
82
|
+
}
|
|
67
83
|
// If allowlist is defined, IP MUST match at least one rule
|
|
68
84
|
if (allowRules !== null) {
|
|
69
85
|
if (!ipMatchesAny(ip, allowRules)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ip-filter.js","sourceRoot":"","sources":["../../src/middleware/ip-filter.ts"],"names":[],"mappings":";;AAmEA,
|
|
1
|
+
{"version":3,"file":"ip-filter.js","sourceRoot":"","sources":["../../src/middleware/ip-filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA0B,OAAO,EAAE,MAAM,UAAU,CAAA;AAGxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAA;IACvC,KAAK,CAAC,EAAE,GAAG,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA0B,OAAO,EAAE,MAAM,UAAU,CAAA;AAGxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAA;IACvC,KAAK,CAAC,EAAE,GAAG,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAwFjE"}
|
|
@@ -15,17 +15,31 @@ function rateLimit(options = {}) {
|
|
|
15
15
|
// If the app is behind a reverse proxy, the user should configure the proxy settings on the app instance.
|
|
16
16
|
return req.ip || 'unknown';
|
|
17
17
|
});
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
// Initialize the native rate limiter. Fallback to a JS Map if the native module fails to load in a strange environment.
|
|
19
|
+
let nativeLimiter = null;
|
|
20
|
+
const fallbackHits = new Map();
|
|
21
|
+
try {
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
23
|
+
const { NativeRateLimiter } = require('@exisjs/rs');
|
|
24
|
+
nativeLimiter = new NativeRateLimiter(windowMs);
|
|
25
|
+
// Sweep native memory periodically via background Rust thread
|
|
26
|
+
const sweepInterval = setInterval(() => {
|
|
27
|
+
nativeLimiter.sweep();
|
|
28
|
+
}, windowMs);
|
|
29
|
+
sweepInterval.unref();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Sweep JS memory fallback
|
|
33
|
+
const sweepInterval = setInterval(() => {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
for (const [key, data] of fallbackHits.entries()) {
|
|
36
|
+
if (data.resetTime <= now) {
|
|
37
|
+
fallbackHits.delete(key);
|
|
38
|
+
}
|
|
25
39
|
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
40
|
+
}, windowMs);
|
|
41
|
+
sweepInterval.unref();
|
|
42
|
+
}
|
|
29
43
|
return async (req, res, next) => {
|
|
30
44
|
try {
|
|
31
45
|
const key = keyGenerator(req);
|
|
@@ -42,13 +56,16 @@ function rateLimit(options = {}) {
|
|
|
42
56
|
}
|
|
43
57
|
currentHits = results[0][1];
|
|
44
58
|
}
|
|
59
|
+
else if (nativeLimiter) {
|
|
60
|
+
currentHits = nativeLimiter.hit(key);
|
|
61
|
+
}
|
|
45
62
|
else {
|
|
46
|
-
let record =
|
|
63
|
+
let record = fallbackHits.get(key);
|
|
47
64
|
if (!record || record.resetTime <= now) {
|
|
48
65
|
record = { count: 0, resetTime: now + windowMs };
|
|
49
66
|
}
|
|
50
67
|
record.count += 1;
|
|
51
|
-
|
|
68
|
+
fallbackHits.set(key, record);
|
|
52
69
|
currentHits = record.count;
|
|
53
70
|
}
|
|
54
71
|
res.set('X-RateLimit-Limit', max.toString());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":";;AAaA,
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { QueueDriver, JobPayload, JobDefinition } from '../types';
|
|
2
2
|
export declare class MemoryQueueDriver implements QueueDriver {
|
|
3
|
-
private
|
|
4
|
-
private
|
|
5
|
-
private
|
|
3
|
+
private nativeQueue;
|
|
4
|
+
private fallbackPending;
|
|
5
|
+
private fallbackProcessing;
|
|
6
|
+
private fallbackDeadLetter;
|
|
7
|
+
private isFallback;
|
|
8
|
+
constructor();
|
|
6
9
|
private getList;
|
|
7
10
|
enqueue(name: string, payload: JobPayload, maxQueue?: number): Promise<string>;
|
|
8
11
|
poll(jobs: Map<string, JobDefinition>): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MemoryDriver.d.ts","sourceRoot":"","sources":["../../../src/queue/drivers/MemoryDriver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"MemoryDriver.d.ts","sourceRoot":"","sources":["../../../src/queue/drivers/MemoryDriver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAEtE,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,kBAAkB,CAA2B;IACrD,OAAO,CAAC,kBAAkB,CAA2B;IACrD,OAAO,CAAC,UAAU,CAAQ;;IAgB1B,OAAO,CAAC,OAAO;IAOT,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,UAAU,EACnB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC;IAmCZ,IAAI,CACR,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAC/B,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IA6CpE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1D,IAAI,CACR,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,UAAU,EACnB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,IAAI,CAAC;IAwDV,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BtD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
|
|
@@ -3,9 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MemoryQueueDriver = void 0;
|
|
4
4
|
class MemoryQueueDriver {
|
|
5
5
|
constructor() {
|
|
6
|
-
this.
|
|
7
|
-
this.
|
|
8
|
-
this.
|
|
6
|
+
this.fallbackPending = new Map();
|
|
7
|
+
this.fallbackProcessing = new Map();
|
|
8
|
+
this.fallbackDeadLetter = new Map();
|
|
9
|
+
this.isFallback = false;
|
|
10
|
+
try {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
12
|
+
const { NativeMemoryQueue } = require('@exisjs/rs');
|
|
13
|
+
this.nativeQueue = new NativeMemoryQueue();
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// Fallback if native module fails to load
|
|
17
|
+
this.isFallback = true;
|
|
18
|
+
this.fallbackPending = new Map();
|
|
19
|
+
this.fallbackProcessing = new Map();
|
|
20
|
+
this.fallbackDeadLetter = new Map();
|
|
21
|
+
}
|
|
9
22
|
}
|
|
10
23
|
getList(map, key) {
|
|
11
24
|
if (!map.has(key)) {
|
|
@@ -14,31 +27,50 @@ class MemoryQueueDriver {
|
|
|
14
27
|
return map.get(key);
|
|
15
28
|
}
|
|
16
29
|
async enqueue(name, payload, maxQueue) {
|
|
17
|
-
const
|
|
30
|
+
const score = Date.now() + (payload.opts?.delay || 0);
|
|
31
|
+
if (!this.isFallback) {
|
|
32
|
+
try {
|
|
33
|
+
this.nativeQueue.enqueue(name, payload.id, JSON.stringify(payload), score, maxQueue);
|
|
34
|
+
return payload.id;
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
throw new Error(err.message, { cause: err });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const pendingList = this.getList(this.fallbackPending, name);
|
|
18
41
|
if (maxQueue !== undefined && pendingList.length >= maxQueue) {
|
|
19
42
|
throw new Error(`Queue backpressure activated: maximum queue size (${maxQueue}) reached for job ${name}.`);
|
|
20
43
|
}
|
|
21
|
-
const score = Date.now() + (payload.opts?.delay || 0);
|
|
22
44
|
pendingList.push({
|
|
23
45
|
id: payload.id,
|
|
24
46
|
payloadStr: JSON.stringify(payload),
|
|
25
47
|
score,
|
|
26
48
|
});
|
|
27
|
-
// Keep it sorted by score
|
|
28
49
|
pendingList.sort((a, b) => a.score - b.score);
|
|
29
50
|
return payload.id;
|
|
30
51
|
}
|
|
31
52
|
async poll(jobs) {
|
|
53
|
+
if (!this.isFallback) {
|
|
54
|
+
const jobNames = Array.from(jobs.keys());
|
|
55
|
+
const visibilityTimeouts = jobNames.map((name) => jobs.get(name)?.defaultOptions?.visibilityTimeout ?? 30000);
|
|
56
|
+
const result = this.nativeQueue.poll(jobNames, visibilityTimeouts);
|
|
57
|
+
if (result && result.length === 3) {
|
|
58
|
+
return {
|
|
59
|
+
queueKey: result[0],
|
|
60
|
+
jobId: result[1],
|
|
61
|
+
payloadStr: result[2],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
32
66
|
const now = Date.now();
|
|
33
67
|
for (const name of jobs.keys()) {
|
|
34
|
-
const pendingList = this.getList(this.
|
|
68
|
+
const pendingList = this.getList(this.fallbackPending, name);
|
|
35
69
|
if (pendingList.length > 0 && pendingList[0].score <= now) {
|
|
36
|
-
// Pop the job
|
|
37
70
|
const job = pendingList.shift();
|
|
38
71
|
const jobDef = jobs.get(name);
|
|
39
72
|
const visibilityTimeout = jobDef?.defaultOptions?.visibilityTimeout ?? 30000;
|
|
40
|
-
|
|
41
|
-
const processingList = this.getList(this.processing, name);
|
|
73
|
+
const processingList = this.getList(this.fallbackProcessing, name);
|
|
42
74
|
processingList.push({
|
|
43
75
|
id: job.id,
|
|
44
76
|
payloadStr: job.payloadStr,
|
|
@@ -54,14 +86,29 @@ class MemoryQueueDriver {
|
|
|
54
86
|
return null;
|
|
55
87
|
}
|
|
56
88
|
async acknowledge(jobName, jobId) {
|
|
57
|
-
|
|
89
|
+
if (!this.isFallback) {
|
|
90
|
+
this.nativeQueue.acknowledge(jobName, jobId);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const processingList = this.getList(this.fallbackProcessing, jobName);
|
|
58
94
|
const index = processingList.findIndex((j) => j.id === jobId);
|
|
59
95
|
if (index !== -1) {
|
|
60
96
|
processingList.splice(index, 1);
|
|
61
97
|
}
|
|
62
98
|
}
|
|
63
99
|
async fail(jobDef, jobId, payload, maxAttempts, error) {
|
|
64
|
-
|
|
100
|
+
if (!this.isFallback) {
|
|
101
|
+
const isDeadLetter = payload.attemptsMade >= maxAttempts;
|
|
102
|
+
const delay = isDeadLetter ? 0 : (payload.opts?.backoff?.delay ?? 0);
|
|
103
|
+
this.nativeQueue.fail(jobDef.name, jobId, JSON.stringify(payload), delay, isDeadLetter);
|
|
104
|
+
if (isDeadLetter && jobDef.onJobFailedPermanently) {
|
|
105
|
+
Promise.resolve(jobDef.onJobFailedPermanently(payload, error)).catch(() => {
|
|
106
|
+
/* noop */
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const processingList = this.getList(this.fallbackProcessing, jobDef.name);
|
|
65
112
|
const index = processingList.findIndex((j) => j.id === jobId);
|
|
66
113
|
if (index !== -1) {
|
|
67
114
|
processingList.splice(index, 1);
|
|
@@ -69,7 +116,7 @@ class MemoryQueueDriver {
|
|
|
69
116
|
if (payload.attemptsMade < maxAttempts) {
|
|
70
117
|
const delay = payload.opts?.backoff?.delay ?? 0;
|
|
71
118
|
const score = Date.now() + delay;
|
|
72
|
-
const pendingList = this.getList(this.
|
|
119
|
+
const pendingList = this.getList(this.fallbackPending, jobDef.name);
|
|
73
120
|
pendingList.push({
|
|
74
121
|
id: jobId,
|
|
75
122
|
payloadStr: JSON.stringify(payload),
|
|
@@ -78,7 +125,7 @@ class MemoryQueueDriver {
|
|
|
78
125
|
pendingList.sort((a, b) => a.score - b.score);
|
|
79
126
|
}
|
|
80
127
|
else {
|
|
81
|
-
const deadLetterList = this.getList(this.
|
|
128
|
+
const deadLetterList = this.getList(this.fallbackDeadLetter, jobDef.name);
|
|
82
129
|
deadLetterList.push({
|
|
83
130
|
id: jobId,
|
|
84
131
|
payloadStr: JSON.stringify(payload),
|
|
@@ -86,23 +133,24 @@ class MemoryQueueDriver {
|
|
|
86
133
|
});
|
|
87
134
|
if (jobDef.onJobFailedPermanently) {
|
|
88
135
|
Promise.resolve(jobDef.onJobFailedPermanently(payload, error)).catch(() => {
|
|
89
|
-
/*
|
|
136
|
+
/* noop */
|
|
90
137
|
});
|
|
91
138
|
}
|
|
92
139
|
}
|
|
93
140
|
}
|
|
94
141
|
async sweep(jobs) {
|
|
142
|
+
if (!this.isFallback) {
|
|
143
|
+
this.nativeQueue.sweep(Array.from(jobs.keys()));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
95
146
|
const now = Date.now();
|
|
96
147
|
for (const name of jobs.keys()) {
|
|
97
|
-
const processingList = this.getList(this.
|
|
98
|
-
const pendingList = this.getList(this.
|
|
99
|
-
// Find expired
|
|
148
|
+
const processingList = this.getList(this.fallbackProcessing, name);
|
|
149
|
+
const pendingList = this.getList(this.fallbackPending, name);
|
|
100
150
|
const expired = processingList.filter((j) => j.score <= now);
|
|
101
151
|
if (expired.length > 0) {
|
|
102
|
-
// Remove from processing
|
|
103
152
|
const remaining = processingList.filter((j) => j.score > now);
|
|
104
|
-
this.
|
|
105
|
-
// Add back to pending
|
|
153
|
+
this.fallbackProcessing.set(name, remaining);
|
|
106
154
|
for (const job of expired) {
|
|
107
155
|
pendingList.push({
|
|
108
156
|
id: job.id,
|
|
@@ -115,8 +163,13 @@ class MemoryQueueDriver {
|
|
|
115
163
|
}
|
|
116
164
|
}
|
|
117
165
|
async close() {
|
|
118
|
-
this.
|
|
119
|
-
|
|
166
|
+
if (!this.isFallback) {
|
|
167
|
+
this.nativeQueue.close();
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
this.fallbackPending.clear();
|
|
171
|
+
this.fallbackProcessing.clear();
|
|
172
|
+
}
|
|
120
173
|
}
|
|
121
174
|
}
|
|
122
175
|
exports.MemoryQueueDriver = MemoryQueueDriver;
|