From 62f50cb50282498d6d2c792f426a2defcf4a7373 Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Tue, 3 Feb 2026 21:28:33 -0500 Subject: [PATCH] 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 --- n8n-workflow.json | 116 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 3 deletions(-) diff --git a/n8n-workflow.json b/n8n-workflow.json index 66bbf87..49d5a1c 100644 --- a/n8n-workflow.json +++ b/n8n-workflow.json @@ -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: 'Batch ' + $json.action + '\\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": {},