n8n-nodes-resilience 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +142 -0
- package/dist/nodes/ConcurrencyGate/ConcurrencyGate.node.d.ts +6 -0
- package/dist/nodes/ConcurrencyGate/ConcurrencyGate.node.d.ts.map +1 -0
- package/dist/nodes/ConcurrencyGate/ConcurrencyGate.node.js +268 -0
- package/dist/nodes/ConcurrencyGate/ConcurrencyGate.node.js.map +1 -0
- package/dist/nodes/ConcurrencyGate/concurrencyGate.svg +6 -0
- package/dist/nodes/DeadLetterQueue/DeadLetterQueue.node.d.ts +6 -0
- package/dist/nodes/DeadLetterQueue/DeadLetterQueue.node.d.ts.map +1 -0
- package/dist/nodes/DeadLetterQueue/DeadLetterQueue.node.js +175 -0
- package/dist/nodes/DeadLetterQueue/DeadLetterQueue.node.js.map +1 -0
- package/dist/nodes/DeadLetterQueue/deadLetterQueue.svg +6 -0
- package/dist/nodes/RetryStrategy/RetryStrategy.node.d.ts +6 -0
- package/dist/nodes/RetryStrategy/RetryStrategy.node.d.ts.map +1 -0
- package/dist/nodes/RetryStrategy/RetryStrategy.node.js +255 -0
- package/dist/nodes/RetryStrategy/RetryStrategy.node.js.map +1 -0
- package/dist/nodes/RetryStrategy/retryStrategy.svg +6 -0
- package/dist/nodes/shared/fieldPath.d.ts +6 -0
- package/dist/nodes/shared/fieldPath.d.ts.map +1 -0
- package/dist/nodes/shared/fieldPath.js +44 -0
- package/dist/nodes/shared/fieldPath.js.map +1 -0
- package/dist/nodes/shared/retry.d.ts +3 -0
- package/dist/nodes/shared/retry.d.ts.map +1 -0
- package/dist/nodes/shared/retry.js +23 -0
- package/dist/nodes/shared/retry.js.map +1 -0
- package/dist/nodes/shared/staticData.d.ts +14 -0
- package/dist/nodes/shared/staticData.d.ts.map +1 -0
- package/dist/nodes/shared/staticData.js +31 -0
- package/dist/nodes/shared/staticData.js.map +1 -0
- package/dist/nodes/shared/utils.d.ts +11 -0
- package/dist/nodes/shared/utils.d.ts.map +1 -0
- package/dist/nodes/shared/utils.js +69 -0
- package/dist/nodes/shared/utils.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Taiwo Hassan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# n8n-nodes-resilience
|
|
2
|
+
|
|
3
|
+
Production-grade resilience utilities for n8n workflows.
|
|
4
|
+
|
|
5
|
+
This community node package helps workflow builders make unreliable integrations easier to manage. The nodes inspect incoming item data, add structured metadata, and route items so the rest of the workflow can handle retries, circuit breaking, concurrency limits, and dead-letter handling with regular n8n nodes.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Follow the [n8n community node installation guide](https://docs.n8n.io/integrations/community-nodes/installation/), or install the package directly:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install n8n-nodes-resilience
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Nodes
|
|
16
|
+
|
|
17
|
+
- **Retry Strategy**: Decide whether an item should continue, retry, or go to an exhausted failure path.
|
|
18
|
+
- **Concurrency Gate**: Limit how many executions/items can enter a protected section at once.
|
|
19
|
+
- **Dead Letter Queue**: Wrap failed items in a clean dead-letter payload for storage or replay.
|
|
20
|
+
|
|
21
|
+
## Retry Strategy
|
|
22
|
+
|
|
23
|
+
Use this node after a risky operation such as an HTTP Request node.
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
HTTP Request
|
|
27
|
+
-> Retry Strategy
|
|
28
|
+
-> output 1 Success / Continue
|
|
29
|
+
-> output 2 Retry -> Wait -> loop back to HTTP Request
|
|
30
|
+
-> output 3 Exhausted -> Dead Letter Queue
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The Retry Strategy node does not sleep internally. It calculates `__retry.delaySeconds` and routes the item. Use an n8n Wait node on the Retry output to perform the actual delay before looping back to the risky operation.
|
|
34
|
+
|
|
35
|
+
Metadata added to each item:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"__retry": {
|
|
40
|
+
"shouldRetry": true,
|
|
41
|
+
"attempt": 1,
|
|
42
|
+
"maxAttempts": 3,
|
|
43
|
+
"strategy": "exponential",
|
|
44
|
+
"delaySeconds": 5,
|
|
45
|
+
"reason": "Status code 503 is retryable",
|
|
46
|
+
"exhausted": false
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Default retryable status codes are `408,429,500,502,503,504`. Default permanent stop codes are `400,401,403,404`.
|
|
52
|
+
|
|
53
|
+
## Concurrency Gate
|
|
54
|
+
|
|
55
|
+
Use Concurrency Gate to protect a section that should only have a limited number of active items/executions.
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
Concurrency Gate (Acquire)
|
|
59
|
+
-> Acquired / Allowed -> protected work
|
|
60
|
+
-> Blocked -> wait, retry, or skip
|
|
61
|
+
|
|
62
|
+
protected work -> Concurrency Gate (Release)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Acquire creates a lock with a TTL and outputs `__concurrencyGate.lockId`. Release can use that lock ID from `__concurrencyGate.lockId`, or an explicit Lock ID parameter.
|
|
66
|
+
|
|
67
|
+
Important limitation: Concurrency Gate v1 uses n8n workflow static data as a best-effort lock store. It is useful for simple local and single-worker setups, but it is not a perfect distributed lock in all multi-worker, queue-mode, or horizontally scaled deployments. For strict distributed concurrency, use an external lock service or database-backed workflow design.
|
|
68
|
+
|
|
69
|
+
Metadata added to each item:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"__concurrencyGate": {
|
|
74
|
+
"key": "customer-123",
|
|
75
|
+
"acquired": true,
|
|
76
|
+
"activeCount": 1,
|
|
77
|
+
"maxConcurrent": 1,
|
|
78
|
+
"reason": "Lock acquired",
|
|
79
|
+
"lockId": "lock_mabc1234_abcd5678",
|
|
80
|
+
"expiresAt": "2026-05-24T12:00:00.000Z"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Dead Letter Queue
|
|
86
|
+
|
|
87
|
+
Use Dead Letter Queue at permanent failure paths, especially after Retry Strategy's Exhausted output.
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
Retry Strategy (Exhausted)
|
|
91
|
+
-> Dead Letter Queue
|
|
92
|
+
-> Google Sheets / Postgres / Slack / Notion / S3 / Webhook / database node
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The v1 operation is **Format Failed Item** and the destination mode is Output Only. This is intentional: the node formats a durable dead-letter item, and users can connect any regular n8n destination node for storage, notification, or replay.
|
|
96
|
+
|
|
97
|
+
Example output:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"deadLetterId": "dlq_mabc1234_abcd5678",
|
|
102
|
+
"timestamp": "2026-05-24T12:00:00.000Z",
|
|
103
|
+
"reason": "Request failed",
|
|
104
|
+
"sourceNode": "Dead Letter Queue",
|
|
105
|
+
"workflowId": "workflow-id",
|
|
106
|
+
"workflowName": "Production workflow",
|
|
107
|
+
"executionId": "12345",
|
|
108
|
+
"originalPayload": {},
|
|
109
|
+
"error": {},
|
|
110
|
+
"retry": {}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Example Workflows
|
|
115
|
+
|
|
116
|
+
### HTTP Retry With Dead Letter
|
|
117
|
+
|
|
118
|
+
1. HTTP Request calls an external API.
|
|
119
|
+
2. Retry Strategy checks `statusCode` and `message`.
|
|
120
|
+
3. Retry output goes to Wait using `{{$json.__retry.delaySeconds}}`.
|
|
121
|
+
4. Wait loops back to HTTP Request.
|
|
122
|
+
5. Exhausted output goes to Dead Letter Queue.
|
|
123
|
+
6. Dead Letter Queue connects to a storage or alerting node.
|
|
124
|
+
|
|
125
|
+
### Concurrency-Limited Section
|
|
126
|
+
|
|
127
|
+
1. Concurrency Gate Acquire uses key `={{$json.customerId}}`.
|
|
128
|
+
2. Acquired output does the protected work.
|
|
129
|
+
3. The final node releases `{{$json.__concurrencyGate.lockId}}`.
|
|
130
|
+
4. Blocked output waits, retries, or skips based on workflow needs.
|
|
131
|
+
|
|
132
|
+
## Development
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
npm install
|
|
136
|
+
npm run build
|
|
137
|
+
npm run lint
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from "n8n-workflow";
|
|
2
|
+
export declare class ConcurrencyGate implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=ConcurrencyGate.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConcurrencyGate.node.d.ts","sourceRoot":"","sources":["../../../nodes/ConcurrencyGate/ConcurrencyGate.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAGrB,MAAM,cAAc,CAAC;AAmBtB,qBAAa,eAAgB,YAAW,SAAS;IAC/C,WAAW,EAAE,oBAAoB,CAmK/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAyIxE"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConcurrencyGate = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const fieldPath_1 = require("../shared/fieldPath");
|
|
6
|
+
const staticData_1 = require("../shared/staticData");
|
|
7
|
+
const utils_1 = require("../shared/utils");
|
|
8
|
+
class ConcurrencyGate {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.description = {
|
|
11
|
+
displayName: "Concurrency Gate",
|
|
12
|
+
name: "concurrencyGate",
|
|
13
|
+
icon: "file:concurrencyGate.svg",
|
|
14
|
+
group: ["transform"],
|
|
15
|
+
version: 1,
|
|
16
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
17
|
+
description: "Best-effort static-data concurrency gate for workflow sections",
|
|
18
|
+
defaults: {
|
|
19
|
+
name: "Concurrency Gate",
|
|
20
|
+
},
|
|
21
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
22
|
+
outputs: [
|
|
23
|
+
{
|
|
24
|
+
type: n8n_workflow_1.NodeConnectionTypes.Main,
|
|
25
|
+
displayName: "Acquired / Allowed",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: n8n_workflow_1.NodeConnectionTypes.Main,
|
|
29
|
+
displayName: "Blocked",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
usableAsTool: true,
|
|
33
|
+
outputNames: ["Acquired / Allowed", "Blocked"],
|
|
34
|
+
properties: [
|
|
35
|
+
{
|
|
36
|
+
displayName: "Operation",
|
|
37
|
+
name: "operation",
|
|
38
|
+
type: "options",
|
|
39
|
+
noDataExpression: true,
|
|
40
|
+
options: [
|
|
41
|
+
{
|
|
42
|
+
name: "Acquire",
|
|
43
|
+
value: "acquire",
|
|
44
|
+
description: "Try to acquire a lock for this gate key",
|
|
45
|
+
action: "Acquire concurrency lock",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "Force Release",
|
|
49
|
+
value: "forceRelease",
|
|
50
|
+
description: "Clear all active locks for this gate key",
|
|
51
|
+
action: "Force release concurrency locks",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "Inspect",
|
|
55
|
+
value: "inspect",
|
|
56
|
+
description: "Return current lock metadata for this gate key",
|
|
57
|
+
action: "Inspect concurrency gate",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "Release",
|
|
61
|
+
value: "release",
|
|
62
|
+
description: "Release a previously acquired lock",
|
|
63
|
+
action: "Release concurrency lock",
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
default: "acquire",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
displayName: "Gate Key",
|
|
70
|
+
name: "gateKey",
|
|
71
|
+
type: "string",
|
|
72
|
+
required: true,
|
|
73
|
+
default: "",
|
|
74
|
+
placeholder: "={{$json.customerId || 'global'}}",
|
|
75
|
+
description: "Unique key for the protected workflow section, such as a customer ID or external service name",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
displayName: "Max Concurrent",
|
|
79
|
+
name: "maxConcurrent",
|
|
80
|
+
type: "number",
|
|
81
|
+
typeOptions: {
|
|
82
|
+
minValue: 1,
|
|
83
|
+
},
|
|
84
|
+
displayOptions: {
|
|
85
|
+
show: {
|
|
86
|
+
operation: ["acquire", "inspect"],
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
default: 1,
|
|
90
|
+
description: "Maximum active locks allowed for this gate key",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
displayName: "Lock TTL Seconds",
|
|
94
|
+
name: "lockTtlSeconds",
|
|
95
|
+
type: "number",
|
|
96
|
+
typeOptions: {
|
|
97
|
+
minValue: 1,
|
|
98
|
+
},
|
|
99
|
+
displayOptions: {
|
|
100
|
+
show: {
|
|
101
|
+
operation: ["acquire", "inspect"],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
default: 300,
|
|
105
|
+
description: "How long an acquired lock remains active if not released",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
displayName: "On Limit Reached",
|
|
109
|
+
name: "onLimitReached",
|
|
110
|
+
type: "options",
|
|
111
|
+
noDataExpression: true,
|
|
112
|
+
displayOptions: {
|
|
113
|
+
show: {
|
|
114
|
+
operation: ["acquire"],
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
options: [
|
|
118
|
+
{
|
|
119
|
+
name: "Allow With Metadata Only",
|
|
120
|
+
value: "allowWithMetadata",
|
|
121
|
+
description: "Allow items through but mark that the lock was not acquired",
|
|
122
|
+
action: "Allow without acquiring",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "Route to Blocked Output",
|
|
126
|
+
value: "routeBlocked",
|
|
127
|
+
description: "Send items over the blocked output when the gate is full",
|
|
128
|
+
action: "Route blocked items",
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
default: "routeBlocked",
|
|
132
|
+
description: "What to do when the active lock count is at the limit",
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
displayName: "Lock ID Field",
|
|
136
|
+
name: "lockIdField",
|
|
137
|
+
type: "string",
|
|
138
|
+
displayOptions: {
|
|
139
|
+
show: {
|
|
140
|
+
operation: ["release"],
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
default: "__concurrencyGate.lockId",
|
|
144
|
+
description: "Dot path containing the lock ID to release. Leave blank to use the metadata lock ID.",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
displayName: "Lock ID",
|
|
148
|
+
name: "lockId",
|
|
149
|
+
type: "string",
|
|
150
|
+
displayOptions: {
|
|
151
|
+
show: {
|
|
152
|
+
operation: ["release"],
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
default: "",
|
|
156
|
+
description: "Optional explicit lock ID to release. Takes precedence over Lock ID Field.",
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
displayName: "Preserve Original Item",
|
|
160
|
+
name: "preserveOriginalItem",
|
|
161
|
+
type: "boolean",
|
|
162
|
+
default: true,
|
|
163
|
+
description: "Whether to keep the incoming JSON and binary data when adding gate metadata",
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async execute() {
|
|
169
|
+
const items = this.getInputData();
|
|
170
|
+
const allowedItems = [];
|
|
171
|
+
const blockedItems = [];
|
|
172
|
+
const states = (0, staticData_1.getConcurrencyStates)(this);
|
|
173
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
174
|
+
try {
|
|
175
|
+
const item = items[itemIndex];
|
|
176
|
+
const operation = this.getNodeParameter("operation", itemIndex);
|
|
177
|
+
const key = this.getNodeParameter("gateKey", itemIndex).trim();
|
|
178
|
+
const preserveOriginalItem = this.getNodeParameter("preserveOriginalItem", itemIndex);
|
|
179
|
+
const now = Date.now();
|
|
180
|
+
const state = (0, staticData_1.getConcurrencyState)(states, key);
|
|
181
|
+
(0, staticData_1.cleanExpiredLocks)(state, now);
|
|
182
|
+
let acquired = false;
|
|
183
|
+
let routeBlocked = false;
|
|
184
|
+
let lockId;
|
|
185
|
+
let expiresAt;
|
|
186
|
+
let reason = "Gate inspected";
|
|
187
|
+
const maxConcurrent = operation === "release" || operation === "forceRelease"
|
|
188
|
+
? 1
|
|
189
|
+
: Math.max(1, this.getNodeParameter("maxConcurrent", itemIndex));
|
|
190
|
+
if (operation === "acquire") {
|
|
191
|
+
const lockTtlSeconds = Math.max(1, this.getNodeParameter("lockTtlSeconds", itemIndex));
|
|
192
|
+
const onLimitReached = this.getNodeParameter("onLimitReached", itemIndex);
|
|
193
|
+
if (state.locks.length < maxConcurrent) {
|
|
194
|
+
lockId = (0, utils_1.generateId)("lock");
|
|
195
|
+
expiresAt = (0, utils_1.isoFromTimestamp)(now + lockTtlSeconds * 1000);
|
|
196
|
+
const lock = {
|
|
197
|
+
id: lockId,
|
|
198
|
+
createdAt: (0, utils_1.isoFromTimestamp)(now),
|
|
199
|
+
expiresAt,
|
|
200
|
+
executionId: this.getExecutionId(),
|
|
201
|
+
};
|
|
202
|
+
state.locks.push(lock);
|
|
203
|
+
acquired = true;
|
|
204
|
+
reason = "Lock acquired";
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
reason = "Concurrency limit reached";
|
|
208
|
+
routeBlocked = onLimitReached === "routeBlocked";
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (operation === "release") {
|
|
212
|
+
const explicitLockId = this.getNodeParameter("lockId", itemIndex).trim();
|
|
213
|
+
const lockIdField = this.getNodeParameter("lockIdField", itemIndex).trim();
|
|
214
|
+
const fieldLockId = lockIdField
|
|
215
|
+
? (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, lockIdField))
|
|
216
|
+
: undefined;
|
|
217
|
+
lockId = explicitLockId || fieldLockId;
|
|
218
|
+
if (lockId) {
|
|
219
|
+
const beforeCount = state.locks.length;
|
|
220
|
+
state.locks = state.locks.filter((lock) => lock.id !== lockId);
|
|
221
|
+
reason =
|
|
222
|
+
state.locks.length < beforeCount
|
|
223
|
+
? "Lock released"
|
|
224
|
+
: "Lock ID was not active";
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
reason = "No lock ID provided";
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (operation === "forceRelease") {
|
|
231
|
+
state.locks = [];
|
|
232
|
+
reason = "All locks cleared for gate key";
|
|
233
|
+
}
|
|
234
|
+
const metadata = {
|
|
235
|
+
key,
|
|
236
|
+
acquired,
|
|
237
|
+
activeCount: state.locks.length,
|
|
238
|
+
maxConcurrent,
|
|
239
|
+
reason,
|
|
240
|
+
lockId,
|
|
241
|
+
expiresAt,
|
|
242
|
+
locks: operation === "inspect" ? state.locks : undefined,
|
|
243
|
+
};
|
|
244
|
+
const outputItem = (0, utils_1.createOutputItem)(item, itemIndex, preserveOriginalItem, "__concurrencyGate", metadata);
|
|
245
|
+
if (routeBlocked) {
|
|
246
|
+
blockedItems.push(outputItem);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
allowedItems.push(outputItem);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
const message = error instanceof Error ? error.message : "Unknown concurrency error";
|
|
254
|
+
if (this.continueOnFail()) {
|
|
255
|
+
blockedItems.push({
|
|
256
|
+
json: { error: message },
|
|
257
|
+
pairedItem: { item: itemIndex },
|
|
258
|
+
});
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), message, { itemIndex });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return [allowedItems, blockedItems];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
exports.ConcurrencyGate = ConcurrencyGate;
|
|
268
|
+
//# sourceMappingURL=ConcurrencyGate.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConcurrencyGate.node.js","sourceRoot":"","sources":["../../../nodes/ConcurrencyGate/ConcurrencyGate.node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Concurrency Gate">
|
|
2
|
+
<rect width="64" height="64" rx="14" fill="#0E8F7E"/>
|
|
3
|
+
<path d="M18 18h28v28H18z" fill="none" stroke="#fff" stroke-width="5" stroke-linejoin="round"/>
|
|
4
|
+
<path d="M12 28h12M12 38h12M40 28h12M40 38h12" fill="none" stroke="#fff" stroke-width="5" stroke-linecap="round"/>
|
|
5
|
+
<path d="M32 24v16" fill="none" stroke="#fff" stroke-width="5" stroke-linecap="round"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from "n8n-workflow";
|
|
2
|
+
export declare class DeadLetterQueue implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=DeadLetterQueue.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeadLetterQueue.node.d.ts","sourceRoot":"","sources":["../../../nodes/DeadLetterQueue/DeadLetterQueue.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAGrB,MAAM,cAAc,CAAC;AAatB,qBAAa,eAAgB,YAAW,SAAS;IAC/C,WAAW,EAAE,oBAAoB,CAwG/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAqGxE"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeadLetterQueue = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const fieldPath_1 = require("../shared/fieldPath");
|
|
6
|
+
const utils_1 = require("../shared/utils");
|
|
7
|
+
class DeadLetterQueue {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.description = {
|
|
10
|
+
displayName: "Dead Letter Queue",
|
|
11
|
+
name: "deadLetterQueue",
|
|
12
|
+
icon: "file:deadLetterQueue.svg",
|
|
13
|
+
group: ["transform"],
|
|
14
|
+
version: 1,
|
|
15
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
16
|
+
description: "Format failed workflow items for review or replay",
|
|
17
|
+
defaults: {
|
|
18
|
+
name: "Dead Letter Queue",
|
|
19
|
+
},
|
|
20
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
21
|
+
outputs: [
|
|
22
|
+
{
|
|
23
|
+
type: n8n_workflow_1.NodeConnectionTypes.Main,
|
|
24
|
+
displayName: "Dead Letter Item",
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
usableAsTool: true,
|
|
28
|
+
properties: [
|
|
29
|
+
{
|
|
30
|
+
displayName: "Operation",
|
|
31
|
+
name: "operation",
|
|
32
|
+
type: "options",
|
|
33
|
+
noDataExpression: true,
|
|
34
|
+
options: [
|
|
35
|
+
{
|
|
36
|
+
name: "Format Failed Item",
|
|
37
|
+
value: "formatFailedItem",
|
|
38
|
+
description: "Wrap the input item as a dead-letter payload",
|
|
39
|
+
action: "Format failed item",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
default: "formatFailedItem",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
displayName: "Failure Reason Field",
|
|
46
|
+
name: "failureReasonField",
|
|
47
|
+
type: "string",
|
|
48
|
+
default: "message",
|
|
49
|
+
description: "Dot path containing the failure reason. Falls back to error metadata when empty.",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
displayName: "Source Node Field",
|
|
53
|
+
name: "sourceNodeField",
|
|
54
|
+
type: "string",
|
|
55
|
+
default: "sourceNode",
|
|
56
|
+
description: "Optional dot path containing the source node name",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
displayName: "Workflow ID Field",
|
|
60
|
+
name: "workflowIdField",
|
|
61
|
+
type: "string",
|
|
62
|
+
default: "workflowId",
|
|
63
|
+
description: "Optional dot path containing a workflow ID override",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
displayName: "Workflow Name Field",
|
|
67
|
+
name: "workflowNameField",
|
|
68
|
+
type: "string",
|
|
69
|
+
default: "workflowName",
|
|
70
|
+
description: "Optional dot path containing a workflow name override",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
displayName: "Execution ID Field",
|
|
74
|
+
name: "executionIdField",
|
|
75
|
+
type: "string",
|
|
76
|
+
default: "executionId",
|
|
77
|
+
description: "Optional dot path containing an execution ID override",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
displayName: "Include Original Payload",
|
|
81
|
+
name: "includeOriginalPayload",
|
|
82
|
+
type: "boolean",
|
|
83
|
+
default: true,
|
|
84
|
+
description: "Whether to include the incoming JSON as originalPayload",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
displayName: "Include Error Metadata",
|
|
88
|
+
name: "includeErrorMetadata",
|
|
89
|
+
type: "boolean",
|
|
90
|
+
default: true,
|
|
91
|
+
description: "Whether to include error, retry, circuit breaker, and gate metadata",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
displayName: "Destination Mode",
|
|
95
|
+
name: "destinationMode",
|
|
96
|
+
type: "options",
|
|
97
|
+
noDataExpression: true,
|
|
98
|
+
options: [
|
|
99
|
+
{
|
|
100
|
+
name: "Output Only",
|
|
101
|
+
value: "outputOnly",
|
|
102
|
+
description: "Send the dead-letter item to the node output",
|
|
103
|
+
action: "Output dead-letter item",
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
default: "outputOnly",
|
|
107
|
+
description: "External dead-letter storage is intentionally left to downstream n8n nodes",
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async execute() {
|
|
113
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
114
|
+
const items = this.getInputData();
|
|
115
|
+
const returnData = [];
|
|
116
|
+
const workflow = this.getWorkflow();
|
|
117
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
118
|
+
try {
|
|
119
|
+
const item = items[itemIndex];
|
|
120
|
+
const operation = this.getNodeParameter("operation", itemIndex);
|
|
121
|
+
const failureReasonField = this.getNodeParameter("failureReasonField", itemIndex);
|
|
122
|
+
const sourceNodeField = this.getNodeParameter("sourceNodeField", itemIndex);
|
|
123
|
+
const workflowIdField = this.getNodeParameter("workflowIdField", itemIndex);
|
|
124
|
+
const workflowNameField = this.getNodeParameter("workflowNameField", itemIndex);
|
|
125
|
+
const executionIdField = this.getNodeParameter("executionIdField", itemIndex);
|
|
126
|
+
const includeOriginalPayload = this.getNodeParameter("includeOriginalPayload", itemIndex);
|
|
127
|
+
const includeErrorMetadata = this.getNodeParameter("includeErrorMetadata", itemIndex);
|
|
128
|
+
const reason = (_c = (_b = (_a = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, failureReasonField))) !== null && _a !== void 0 ? _a : (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, "error.message"))) !== null && _b !== void 0 ? _b : (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, "error"))) !== null && _c !== void 0 ? _c : "Failed item";
|
|
129
|
+
const error = includeErrorMetadata
|
|
130
|
+
? (0, utils_1.removeUndefinedValues)({
|
|
131
|
+
error: (0, fieldPath_1.getValueAtPath)(item.json, "error"),
|
|
132
|
+
message: (0, fieldPath_1.getValueAtPath)(item.json, "message"),
|
|
133
|
+
statusCode: (0, fieldPath_1.getValueAtPath)(item.json, "statusCode"),
|
|
134
|
+
concurrencyGate: (0, fieldPath_1.getValueAtPath)(item.json, "__concurrencyGate"),
|
|
135
|
+
})
|
|
136
|
+
: {};
|
|
137
|
+
const deadLetter = (0, utils_1.removeUndefinedValues)({
|
|
138
|
+
deadLetterId: (0, utils_1.generateId)("dlq"),
|
|
139
|
+
timestamp: new Date().toISOString(),
|
|
140
|
+
operation,
|
|
141
|
+
reason,
|
|
142
|
+
sourceNode: (_d = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, sourceNodeField))) !== null && _d !== void 0 ? _d : this.getNode().name,
|
|
143
|
+
workflowId: (_e = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, workflowIdField))) !== null && _e !== void 0 ? _e : workflow.id,
|
|
144
|
+
workflowName: (_f = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, workflowNameField))) !== null && _f !== void 0 ? _f : workflow.name,
|
|
145
|
+
executionId: (_g = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, executionIdField))) !== null && _g !== void 0 ? _g : this.getExecutionId(),
|
|
146
|
+
originalPayload: includeOriginalPayload
|
|
147
|
+
? (0, utils_1.deepCopy)(item.json)
|
|
148
|
+
: undefined,
|
|
149
|
+
error,
|
|
150
|
+
retry: includeErrorMetadata
|
|
151
|
+
? (0, utils_1.asDataObject)((0, fieldPath_1.getValueAtPath)(item.json, "__retry"))
|
|
152
|
+
: {},
|
|
153
|
+
});
|
|
154
|
+
returnData.push({
|
|
155
|
+
json: deadLetter,
|
|
156
|
+
pairedItem: { item: itemIndex },
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
const message = error instanceof Error ? error.message : "Unknown dead-letter error";
|
|
161
|
+
if (this.continueOnFail()) {
|
|
162
|
+
returnData.push({
|
|
163
|
+
json: { error: message },
|
|
164
|
+
pairedItem: { item: itemIndex },
|
|
165
|
+
});
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), message, { itemIndex });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return [returnData];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.DeadLetterQueue = DeadLetterQueue;
|
|
175
|
+
//# sourceMappingURL=DeadLetterQueue.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeadLetterQueue.node.js","sourceRoot":"","sources":["../../../nodes/DeadLetterQueue/DeadLetterQueue.node.ts"],"names":[],"mappings":"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"}
|