[
  {
    "id": "resume_example_tab",
    "type": "tab",
    "label": "Auto-resume on workflow failure",
    "disabled": false,
    "info": "# Auto-resume on workflow failure\n\nThis example demonstrates how to automatically resume a failed workflow using a **simple loop pattern**. When a workflow fails, it loops directly back to the launch node which automatically retries with resume enabled.\n\n## How it works (Loop Pattern)\n\n1. **Trigger** - Click inject to start (or use any trigger)\n2. **Launch** - Launches workflow (reads workflow ID from msg.workflowId for resume)\n3. **Monitor** - Monitors workflow status with three outputs\n4. **On Success** - Flow completes (output 2)\n5. **On Failure** - Loops directly back to Launch node (output 3)\n\n## Key Features\n\n- **Single Launch Node**: The same node handles both initial launch and resume\n- **Direct Loop**: Failed workflows loop directly back - no intermediate nodes needed!\n- **Automatic resume**: The launch node reads msg.workflowId and automatically:\n  - Fetches the session ID from the failed workflow\n  - Enables Nextflow resume\n  - Uses the correct commit/revision\n\n## Setup Instructions\n\n1. Double click the **\"Launch workflow\"** node:\n   - Configure Seqera Platform credentials\n   - Set launchpad name\n   - **Important**: \"Resume from\" field is set to read from \"msg.workflowId\" (type: msg)\n\n2. Configure the **\"Monitor workflow\"** node with same Seqera config\n\n3. Click **\"Deploy\"** in Node-RED (top right)\n\n4. Click the **Inject** node to start\n\n## Important Notes\n\n- The resumed workflow must use the same work directory as the original\n- Your compute environment must have access to the cached results\n- **This creates an infinite loop** that retries until success - add retry limit logic if needed\n- Each retry uses Nextflow's `-resume` to skip completed tasks",
    "env": []
  },
  {
    "id": "inject_trigger",
    "type": "inject",
    "z": "resume_example_tab",
    "name": "Trigger workflow",
    "props": [],
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "topic": "",
    "x": 140,
    "y": 180,
    "wires": [["launch_node"]]
  },
  {
    "id": "launch_node",
    "type": "seqera-workflow-launch",
    "z": "resume_example_tab",
    "name": "Launch workflow",
    "seqera": "",
    "launchpadName": "nf-core-rnaseq",
    "launchpadNameType": "str",
    "paramsKey": "{}",
    "paramsKeyType": "json",
    "params": [
      {
        "name": "outdir",
        "value": "./results",
        "valueType": "str"
      }
    ],
    "runName": "",
    "runNameType": "str",
    "resumeWorkflowId": "workflowId",
    "resumeWorkflowIdType": "msg",
    "workspaceId": "",
    "workspaceIdType": "str",
    "sourceWorkspaceId": "",
    "sourceWorkspaceIdType": "str",
    "x": 350,
    "y": 180,
    "wires": [["monitor_node"]]
  },
  {
    "id": "monitor_node",
    "type": "seqera-workflow-monitor",
    "z": "resume_example_tab",
    "name": "Monitor workflow",
    "seqera": "",
    "workflowId": "workflowId",
    "workflowIdType": "msg",
    "workspaceId": "",
    "workspaceIdType": "str",
    "keepPolling": true,
    "poll": "15",
    "pollUnits": "seconds",
    "x": 570,
    "y": 180,
    "wires": [[], ["debug_success"], ["73841c107d946dcc"]]
  },
  {
    "id": "debug_success",
    "type": "debug",
    "z": "resume_example_tab",
    "name": "✓ Success!",
    "active": true,
    "tosidebar": true,
    "console": false,
    "tostatus": false,
    "complete": "true",
    "targetType": "full",
    "statusVal": "",
    "statusType": "auto",
    "x": 770,
    "y": 180,
    "wires": []
  },
  {
    "id": "comment_trigger",
    "type": "comment",
    "z": "resume_example_tab",
    "name": "Trigger",
    "info": "Click this inject node to start the workflow.\n\nIn a real automation, you might trigger this\nfrom a file upload, scheduled time, or other event.\n\nThe initial message has no workflow ID,\nso the launch node will start fresh.",
    "x": 130,
    "y": 120,
    "wires": []
  },
  {
    "id": "comment_launch",
    "type": "comment",
    "z": "resume_example_tab",
    "name": "Launch (with loop)",
    "info": "This node handles BOTH initial launch AND resume.\n\n**Configuration:**\n- Resume from: `msg.workflowId` (type: msg)\n\n**First run:** `msg.workflowId` is `undefined` → launches fresh\n**Loop back:** `msg.workflowId` is populated → fetches session ID and resumes\n\nThe same node works for both cases! When a workflow ID is provided,\nthe node automatically fetches the session ID from the API and enables resume.",
    "x": 350,
    "y": 120,
    "wires": []
  },
  {
    "id": "comment_monitor",
    "type": "comment",
    "z": "resume_example_tab",
    "name": "Monitor",
    "info": "Monitors the workflow status.\n\n**Three outputs:**\n1. Running status (not connected - no action needed)\n2. Success (workflow completed) → Flow ends here with debug output\n3. Failed (workflow errored) → Loops directly back to Launch node\n\nOutput 3 connects back to the launch node, creating the resume loop.",
    "x": 550,
    "y": 120,
    "wires": []
  },
  {
    "id": "comment_outputs",
    "type": "comment",
    "z": "resume_example_tab",
    "name": "Outputs",
    "info": "**Success** - Final successful completion (debug output)",
    "x": 770,
    "y": 120,
    "wires": []
  },
  {
    "id": "73841c107d946dcc",
    "type": "change",
    "z": "resume_example_tab",
    "name": "Increment retry counter",
    "rules": [
      {
        "t": "set",
        "p": "_retries",
        "pt": "msg",
        "to": "_retries ? _retries + 1 : 1",
        "tot": "jsonata"
      }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 190,
    "y": 280,
    "wires": [["d462ab97a42a95e0"]]
  },
  {
    "id": "d462ab97a42a95e0",
    "type": "switch",
    "z": "resume_example_tab",
    "name": "<= 3 retries?",
    "property": "_retries",
    "propertyType": "msg",
    "rules": [
      {
        "t": "lte",
        "v": "3",
        "vt": "str"
      },
      {
        "t": "else"
      }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 2,
    "x": 410,
    "y": 280,
    "wires": [["launch_node"], ["59af93d472724fe5"]]
  },
  {
    "id": "59af93d472724fe5",
    "type": "debug",
    "z": "resume_example_tab",
    "name": "✘ Give up",
    "active": true,
    "tosidebar": true,
    "console": false,
    "tostatus": false,
    "complete": "true",
    "targetType": "full",
    "statusVal": "",
    "statusType": "auto",
    "x": 590,
    "y": 280,
    "wires": []
  },
  {
    "id": "3f8061dd9c9fca4c",
    "type": "comment",
    "z": "resume_example_tab",
    "name": "Counter",
    "info": "This `change` node sets `msg._retries` if\nnot already set, and increments it by\none if it does.\n\nSeqera Node-RED nodes pass through\nunrecognised `msg` variables, so this\npersists through the loop for each launch.\n\nMultiple pipeline launches can be triggered\nin parallel and each will have its own\nretry counter in the `msg` object.",
    "x": 150,
    "y": 320,
    "wires": []
  },
  {
    "id": "5ee40e98b81ff1e7",
    "type": "comment",
    "z": "resume_example_tab",
    "name": "Switch",
    "info": "A Node-RED `switch` node checks if we have\nhad 3 retries already by inspecting our\n`msg._retries` counter.",
    "x": 390,
    "y": 320,
    "wires": []
  },
  {
    "id": "9d80d663bb701bf6",
    "type": "comment",
    "z": "resume_example_tab",
    "name": "Failure",
    "info": "**Failure** - Give up after 3 attempts (debug output)",
    "x": 590,
    "y": 320,
    "wires": []
  },
  {
    "id": "ec31addc40995619",
    "type": "global-config",
    "env": [],
    "modules": {
      "@seqera/node-red-seqera": "1.2.0"
    }
  }
]
