feat(09-02): add loop over items for sequential batch execution

- Add Initialize Batch State code node to prepare batch data
- Add Send Batch Start Message to show initial progress
- Add Prepare Batch Loop to format containers for iteration
- Add Batch Loop (splitInBatches) for sequential processing
- Connect Route Batch Action outputs (update/start/restart) to batch flow
This commit is contained in:
Lucas Berger
2026-02-03 21:28:33 -05:00
parent 1274eab438
commit 62f50cb502
+113 -3
View File
@@ -4412,6 +4412,65 @@
2000,
600
]
},
{
"parameters": {
"jsCode": "// Initialize batch state for execution\n// Input comes from Route Batch Action OR batch callbacks (bexec, bstop confirmed)\nconst data = $json;\n\n// Handle different input sources\nlet containers, action, chatId, messageId;\n\nif (data.allMatched) {\n // From Route Batch Action (direct batch command)\n containers = data.allMatched;\n action = data.action;\n chatId = data.chatId;\n messageId = data.messageId || null;\n} else if (data.containerNames) {\n // From batch callback (bexec or bstop:confirm)\n // Need to resolve names to container objects\n containers = data.containerNames.map(name => ({ Name: name, Id: null }));\n action = data.batchAction || 'stop';\n chatId = data.chatId;\n messageId = data.messageId;\n} else {\n throw new Error('Invalid batch state input');\n}\n\nreturn {\n json: {\n containers: containers,\n action: action,\n totalCount: containers.length,\n successCount: 0,\n failureCount: 0,\n warningCount: 0,\n results: [],\n chatId: chatId,\n messageId: messageId,\n currentIndex: 0,\n progressMessageId: null\n }\n};"
},
"id": "code-init-batch-state",
"name": "Initialize Batch State",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2440,
-500
]
},
{
"parameters": {
"method": "POST",
"url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ chat_id: $json.chatId, text: '<b>Batch ' + $json.action + '</b>\\n\\nStarting ' + $json.action + ' for ' + $json.totalCount + ' containers...', parse_mode: 'HTML' }) }}",
"options": {}
},
"id": "http-send-batch-start",
"name": "Send Batch Start Message",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2660,
-500
]
},
{
"parameters": {
"jsCode": "// Store progress message ID and prepare containers for loop\nconst batchState = $('Initialize Batch State').item.json;\nconst response = $json;\n\n// Get message_id from Telegram response\nconst progressMessageId = response.result?.message_id || null;\n\n// Return array of items for the loop - each container as separate item\nconst items = batchState.containers.map((container, index) => ({\n json: {\n container: container,\n containerIndex: index,\n action: batchState.action,\n totalCount: batchState.totalCount,\n chatId: batchState.chatId,\n progressMessageId: progressMessageId,\n // Running totals - will be updated as loop progresses\n successCount: 0,\n failureCount: 0,\n warningCount: 0,\n results: []\n }\n}));\n\nreturn items;"
},
"id": "code-prepare-batch-loop",
"name": "Prepare Batch Loop",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2880,
-500
]
},
{
"parameters": {
"options": {
"reset": false
}
},
"id": "loop-batch",
"name": "Batch Loop",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
3100,
-500
]
}
],
"connections": {
@@ -5725,9 +5784,27 @@
},
"Route Batch Action": {
"main": [
[],
[],
[],
[
{
"node": "Initialize Batch State",
"type": "main",
"index": 0
}
],
[
{
"node": "Initialize Batch State",
"type": "main",
"index": 0
}
],
[
{
"node": "Initialize Batch State",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Batch Stop Confirmation",
@@ -6391,6 +6468,39 @@
}
]
]
},
"Initialize Batch State": {
"main": [
[
{
"node": "Send Batch Start Message",
"type": "main",
"index": 0
}
]
]
},
"Send Batch Start Message": {
"main": [
[
{
"node": "Prepare Batch Loop",
"type": "main",
"index": 0
}
]
]
},
"Prepare Batch Loop": {
"main": [
[
{
"node": "Batch Loop",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},