{ "name": "PBS: Cloudflare Cache Warmer 5 days", "nodes": [ { "parameters": { "rule": { "interval": [ { "daysInterval": 5 } ] } }, "id": "17b4e5fd-e821-477e-9df0-aade6ccefbbf", "name": "Daily 4 AM ET", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [ -720, -80 ] }, { "parameters": { "operation": "executeQuery", "query": "SELECT recipe_url AS url, recipe_title AS title\nFROM pbs_recipes\nWHERE recipe_url IS NOT NULL\n AND recipe_url != ''\nORDER BY post_id ASC", "options": {} }, "id": "22f29499-7bcd-4699-8c3a-799c58d0cfec", "name": "Get Recipe URLs", "type": "n8n-nodes-base.mySql", "typeVersion": 2.4, "position": [ -496, -80 ], "credentials": { "mySql": { "id": "4ETlVumrAq95ispJ", "name": "MySQL account" } } }, { "parameters": { "jsCode": "// Initialize tracking counters before the loop begins.\nconst staticData = $getWorkflowStaticData('global');\nstaticData.warmed = 0;\nstaticData.errors = 0;\nstaticData.errorUrls = [];\nstaticData.totalUrls = $input.all().length;\n\n// Pass all items through unchanged\nreturn $input.all();\n" }, "id": "efebcbc9-c6a8-44c6-a92c-591e478bf0b0", "name": "Init Counters", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -272, -80 ] }, { "parameters": { "options": {} }, "id": "beae05d0-c631-403c-b414-a224e3e1b531", "name": "Loop Recipe URLs", "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ -32, -80 ] }, { "parameters": { "url": "={{ $json.url }}", "options": { "redirect": { "redirect": {} }, "response": { "response": { "responseFormat": "text" } }, "timeout": 30000 } }, "id": "f7cd0cc1-b755-49ff-b08c-e040da9f285d", "name": "Warm Cache (GET)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 208, -80 ], "onError": "continueRegularOutput" }, { "parameters": { "jsCode": "// Track success/failure for each URL warming attempt.\nconst staticData = $getWorkflowStaticData('global');\n\nconst item = $input.first().json;\nconst statusCode = item.statusCode || item.$response?.statusCode || 200;\nconst url = $('Loop Recipe URLs').first().json.url || 'unknown';\n\nif (statusCode >= 200 && statusCode < 400) {\n staticData.warmed++;\n} else {\n staticData.errors++;\n if (staticData.errorUrls.length < 10) {\n staticData.errorUrls.push(url + ' (' + statusCode + ')');\n }\n}\n\nreturn [{ json: { tracked: true } }];\n" }, "id": "73caf61c-cd15-4dd1-977e-9bf053e1f062", "name": "Track Results", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 384, -80 ] }, { "parameters": { "jsCode": "// Build final summary message after all recipe URLs have been warmed.\nconst staticData = $getWorkflowStaticData('global');\nconst warmed = staticData.warmed || 0;\nconst errors = staticData.errors || 0;\nconst errorUrls = staticData.errorUrls || [];\nconst total = staticData.totalUrls || (warmed + errors);\n\nlet message = 'šŸ”„ *PBS Cache Warmer — Daily Run Complete*\\n';\nmessage += '\\n*Recipe URLs in database:* ' + total;\nmessage += '\\n*Warmed successfully:* ' + warmed;\nmessage += '\\n*Errors:* ' + errors;\n\nif (errors > 0 && errorUrls.length > 0) {\n message += '\\n\\n*Failed URLs (first 10):*';\n errorUrls.forEach(u => {\n message += '\\n• ' + u;\n });\n}\n\nif (errors === 0) {\n message += '\\n\\nāœ… All recipe pages cached successfully.';\n}\n\n// Clean up static data for next run\nstaticData.warmed = 0;\nstaticData.errors = 0;\nstaticData.errorUrls = [];\nstaticData.totalUrls = 0;\nconst title = \"PBS-Cache Refresh\"\nconst timestamp = $now.toFormat('MMM dd, HH:mm:ss')\n\nreturn [{ json: { title, message, timestamp } }];\n" }, "id": "866a4920-9d22-47e6-b48c-e121be8ec3e9", "name": "Build Summary", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 176, -272 ] }, { "parameters": { "workflowId": { "__rl": true, "value": "-DlPrT1UsgmacYJyoUJXU", "mode": "list", "cachedResultUrl": "/workflow/-DlPrT1UsgmacYJyoUJXU", "cachedResultName": "PBS: Google Chat Notify (Sub-Workflow)" }, "workflowInputs": { "mappingMode": "defineBelow", "value": {}, "matchingColumns": [], "schema": [], "attemptToConvertTypes": false, "convertFieldsToString": true }, "options": {} }, "type": "n8n-nodes-base.executeWorkflow", "typeVersion": 1.3, "position": [ 384, -288 ], "id": "67d65c33-84ed-40bb-bfb3-7a54e1f1664c", "name": "Call 'PBS: Google Chat Notify (Sub-Workflow)'" }, { "parameters": {}, "id": "0810a6a3-9440-4bae-a399-5c73f1f3f460", "name": "Wait 5s", "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [ 608, -80 ], "webhookId": "d3c0e894-852f-42ff-a7ef-d5b692b74958" } ], "pinData": { "Daily 4 AM ET": [ { "json": { "timestamp": "2026-04-20T22:20:39.641-04:00", "Readable date": "April 20th 2026, 10:20:39 pm", "Readable time": "10:20:39 pm", "Day of week": "Monday", "Year": "2026", "Month": "April", "Day of month": "20", "Hour": "22", "Minute": "20", "Second": "39", "Timezone": "America/New_York (UTC-04:00)" }, "pairedItem": { "item": 0 } } ] }, "connections": { "Daily 4 AM ET": { "main": [ [ { "node": "Get Recipe URLs", "type": "main", "index": 0 } ] ] }, "Get Recipe URLs": { "main": [ [ { "node": "Init Counters", "type": "main", "index": 0 } ] ] }, "Init Counters": { "main": [ [ { "node": "Loop Recipe URLs", "type": "main", "index": 0 } ] ] }, "Loop Recipe URLs": { "main": [ [ { "node": "Build Summary", "type": "main", "index": 0 } ], [ { "node": "Warm Cache (GET)", "type": "main", "index": 0 } ] ] }, "Warm Cache (GET)": { "main": [ [ { "node": "Track Results", "type": "main", "index": 0 } ] ] }, "Track Results": { "main": [ [ { "node": "Wait 5s", "type": "main", "index": 0 } ] ] }, "Build Summary": { "main": [ [ { "node": "Call 'PBS: Google Chat Notify (Sub-Workflow)'", "type": "main", "index": 0 } ] ] }, "Wait 5s": { "main": [ [ { "node": "Loop Recipe URLs", "type": "main", "index": 0 } ] ] } }, "active": true, "settings": { "executionOrder": "v1", "availableInMCP": false }, "versionId": "1139d52b-c9ea-4e78-8dc8-ef6904416593", "meta": { "templateCredsSetupCompleted": true, "instanceId": "eeb18e777509f7207ee9abd45845e7fbf014989719160f3ed6ae633d872bf6c4" }, "id": "UPgYRkjq9YrUbGmvWL_wC", "tags": [] }