@uploadista/server 0.0.18-beta.4 → 0.0.18-beta.6
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/index.cjs +2 -2
- package/dist/index.d.cts +79 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +79 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/core/http-handlers/dlq-http-handlers.ts +177 -0
- package/src/core/http-handlers/http-handlers.ts +27 -0
- package/src/core/routes.ts +99 -0
- package/src/core/server.ts +21 -7
- package/src/core/types.ts +28 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { DeadLetterQueueService } from "@uploadista/core/flow";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import type {
|
|
4
|
+
DlqCleanupRequest,
|
|
5
|
+
DlqCleanupResponse,
|
|
6
|
+
DlqDeleteRequest,
|
|
7
|
+
DlqDeleteResponse,
|
|
8
|
+
DlqGetRequest,
|
|
9
|
+
DlqGetResponse,
|
|
10
|
+
DlqListRequest,
|
|
11
|
+
DlqListResponse,
|
|
12
|
+
DlqResolveRequest,
|
|
13
|
+
DlqResolveResponse,
|
|
14
|
+
DlqRetryAllRequest,
|
|
15
|
+
DlqRetryAllResponse,
|
|
16
|
+
DlqRetryRequest,
|
|
17
|
+
DlqRetryResponse,
|
|
18
|
+
DlqStatsRequest,
|
|
19
|
+
DlqStatsResponse,
|
|
20
|
+
} from "../routes";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Handle GET /api/dlq - List DLQ items
|
|
24
|
+
*/
|
|
25
|
+
export const handleDlqList = (req: DlqListRequest) =>
|
|
26
|
+
Effect.gen(function* () {
|
|
27
|
+
const dlq = yield* DeadLetterQueueService;
|
|
28
|
+
const result = yield* dlq.list(req.options);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
type: "dlq-list",
|
|
32
|
+
status: 200,
|
|
33
|
+
headers: { "Content-Type": "application/json" },
|
|
34
|
+
body: result,
|
|
35
|
+
} satisfies DlqListResponse;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Handle GET /api/dlq/:itemId - Get a specific DLQ item
|
|
40
|
+
*/
|
|
41
|
+
export const handleDlqGet = (req: DlqGetRequest) =>
|
|
42
|
+
Effect.gen(function* () {
|
|
43
|
+
const dlq = yield* DeadLetterQueueService;
|
|
44
|
+
const item = yield* dlq.get(req.itemId);
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
type: "dlq-get",
|
|
48
|
+
status: 200,
|
|
49
|
+
headers: { "Content-Type": "application/json" },
|
|
50
|
+
body: item,
|
|
51
|
+
} satisfies DlqGetResponse;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Handle POST /api/dlq/:itemId/retry - Retry a specific DLQ item
|
|
56
|
+
*/
|
|
57
|
+
export const handleDlqRetry = (req: DlqRetryRequest) =>
|
|
58
|
+
Effect.gen(function* () {
|
|
59
|
+
const dlq = yield* DeadLetterQueueService;
|
|
60
|
+
|
|
61
|
+
// Mark item as retrying
|
|
62
|
+
yield* dlq.markRetrying(req.itemId);
|
|
63
|
+
|
|
64
|
+
// TODO: Implement actual retry logic by re-executing the flow
|
|
65
|
+
// This would require access to FlowServer and the original job context
|
|
66
|
+
// For now, we just mark it as retrying and return success
|
|
67
|
+
// The actual retry would be handled by a background scheduler
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
type: "dlq-retry",
|
|
71
|
+
status: 200,
|
|
72
|
+
headers: { "Content-Type": "application/json" },
|
|
73
|
+
body: { success: true },
|
|
74
|
+
} satisfies DlqRetryResponse;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Handle POST /api/dlq/retry-all - Retry all matching DLQ items
|
|
79
|
+
*/
|
|
80
|
+
export const handleDlqRetryAll = (req: DlqRetryAllRequest) =>
|
|
81
|
+
Effect.gen(function* () {
|
|
82
|
+
const dlq = yield* DeadLetterQueueService;
|
|
83
|
+
|
|
84
|
+
// List items matching the filter
|
|
85
|
+
const { items } = yield* dlq.list({
|
|
86
|
+
status: req.options?.status,
|
|
87
|
+
flowId: req.options?.flowId,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
let succeeded = 0;
|
|
91
|
+
let failed = 0;
|
|
92
|
+
|
|
93
|
+
// Mark each item for retry
|
|
94
|
+
for (const item of items) {
|
|
95
|
+
const result = yield* Effect.either(dlq.markRetrying(item.id));
|
|
96
|
+
if (result._tag === "Right") {
|
|
97
|
+
succeeded++;
|
|
98
|
+
} else {
|
|
99
|
+
failed++;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
type: "dlq-retry-all",
|
|
105
|
+
status: 200,
|
|
106
|
+
headers: { "Content-Type": "application/json" },
|
|
107
|
+
body: {
|
|
108
|
+
retried: items.length,
|
|
109
|
+
succeeded,
|
|
110
|
+
failed,
|
|
111
|
+
},
|
|
112
|
+
} satisfies DlqRetryAllResponse;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Handle DELETE /api/dlq/:itemId - Delete a DLQ item
|
|
117
|
+
*/
|
|
118
|
+
export const handleDlqDelete = (req: DlqDeleteRequest) =>
|
|
119
|
+
Effect.gen(function* () {
|
|
120
|
+
const dlq = yield* DeadLetterQueueService;
|
|
121
|
+
yield* dlq.delete(req.itemId);
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
type: "dlq-delete",
|
|
125
|
+
status: 200,
|
|
126
|
+
headers: { "Content-Type": "application/json" },
|
|
127
|
+
body: { success: true },
|
|
128
|
+
} satisfies DlqDeleteResponse;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Handle POST /api/dlq/:itemId/resolve - Manually resolve a DLQ item
|
|
133
|
+
*/
|
|
134
|
+
export const handleDlqResolve = (req: DlqResolveRequest) =>
|
|
135
|
+
Effect.gen(function* () {
|
|
136
|
+
const dlq = yield* DeadLetterQueueService;
|
|
137
|
+
const item = yield* dlq.markResolved(req.itemId);
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
type: "dlq-resolve",
|
|
141
|
+
status: 200,
|
|
142
|
+
headers: { "Content-Type": "application/json" },
|
|
143
|
+
body: item,
|
|
144
|
+
} satisfies DlqResolveResponse;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Handle POST /api/dlq/cleanup - Cleanup old DLQ items
|
|
149
|
+
*/
|
|
150
|
+
export const handleDlqCleanup = (req: DlqCleanupRequest) =>
|
|
151
|
+
Effect.gen(function* () {
|
|
152
|
+
const dlq = yield* DeadLetterQueueService;
|
|
153
|
+
const result = yield* dlq.cleanup(req.options);
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
type: "dlq-cleanup",
|
|
157
|
+
status: 200,
|
|
158
|
+
headers: { "Content-Type": "application/json" },
|
|
159
|
+
body: result,
|
|
160
|
+
} satisfies DlqCleanupResponse;
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Handle GET /api/dlq/stats - Get DLQ statistics
|
|
165
|
+
*/
|
|
166
|
+
export const handleDlqStats = (_req: DlqStatsRequest) =>
|
|
167
|
+
Effect.gen(function* () {
|
|
168
|
+
const dlq = yield* DeadLetterQueueService;
|
|
169
|
+
const stats = yield* dlq.getStats();
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
type: "dlq-stats",
|
|
173
|
+
status: 200,
|
|
174
|
+
headers: { "Content-Type": "application/json" },
|
|
175
|
+
body: stats,
|
|
176
|
+
} satisfies DlqStatsResponse;
|
|
177
|
+
});
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import type { UploadistaRequest, UploadistaResponse } from "../routes";
|
|
3
|
+
import {
|
|
4
|
+
handleDlqCleanup,
|
|
5
|
+
handleDlqDelete,
|
|
6
|
+
handleDlqGet,
|
|
7
|
+
handleDlqList,
|
|
8
|
+
handleDlqResolve,
|
|
9
|
+
handleDlqRetry,
|
|
10
|
+
handleDlqRetryAll,
|
|
11
|
+
handleDlqStats,
|
|
12
|
+
} from "./dlq-http-handlers";
|
|
3
13
|
import {
|
|
4
14
|
handleCancelFlow,
|
|
5
15
|
handleGetFlow,
|
|
@@ -44,6 +54,23 @@ export const handleUploadistaRequest = <TRequirements>(
|
|
|
44
54
|
return (yield* handlePauseFlow(req)) as UploadistaResponse;
|
|
45
55
|
case "cancel-flow":
|
|
46
56
|
return (yield* handleCancelFlow(req)) as UploadistaResponse;
|
|
57
|
+
// DLQ Admin routes
|
|
58
|
+
case "dlq-list":
|
|
59
|
+
return (yield* handleDlqList(req)) as UploadistaResponse;
|
|
60
|
+
case "dlq-get":
|
|
61
|
+
return (yield* handleDlqGet(req)) as UploadistaResponse;
|
|
62
|
+
case "dlq-retry":
|
|
63
|
+
return (yield* handleDlqRetry(req)) as UploadistaResponse;
|
|
64
|
+
case "dlq-retry-all":
|
|
65
|
+
return (yield* handleDlqRetryAll(req)) as UploadistaResponse;
|
|
66
|
+
case "dlq-delete":
|
|
67
|
+
return (yield* handleDlqDelete(req)) as UploadistaResponse;
|
|
68
|
+
case "dlq-resolve":
|
|
69
|
+
return (yield* handleDlqResolve(req)) as UploadistaResponse;
|
|
70
|
+
case "dlq-cleanup":
|
|
71
|
+
return (yield* handleDlqCleanup(req)) as UploadistaResponse;
|
|
72
|
+
case "dlq-stats":
|
|
73
|
+
return (yield* handleDlqStats(req)) as UploadistaResponse;
|
|
47
74
|
case "not-found":
|
|
48
75
|
return {
|
|
49
76
|
status: 404,
|
package/src/core/routes.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
DataStoreCapabilities,
|
|
3
|
+
DeadLetterCleanupOptions,
|
|
4
|
+
DeadLetterCleanupResult,
|
|
5
|
+
DeadLetterItem,
|
|
6
|
+
DeadLetterItemStatus,
|
|
7
|
+
DeadLetterListOptions,
|
|
8
|
+
DeadLetterQueueStats,
|
|
3
9
|
FlowData,
|
|
4
10
|
FlowJob,
|
|
5
11
|
UploadFile,
|
|
@@ -17,6 +23,16 @@ export type UploadistaRouteType =
|
|
|
17
23
|
| "resume-flow"
|
|
18
24
|
| "pause-flow"
|
|
19
25
|
| "cancel-flow"
|
|
26
|
+
// DLQ Admin routes
|
|
27
|
+
| "dlq-list"
|
|
28
|
+
| "dlq-get"
|
|
29
|
+
| "dlq-retry"
|
|
30
|
+
| "dlq-retry-all"
|
|
31
|
+
| "dlq-delete"
|
|
32
|
+
| "dlq-resolve"
|
|
33
|
+
| "dlq-cleanup"
|
|
34
|
+
| "dlq-stats"
|
|
35
|
+
// Error routes
|
|
20
36
|
| "not-found"
|
|
21
37
|
| "bad-request"
|
|
22
38
|
| "method-not-allowed"
|
|
@@ -154,6 +170,69 @@ export type CancelFlowResponse = UploadistaStandardResponse<
|
|
|
154
170
|
FlowJob
|
|
155
171
|
>;
|
|
156
172
|
|
|
173
|
+
// ============================================================================
|
|
174
|
+
// Dead Letter Queue Admin Routes
|
|
175
|
+
// ============================================================================
|
|
176
|
+
|
|
177
|
+
export type DlqListRequest = UploadistaRoute<"dlq-list"> & {
|
|
178
|
+
options?: DeadLetterListOptions;
|
|
179
|
+
};
|
|
180
|
+
export type DlqListResponse = UploadistaStandardResponse<
|
|
181
|
+
"dlq-list",
|
|
182
|
+
{ items: DeadLetterItem[]; total: number }
|
|
183
|
+
>;
|
|
184
|
+
|
|
185
|
+
export type DlqGetRequest = UploadistaRoute<"dlq-get"> & {
|
|
186
|
+
itemId: string;
|
|
187
|
+
};
|
|
188
|
+
export type DlqGetResponse = UploadistaStandardResponse<"dlq-get", DeadLetterItem>;
|
|
189
|
+
|
|
190
|
+
export type DlqRetryRequest = UploadistaRoute<"dlq-retry"> & {
|
|
191
|
+
itemId: string;
|
|
192
|
+
};
|
|
193
|
+
export type DlqRetryResponse = UploadistaStandardResponse<
|
|
194
|
+
"dlq-retry",
|
|
195
|
+
{ success: boolean; newJobId?: string }
|
|
196
|
+
>;
|
|
197
|
+
|
|
198
|
+
export type DlqRetryAllRequest = UploadistaRoute<"dlq-retry-all"> & {
|
|
199
|
+
options?: { status?: DeadLetterItemStatus; flowId?: string };
|
|
200
|
+
};
|
|
201
|
+
export type DlqRetryAllResponse = UploadistaStandardResponse<
|
|
202
|
+
"dlq-retry-all",
|
|
203
|
+
{ retried: number; succeeded: number; failed: number }
|
|
204
|
+
>;
|
|
205
|
+
|
|
206
|
+
export type DlqDeleteRequest = UploadistaRoute<"dlq-delete"> & {
|
|
207
|
+
itemId: string;
|
|
208
|
+
};
|
|
209
|
+
export type DlqDeleteResponse = UploadistaStandardResponse<
|
|
210
|
+
"dlq-delete",
|
|
211
|
+
{ success: boolean }
|
|
212
|
+
>;
|
|
213
|
+
|
|
214
|
+
export type DlqResolveRequest = UploadistaRoute<"dlq-resolve"> & {
|
|
215
|
+
itemId: string;
|
|
216
|
+
};
|
|
217
|
+
export type DlqResolveResponse = UploadistaStandardResponse<
|
|
218
|
+
"dlq-resolve",
|
|
219
|
+
DeadLetterItem
|
|
220
|
+
>;
|
|
221
|
+
|
|
222
|
+
export type DlqCleanupRequest = UploadistaRoute<"dlq-cleanup"> & {
|
|
223
|
+
options?: DeadLetterCleanupOptions;
|
|
224
|
+
};
|
|
225
|
+
export type DlqCleanupResponse = UploadistaStandardResponse<
|
|
226
|
+
"dlq-cleanup",
|
|
227
|
+
DeadLetterCleanupResult
|
|
228
|
+
>;
|
|
229
|
+
|
|
230
|
+
export type DlqStatsRequest = UploadistaRoute<"dlq-stats">;
|
|
231
|
+
export type DlqStatsResponse = UploadistaStandardResponse<
|
|
232
|
+
"dlq-stats",
|
|
233
|
+
DeadLetterQueueStats
|
|
234
|
+
>;
|
|
235
|
+
|
|
157
236
|
export type UploadistaRequest =
|
|
158
237
|
| CreateUploadRequest
|
|
159
238
|
| GetCapabilitiesRequest
|
|
@@ -165,6 +244,16 @@ export type UploadistaRequest =
|
|
|
165
244
|
| ResumeFlowRequest
|
|
166
245
|
| PauseFlowRequest
|
|
167
246
|
| CancelFlowRequest
|
|
247
|
+
// DLQ Admin requests
|
|
248
|
+
| DlqListRequest
|
|
249
|
+
| DlqGetRequest
|
|
250
|
+
| DlqRetryRequest
|
|
251
|
+
| DlqRetryAllRequest
|
|
252
|
+
| DlqDeleteRequest
|
|
253
|
+
| DlqResolveRequest
|
|
254
|
+
| DlqCleanupRequest
|
|
255
|
+
| DlqStatsRequest
|
|
256
|
+
// Error requests
|
|
168
257
|
| NotFoundRequest
|
|
169
258
|
| BadRequestRequest
|
|
170
259
|
| MethodNotAllowedRequest
|
|
@@ -181,6 +270,16 @@ export type UploadistaResponse =
|
|
|
181
270
|
| ResumeFlowResponse
|
|
182
271
|
| PauseFlowResponse
|
|
183
272
|
| CancelFlowResponse
|
|
273
|
+
// DLQ Admin responses
|
|
274
|
+
| DlqListResponse
|
|
275
|
+
| DlqGetResponse
|
|
276
|
+
| DlqRetryResponse
|
|
277
|
+
| DlqRetryAllResponse
|
|
278
|
+
| DlqDeleteResponse
|
|
279
|
+
| DlqResolveResponse
|
|
280
|
+
| DlqCleanupResponse
|
|
281
|
+
| DlqStatsResponse
|
|
282
|
+
// Error responses
|
|
184
283
|
| NotFoundResponse
|
|
185
284
|
| BadRequestResponse
|
|
186
285
|
| MethodNotAllowedResponse
|
package/src/core/server.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PluginLayer, UploadistaError } from "@uploadista/core";
|
|
2
2
|
import {
|
|
3
|
+
deadLetterQueueService,
|
|
3
4
|
type Flow,
|
|
4
5
|
FlowProvider,
|
|
5
6
|
FlowWaitUntil,
|
|
@@ -7,6 +8,7 @@ import {
|
|
|
7
8
|
} from "@uploadista/core/flow";
|
|
8
9
|
import {
|
|
9
10
|
createDataStoreLayer,
|
|
11
|
+
deadLetterQueueKvStore,
|
|
10
12
|
type UploadFileDataStores,
|
|
11
13
|
type UploadFileKVStore,
|
|
12
14
|
} from "@uploadista/core/types";
|
|
@@ -197,6 +199,7 @@ export const createUploadistaServer = async <
|
|
|
197
199
|
adapter,
|
|
198
200
|
authCacheConfig,
|
|
199
201
|
circuitBreaker = true,
|
|
202
|
+
deadLetterQueue = false,
|
|
200
203
|
}: UploadistaServerConfig<
|
|
201
204
|
TContext,
|
|
202
205
|
TResponse,
|
|
@@ -272,22 +275,30 @@ export const createUploadistaServer = async <
|
|
|
272
275
|
? kvCircuitBreakerStoreLayer.pipe(Layer.provide(kvStore))
|
|
273
276
|
: null;
|
|
274
277
|
|
|
278
|
+
// Create dead letter queue layer if enabled (uses the provided kvStore)
|
|
279
|
+
// The DLQ layer provides both the KV store wrapper and the service
|
|
280
|
+
const dlqLayer = deadLetterQueue
|
|
281
|
+
? deadLetterQueueService.pipe(
|
|
282
|
+
Layer.provide(deadLetterQueueKvStore),
|
|
283
|
+
Layer.provide(kvStore),
|
|
284
|
+
)
|
|
285
|
+
: null;
|
|
286
|
+
|
|
275
287
|
/**
|
|
276
288
|
* Merge all server layers including plugins.
|
|
277
289
|
*
|
|
278
290
|
* This combines the core server infrastructure (upload server, flow server,
|
|
279
|
-
* metrics, auth cache, circuit breaker) with user-provided plugin layers.
|
|
291
|
+
* metrics, auth cache, circuit breaker, dead letter queue) with user-provided plugin layers.
|
|
280
292
|
*/
|
|
281
|
-
const
|
|
293
|
+
const serverLayerRaw = Layer.mergeAll(
|
|
282
294
|
uploadServerLayer,
|
|
283
295
|
flowServerLayer,
|
|
284
296
|
effectiveMetricsLayer,
|
|
285
297
|
authCacheLayer,
|
|
286
298
|
...plugins,
|
|
299
|
+
...(circuitBreakerStoreLayer ? [circuitBreakerStoreLayer] : []),
|
|
300
|
+
...(dlqLayer ? [dlqLayer] : []),
|
|
287
301
|
);
|
|
288
|
-
const serverLayerRaw = circuitBreakerStoreLayer
|
|
289
|
-
? Layer.merge(baseServerLayer, circuitBreakerStoreLayer)
|
|
290
|
-
: baseServerLayer;
|
|
291
302
|
|
|
292
303
|
/**
|
|
293
304
|
* Type Casting Rationale for Plugin System
|
|
@@ -485,7 +496,7 @@ export const createUploadistaServer = async <
|
|
|
485
496
|
}
|
|
486
497
|
}
|
|
487
498
|
|
|
488
|
-
// Combine auth context, auth cache, metrics layers, plugins, circuit breaker, and waitUntil
|
|
499
|
+
// Combine auth context, auth cache, metrics layers, plugins, circuit breaker, DLQ, and waitUntil
|
|
489
500
|
// This ensures that flow nodes have access to all required services
|
|
490
501
|
const baseRequestContextLayer = Layer.mergeAll(
|
|
491
502
|
authContextLayer,
|
|
@@ -494,9 +505,12 @@ export const createUploadistaServer = async <
|
|
|
494
505
|
...plugins,
|
|
495
506
|
...waitUntilLayers,
|
|
496
507
|
);
|
|
497
|
-
const
|
|
508
|
+
const withCircuitBreakerContext = circuitBreakerStoreLayer
|
|
498
509
|
? Layer.merge(baseRequestContextLayer, circuitBreakerStoreLayer)
|
|
499
510
|
: baseRequestContextLayer;
|
|
511
|
+
const requestContextLayer = dlqLayer
|
|
512
|
+
? Layer.merge(withCircuitBreakerContext, dlqLayer)
|
|
513
|
+
: withCircuitBreakerContext;
|
|
500
514
|
|
|
501
515
|
// Check for baseUrl/api/ prefix
|
|
502
516
|
if (uploadistaRequest.type === "not-found") {
|
package/src/core/types.ts
CHANGED
|
@@ -323,6 +323,34 @@ export interface UploadistaServerConfig<
|
|
|
323
323
|
* ```
|
|
324
324
|
*/
|
|
325
325
|
circuitBreaker?: boolean;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Optional: Enable dead letter queue for failed flow jobs.
|
|
329
|
+
*
|
|
330
|
+
* When enabled, failed flow jobs are captured in a DLQ with full context
|
|
331
|
+
* for debugging and retry. The DLQ state is stored in the KV store,
|
|
332
|
+
* allowing it to be shared across multiple server instances.
|
|
333
|
+
*
|
|
334
|
+
* Set to `false` to disable the DLQ entirely.
|
|
335
|
+
*
|
|
336
|
+
* @default false
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```typescript
|
|
340
|
+
* // Enable DLQ (uses the provided kvStore)
|
|
341
|
+
* const server = await createUploadistaServer({
|
|
342
|
+
* kvStore: redisKvStore,
|
|
343
|
+
* deadLetterQueue: true
|
|
344
|
+
* });
|
|
345
|
+
*
|
|
346
|
+
* // DLQ is disabled by default
|
|
347
|
+
* const server = await createUploadistaServer({
|
|
348
|
+
* kvStore: redisKvStore,
|
|
349
|
+
* // deadLetterQueue: false (default)
|
|
350
|
+
* });
|
|
351
|
+
* ```
|
|
352
|
+
*/
|
|
353
|
+
deadLetterQueue?: boolean;
|
|
326
354
|
}
|
|
327
355
|
|
|
328
356
|
/**
|