bps-kit 1.2.2 → 1.3.1
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/.bps-kit.json +4 -4
- package/README.md +3 -0
- package/implementation_plan.md.resolved +37 -0
- package/package.json +2 -2
- package/templates/agents-template/ARCHITECTURE.md +21 -9
- package/templates/agents-template/agents/automation-specialist.md +157 -0
- package/templates/agents-template/rules/GEMINI.md +2 -10
- package/templates/agents-template/workflows/automate.md +153 -0
- package/templates/skills_normal/n8n-code-javascript/BUILTIN_FUNCTIONS.md +764 -0
- package/templates/skills_normal/n8n-code-javascript/COMMON_PATTERNS.md +1110 -0
- package/templates/skills_normal/n8n-code-javascript/DATA_ACCESS.md +782 -0
- package/templates/skills_normal/n8n-code-javascript/ERROR_PATTERNS.md +763 -0
- package/templates/skills_normal/n8n-code-javascript/README.md +350 -0
- package/templates/skills_normal/n8n-code-javascript/SKILL.md +699 -0
- package/templates/skills_normal/n8n-code-python/COMMON_PATTERNS.md +794 -0
- package/templates/skills_normal/n8n-code-python/DATA_ACCESS.md +702 -0
- package/templates/skills_normal/n8n-code-python/ERROR_PATTERNS.md +601 -0
- package/templates/skills_normal/n8n-code-python/README.md +386 -0
- package/templates/skills_normal/n8n-code-python/SKILL.md +748 -0
- package/templates/skills_normal/n8n-code-python/STANDARD_LIBRARY.md +974 -0
- package/templates/skills_normal/n8n-expression-syntax/COMMON_MISTAKES.md +393 -0
- package/templates/skills_normal/n8n-expression-syntax/EXAMPLES.md +483 -0
- package/templates/skills_normal/n8n-expression-syntax/README.md +93 -0
- package/templates/skills_normal/n8n-expression-syntax/SKILL.md +516 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/README.md +99 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/SEARCH_GUIDE.md +374 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/SKILL.md +642 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/VALIDATION_GUIDE.md +442 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/WORKFLOW_GUIDE.md +618 -0
- package/templates/skills_normal/n8n-node-configuration/DEPENDENCIES.md +789 -0
- package/templates/skills_normal/n8n-node-configuration/OPERATION_PATTERNS.md +913 -0
- package/templates/skills_normal/n8n-node-configuration/README.md +364 -0
- package/templates/skills_normal/n8n-node-configuration/SKILL.md +785 -0
- package/templates/skills_normal/n8n-validation-expert/ERROR_CATALOG.md +943 -0
- package/templates/skills_normal/n8n-validation-expert/FALSE_POSITIVES.md +720 -0
- package/templates/skills_normal/n8n-validation-expert/README.md +290 -0
- package/templates/skills_normal/n8n-validation-expert/SKILL.md +689 -0
- package/templates/skills_normal/n8n-workflow-patterns/README.md +251 -0
- package/templates/skills_normal/n8n-workflow-patterns/SKILL.md +411 -0
- package/templates/skills_normal/n8n-workflow-patterns/ai_agent_workflow.md +784 -0
- package/templates/skills_normal/n8n-workflow-patterns/database_operations.md +785 -0
- package/templates/skills_normal/n8n-workflow-patterns/http_api_integration.md +734 -0
- package/templates/skills_normal/n8n-workflow-patterns/scheduled_tasks.md +773 -0
- package/templates/skills_normal/n8n-workflow-patterns/webhook_processing.md +545 -0
- package/templates/vault/n8n-code-javascript/SKILL.md +10 -10
- package/templates/vault/n8n-code-python/SKILL.md +11 -11
- package/templates/vault/n8n-expression-syntax/SKILL.md +4 -4
- package/templates/vault/n8n-mcp-tools-expert/SKILL.md +9 -9
- package/templates/vault/n8n-node-configuration/SKILL.md +2 -2
- package/templates/vault/n8n-validation-expert/SKILL.md +3 -3
- package/templates/vault/n8n-workflow-patterns/SKILL.md +11 -11
|
@@ -0,0 +1,773 @@
|
|
|
1
|
+
# Scheduled Tasks Pattern
|
|
2
|
+
|
|
3
|
+
**Use Case**: Recurring automation workflows that run automatically on a schedule.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Pattern Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Schedule Trigger → [Fetch Data] → [Process] → [Deliver] → [Log/Notify]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**Key Characteristic**: Time-based automated execution
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Core Components
|
|
18
|
+
|
|
19
|
+
### 1. Schedule Trigger
|
|
20
|
+
**Purpose**: Execute workflow at specified times
|
|
21
|
+
|
|
22
|
+
**Modes**:
|
|
23
|
+
- **Interval** - Every X minutes/hours/days
|
|
24
|
+
- **Cron** - Specific times (advanced)
|
|
25
|
+
- **Days & Hours** - Simple recurring schedule
|
|
26
|
+
|
|
27
|
+
### 2. Data Source
|
|
28
|
+
**Common sources**:
|
|
29
|
+
- HTTP Request (APIs)
|
|
30
|
+
- Database queries
|
|
31
|
+
- File reads
|
|
32
|
+
- Service-specific nodes
|
|
33
|
+
|
|
34
|
+
### 3. Processing
|
|
35
|
+
**Typical operations**:
|
|
36
|
+
- Filter/transform data
|
|
37
|
+
- Aggregate statistics
|
|
38
|
+
- Generate reports
|
|
39
|
+
- Check conditions
|
|
40
|
+
|
|
41
|
+
### 4. Delivery
|
|
42
|
+
**Output channels**:
|
|
43
|
+
- Email
|
|
44
|
+
- Slack/Discord/Teams
|
|
45
|
+
- File storage
|
|
46
|
+
- Database writes
|
|
47
|
+
|
|
48
|
+
### 5. Logging
|
|
49
|
+
**Purpose**: Track execution history
|
|
50
|
+
|
|
51
|
+
**Methods**:
|
|
52
|
+
- Database log entries
|
|
53
|
+
- File append
|
|
54
|
+
- Monitoring service
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Schedule Configuration
|
|
59
|
+
|
|
60
|
+
### Interval Mode
|
|
61
|
+
**Best for**: Simple recurring tasks
|
|
62
|
+
|
|
63
|
+
**Examples**:
|
|
64
|
+
```javascript
|
|
65
|
+
// Every 15 minutes
|
|
66
|
+
{
|
|
67
|
+
mode: "interval",
|
|
68
|
+
interval: 15,
|
|
69
|
+
unit: "minutes"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Every 2 hours
|
|
73
|
+
{
|
|
74
|
+
mode: "interval",
|
|
75
|
+
interval: 2,
|
|
76
|
+
unit: "hours"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Every day at midnight
|
|
80
|
+
{
|
|
81
|
+
mode: "interval",
|
|
82
|
+
interval: 1,
|
|
83
|
+
unit: "days"
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Days & Hours Mode
|
|
88
|
+
**Best for**: Specific days and times
|
|
89
|
+
|
|
90
|
+
**Examples**:
|
|
91
|
+
```javascript
|
|
92
|
+
// Weekdays at 9 AM
|
|
93
|
+
{
|
|
94
|
+
mode: "daysAndHours",
|
|
95
|
+
days: ["monday", "tuesday", "wednesday", "thursday", "friday"],
|
|
96
|
+
hour: 9,
|
|
97
|
+
minute: 0
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Every Monday at 6 PM
|
|
101
|
+
{
|
|
102
|
+
mode: "daysAndHours",
|
|
103
|
+
days: ["monday"],
|
|
104
|
+
hour: 18,
|
|
105
|
+
minute: 0
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Cron Mode (Advanced)
|
|
110
|
+
**Best for**: Complex schedules
|
|
111
|
+
|
|
112
|
+
**Examples**:
|
|
113
|
+
```javascript
|
|
114
|
+
// Every weekday at 9 AM
|
|
115
|
+
{
|
|
116
|
+
mode: "cron",
|
|
117
|
+
expression: "0 9 * * 1-5"
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// First day of every month at midnight
|
|
121
|
+
{
|
|
122
|
+
mode: "cron",
|
|
123
|
+
expression: "0 0 1 * *"
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Every 15 minutes during business hours (9 AM - 5 PM) on weekdays
|
|
127
|
+
{
|
|
128
|
+
mode: "cron",
|
|
129
|
+
expression: "*/15 9-17 * * 1-5"
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Cron format**: `minute hour day month weekday`
|
|
134
|
+
- `*` = any value
|
|
135
|
+
- `*/15` = every 15 units
|
|
136
|
+
- `1-5` = range (Monday-Friday)
|
|
137
|
+
- `1,15` = specific values
|
|
138
|
+
|
|
139
|
+
**Cron examples**:
|
|
140
|
+
```
|
|
141
|
+
0 */6 * * * Every 6 hours
|
|
142
|
+
0 9,17 * * * At 9 AM and 5 PM daily
|
|
143
|
+
0 0 * * 0 Every Sunday at midnight
|
|
144
|
+
*/30 * * * * Every 30 minutes
|
|
145
|
+
0 0 1,15 * * 1st and 15th of each month
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Common Use Cases
|
|
151
|
+
|
|
152
|
+
### 1. Daily Reports
|
|
153
|
+
**Flow**: Schedule → Fetch data → Aggregate → Format → Email
|
|
154
|
+
|
|
155
|
+
**Example** (Sales report):
|
|
156
|
+
```
|
|
157
|
+
1. Schedule (daily at 9 AM)
|
|
158
|
+
|
|
159
|
+
2. Postgres (query yesterday's sales)
|
|
160
|
+
SELECT date, SUM(amount) as total, COUNT(*) as orders
|
|
161
|
+
FROM orders
|
|
162
|
+
WHERE date = CURRENT_DATE - INTERVAL '1 day'
|
|
163
|
+
GROUP BY date
|
|
164
|
+
|
|
165
|
+
3. Code (calculate metrics)
|
|
166
|
+
- Total revenue
|
|
167
|
+
- Order count
|
|
168
|
+
- Average order value
|
|
169
|
+
- Comparison to previous day
|
|
170
|
+
|
|
171
|
+
4. Set (format email body)
|
|
172
|
+
Subject: Daily Sales Report - {{$json.date}}
|
|
173
|
+
Body: Formatted HTML with metrics
|
|
174
|
+
|
|
175
|
+
5. Email (send to team@company.com)
|
|
176
|
+
|
|
177
|
+
6. Slack (post summary to #sales)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 2. Data Synchronization
|
|
181
|
+
**Flow**: Schedule → Fetch from source → Transform → Write to target
|
|
182
|
+
|
|
183
|
+
**Example** (CRM to data warehouse sync):
|
|
184
|
+
```
|
|
185
|
+
1. Schedule (every hour)
|
|
186
|
+
|
|
187
|
+
2. Set (store last sync time)
|
|
188
|
+
SELECT MAX(synced_at) FROM sync_log
|
|
189
|
+
|
|
190
|
+
3. HTTP Request (fetch new CRM contacts since last sync)
|
|
191
|
+
GET /api/contacts?updated_since={{$json.last_sync}}
|
|
192
|
+
|
|
193
|
+
4. IF (check if new records exist)
|
|
194
|
+
|
|
195
|
+
5. Set (transform CRM schema to warehouse schema)
|
|
196
|
+
|
|
197
|
+
6. Postgres (warehouse - INSERT new contacts)
|
|
198
|
+
|
|
199
|
+
7. Postgres (UPDATE sync_log SET synced_at = NOW())
|
|
200
|
+
|
|
201
|
+
8. IF (error occurred)
|
|
202
|
+
└─ Slack (alert #data-team)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### 3. Monitoring & Health Checks
|
|
206
|
+
**Flow**: Schedule → Check endpoints → Alert if down
|
|
207
|
+
|
|
208
|
+
**Example** (Website uptime monitor):
|
|
209
|
+
```
|
|
210
|
+
1. Schedule (every 5 minutes)
|
|
211
|
+
|
|
212
|
+
2. HTTP Request (GET https://example.com/health)
|
|
213
|
+
- timeout: 10 seconds
|
|
214
|
+
- continueOnFail: true
|
|
215
|
+
|
|
216
|
+
3. IF (status !== 200 OR response_time > 2000ms)
|
|
217
|
+
|
|
218
|
+
4. Redis (check alert cooldown - don't spam)
|
|
219
|
+
- Key: alert:website_down
|
|
220
|
+
- TTL: 30 minutes
|
|
221
|
+
|
|
222
|
+
5. IF (no recent alert sent)
|
|
223
|
+
|
|
224
|
+
6. [Alert Actions]
|
|
225
|
+
├─ Slack (notify #ops-team)
|
|
226
|
+
├─ PagerDuty (create incident)
|
|
227
|
+
├─ Email (alert@company.com)
|
|
228
|
+
└─ Redis (set alert cooldown)
|
|
229
|
+
|
|
230
|
+
7. Postgres (log uptime check result)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### 4. Cleanup & Maintenance
|
|
234
|
+
**Flow**: Schedule → Find old data → Archive/Delete → Report
|
|
235
|
+
|
|
236
|
+
**Example** (Database cleanup):
|
|
237
|
+
```
|
|
238
|
+
1. Schedule (weekly on Sunday at 2 AM)
|
|
239
|
+
|
|
240
|
+
2. Postgres (find old records)
|
|
241
|
+
SELECT * FROM logs
|
|
242
|
+
WHERE created_at < NOW() - INTERVAL '90 days'
|
|
243
|
+
LIMIT 10000
|
|
244
|
+
|
|
245
|
+
3. IF (records exist)
|
|
246
|
+
|
|
247
|
+
4. Code (export to JSON for archive)
|
|
248
|
+
|
|
249
|
+
5. Google Drive (upload archive file)
|
|
250
|
+
- Filename: logs_archive_{{$now.format('YYYY-MM-DD')}}.json
|
|
251
|
+
|
|
252
|
+
6. Postgres (DELETE archived records)
|
|
253
|
+
DELETE FROM logs
|
|
254
|
+
WHERE id IN ({{$json.archived_ids}})
|
|
255
|
+
|
|
256
|
+
7. Slack (report: "Archived X records, deleted Y records")
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 5. Data Enrichment
|
|
260
|
+
**Flow**: Schedule → Find incomplete records → Enrich → Update
|
|
261
|
+
|
|
262
|
+
**Example** (Enrich contacts with company data):
|
|
263
|
+
```
|
|
264
|
+
1. Schedule (nightly at 3 AM)
|
|
265
|
+
|
|
266
|
+
2. Postgres (find contacts without company data)
|
|
267
|
+
SELECT id, email, domain FROM contacts
|
|
268
|
+
WHERE company_name IS NULL
|
|
269
|
+
AND created_at > NOW() - INTERVAL '7 days'
|
|
270
|
+
LIMIT 100
|
|
271
|
+
|
|
272
|
+
3. Split In Batches (10 contacts per batch)
|
|
273
|
+
|
|
274
|
+
4. HTTP Request (call Clearbit enrichment API)
|
|
275
|
+
- For each contact domain
|
|
276
|
+
- Rate limit: wait 1 second between batches
|
|
277
|
+
|
|
278
|
+
5. Set (map API response to database schema)
|
|
279
|
+
|
|
280
|
+
6. Postgres (UPDATE contacts with company data)
|
|
281
|
+
|
|
282
|
+
7. Wait (1 second - rate limiting)
|
|
283
|
+
|
|
284
|
+
8. Loop (back to step 4 until all batches processed)
|
|
285
|
+
|
|
286
|
+
9. Email (summary: "Enriched X contacts")
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### 6. Backup Automation
|
|
290
|
+
**Flow**: Schedule → Export data → Compress → Store → Verify
|
|
291
|
+
|
|
292
|
+
**Example** (Database backup):
|
|
293
|
+
```
|
|
294
|
+
1. Schedule (daily at 2 AM)
|
|
295
|
+
|
|
296
|
+
2. Code (execute pg_dump)
|
|
297
|
+
const { exec } = require('child_process');
|
|
298
|
+
exec('pg_dump -h db.example.com mydb > backup.sql')
|
|
299
|
+
|
|
300
|
+
3. Code (compress backup)
|
|
301
|
+
const zlib = require('zlib');
|
|
302
|
+
// Compress backup.sql to backup.sql.gz
|
|
303
|
+
|
|
304
|
+
4. AWS S3 (upload compressed backup)
|
|
305
|
+
- Bucket: backups
|
|
306
|
+
- Key: db/backup-{{$now.format('YYYY-MM-DD')}}.sql.gz
|
|
307
|
+
|
|
308
|
+
5. AWS S3 (list old backups)
|
|
309
|
+
- Keep last 30 days only
|
|
310
|
+
|
|
311
|
+
6. AWS S3 (delete old backups)
|
|
312
|
+
|
|
313
|
+
7. IF (error occurred)
|
|
314
|
+
├─ PagerDuty (critical alert)
|
|
315
|
+
└─ Email (backup failed!)
|
|
316
|
+
ELSE
|
|
317
|
+
└─ Slack (#devops: "✅ Backup completed")
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### 7. Content Publishing
|
|
321
|
+
**Flow**: Schedule → Fetch content → Format → Publish
|
|
322
|
+
|
|
323
|
+
**Example** (Automated social media posts):
|
|
324
|
+
```
|
|
325
|
+
1. Schedule (every 3 hours during business hours)
|
|
326
|
+
- Cron: 0 9,12,15,18 * * 1-5
|
|
327
|
+
|
|
328
|
+
2. Google Sheets (read content queue)
|
|
329
|
+
- Sheet: "Scheduled Posts"
|
|
330
|
+
- Filter: status=pending AND publish_time <= NOW()
|
|
331
|
+
|
|
332
|
+
3. IF (posts available)
|
|
333
|
+
|
|
334
|
+
4. HTTP Request (shorten URLs in post)
|
|
335
|
+
|
|
336
|
+
5. HTTP Request (POST to Twitter API)
|
|
337
|
+
|
|
338
|
+
6. HTTP Request (POST to LinkedIn API)
|
|
339
|
+
|
|
340
|
+
7. Google Sheets (update status=published)
|
|
341
|
+
|
|
342
|
+
8. Slack (notify #marketing: "Posted: {{$json.title}}")
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Timezone Considerations
|
|
348
|
+
|
|
349
|
+
### Set Workflow Timezone
|
|
350
|
+
```javascript
|
|
351
|
+
// In workflow settings
|
|
352
|
+
{
|
|
353
|
+
timezone: "America/New_York" // EST/EDT
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Common Timezones
|
|
358
|
+
```
|
|
359
|
+
America/New_York - Eastern (US)
|
|
360
|
+
America/Chicago - Central (US)
|
|
361
|
+
America/Denver - Mountain (US)
|
|
362
|
+
America/Los_Angeles - Pacific (US)
|
|
363
|
+
Europe/London - GMT/BST
|
|
364
|
+
Europe/Paris - CET/CEST
|
|
365
|
+
Asia/Tokyo - JST
|
|
366
|
+
Australia/Sydney - AEDT
|
|
367
|
+
UTC - Universal Time
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Handle Daylight Saving
|
|
371
|
+
**Best practice**: Use timezone-aware scheduling
|
|
372
|
+
|
|
373
|
+
```javascript
|
|
374
|
+
// ❌ Bad: UTC schedule for "9 AM local"
|
|
375
|
+
// Will be off by 1 hour during DST transitions
|
|
376
|
+
|
|
377
|
+
// ✅ Good: Set workflow timezone
|
|
378
|
+
{
|
|
379
|
+
timezone: "America/New_York",
|
|
380
|
+
schedule: {
|
|
381
|
+
mode: "daysAndHours",
|
|
382
|
+
hour: 9 // Always 9 AM Eastern, regardless of DST
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## Error Handling
|
|
390
|
+
|
|
391
|
+
### Pattern 1: Error Trigger Workflow
|
|
392
|
+
**Main workflow**: Normal execution
|
|
393
|
+
**Error workflow**: Alerts and recovery
|
|
394
|
+
|
|
395
|
+
**Main**:
|
|
396
|
+
```
|
|
397
|
+
Schedule → Fetch → Process → Deliver
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
**Error**:
|
|
401
|
+
```
|
|
402
|
+
Error Trigger (for main workflow)
|
|
403
|
+
→ Set (extract error details)
|
|
404
|
+
→ Slack (#ops-team: "❌ Scheduled job failed")
|
|
405
|
+
→ Email (admin alert)
|
|
406
|
+
→ Postgres (log error for analysis)
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Pattern 2: Retry with Backoff
|
|
410
|
+
```
|
|
411
|
+
Schedule → HTTP Request (continueOnFail: true)
|
|
412
|
+
→ IF (error)
|
|
413
|
+
├─ Wait (5 minutes)
|
|
414
|
+
├─ HTTP Request (retry 1)
|
|
415
|
+
└─ IF (still error)
|
|
416
|
+
├─ Wait (15 minutes)
|
|
417
|
+
├─ HTTP Request (retry 2)
|
|
418
|
+
└─ IF (still error)
|
|
419
|
+
└─ Alert admin
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Pattern 3: Partial Failure Handling
|
|
423
|
+
```
|
|
424
|
+
Schedule → Split In Batches
|
|
425
|
+
→ Process (continueOnFail: true)
|
|
426
|
+
→ Code (track successes and failures)
|
|
427
|
+
→ Report:
|
|
428
|
+
"✅ Processed: 95/100"
|
|
429
|
+
"❌ Failed: 5/100"
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## Performance Optimization
|
|
435
|
+
|
|
436
|
+
### 1. Batch Processing
|
|
437
|
+
For large datasets:
|
|
438
|
+
|
|
439
|
+
```
|
|
440
|
+
Schedule → Query (LIMIT 10000)
|
|
441
|
+
→ Split In Batches (100 items)
|
|
442
|
+
→ Process batch
|
|
443
|
+
→ Loop
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### 2. Parallel Processing
|
|
447
|
+
When operations are independent:
|
|
448
|
+
|
|
449
|
+
```
|
|
450
|
+
Schedule
|
|
451
|
+
├─ [Branch 1: Update DB]
|
|
452
|
+
├─ [Branch 2: Send emails]
|
|
453
|
+
└─ [Branch 3: Generate report]
|
|
454
|
+
→ Merge (wait for all) → Final notification
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### 3. Skip if Already Running
|
|
458
|
+
Prevent overlapping executions:
|
|
459
|
+
|
|
460
|
+
```
|
|
461
|
+
Schedule → Redis (check lock)
|
|
462
|
+
→ IF (lock exists)
|
|
463
|
+
└─ End (skip this execution)
|
|
464
|
+
→ ELSE
|
|
465
|
+
├─ Redis (set lock, TTL 30 min)
|
|
466
|
+
├─ [Execute workflow]
|
|
467
|
+
└─ Redis (delete lock)
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### 4. Early Exit on No Data
|
|
471
|
+
Don't waste time if nothing to process:
|
|
472
|
+
|
|
473
|
+
```
|
|
474
|
+
Schedule → Query (check if work exists)
|
|
475
|
+
→ IF (no results)
|
|
476
|
+
└─ End workflow (exit early)
|
|
477
|
+
→ ELSE
|
|
478
|
+
└─ Process data
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
## Monitoring & Logging
|
|
484
|
+
|
|
485
|
+
### Pattern 1: Execution Log Table
|
|
486
|
+
```sql
|
|
487
|
+
CREATE TABLE workflow_executions (
|
|
488
|
+
id SERIAL PRIMARY KEY,
|
|
489
|
+
workflow_name VARCHAR(255),
|
|
490
|
+
started_at TIMESTAMP,
|
|
491
|
+
completed_at TIMESTAMP,
|
|
492
|
+
status VARCHAR(50),
|
|
493
|
+
records_processed INT,
|
|
494
|
+
error_message TEXT
|
|
495
|
+
);
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
**Log execution**:
|
|
499
|
+
```
|
|
500
|
+
Schedule
|
|
501
|
+
→ Set (record start)
|
|
502
|
+
→ [Workflow logic]
|
|
503
|
+
→ Postgres (INSERT execution log)
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Pattern 2: Metrics Collection
|
|
507
|
+
```
|
|
508
|
+
Schedule → [Execute]
|
|
509
|
+
→ Code (calculate metrics)
|
|
510
|
+
- Duration
|
|
511
|
+
- Records processed
|
|
512
|
+
- Success rate
|
|
513
|
+
→ HTTP Request (send to monitoring system)
|
|
514
|
+
- Datadog, Prometheus, etc.
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Pattern 3: Summary Notifications
|
|
518
|
+
Daily/weekly execution summaries:
|
|
519
|
+
|
|
520
|
+
```
|
|
521
|
+
Schedule (daily at 6 PM) → Query execution logs
|
|
522
|
+
→ Code (aggregate today's executions)
|
|
523
|
+
→ Email (summary report)
|
|
524
|
+
"Today's Workflow Executions:
|
|
525
|
+
- 24/24 successful
|
|
526
|
+
- 0 failures
|
|
527
|
+
- Avg duration: 2.3 min"
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## Testing Scheduled Workflows
|
|
533
|
+
|
|
534
|
+
### 1. Use Manual Trigger for Testing
|
|
535
|
+
**Development pattern**:
|
|
536
|
+
```
|
|
537
|
+
Manual Trigger (for testing)
|
|
538
|
+
→ [Same workflow logic]
|
|
539
|
+
→ [Outputs]
|
|
540
|
+
|
|
541
|
+
// Once tested, replace with Schedule Trigger
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### 2. Test with Different Times
|
|
545
|
+
```javascript
|
|
546
|
+
// Code node - simulate different times
|
|
547
|
+
const testTime = new Date('2024-01-15T09:00:00Z');
|
|
548
|
+
return [{ json: { currentTime: testTime } }];
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### 3. Dry Run Mode
|
|
552
|
+
```
|
|
553
|
+
Schedule → Set (dryRun: true)
|
|
554
|
+
→ IF (dryRun)
|
|
555
|
+
└─ Log what would happen (don't execute)
|
|
556
|
+
→ ELSE
|
|
557
|
+
└─ Execute normally
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### 4. Shorter Interval for Testing
|
|
561
|
+
```javascript
|
|
562
|
+
// Testing: every 1 minute
|
|
563
|
+
{
|
|
564
|
+
mode: "interval",
|
|
565
|
+
interval: 1,
|
|
566
|
+
unit: "minutes"
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// Production: every 1 hour
|
|
570
|
+
{
|
|
571
|
+
mode: "interval",
|
|
572
|
+
interval: 1,
|
|
573
|
+
unit: "hours"
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
## Common Gotchas
|
|
580
|
+
|
|
581
|
+
### 1. ❌ Wrong: Ignoring timezone
|
|
582
|
+
```javascript
|
|
583
|
+
Schedule (9 AM) // 9 AM in which timezone?
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### ✅ Correct: Set workflow timezone
|
|
587
|
+
```javascript
|
|
588
|
+
// Workflow settings
|
|
589
|
+
{
|
|
590
|
+
timezone: "America/New_York"
|
|
591
|
+
}
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### 2. ❌ Wrong: Overlapping executions
|
|
595
|
+
```
|
|
596
|
+
Schedule (every 5 min) → Long-running task (10 min)
|
|
597
|
+
// Two executions running simultaneously!
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### ✅ Correct: Add execution lock
|
|
601
|
+
```
|
|
602
|
+
Schedule → Redis (check lock)
|
|
603
|
+
→ IF (locked) → Skip
|
|
604
|
+
→ ELSE → Execute
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
### 3. ❌ Wrong: No error handling
|
|
608
|
+
```
|
|
609
|
+
Schedule → API call → Process (fails silently)
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
### ✅ Correct: Add error workflow
|
|
613
|
+
```
|
|
614
|
+
Main: Schedule → Execute
|
|
615
|
+
Error: Error Trigger → Alert
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### 4. ❌ Wrong: Processing all data at once
|
|
619
|
+
```
|
|
620
|
+
Schedule → SELECT 1000000 records → Process (OOM)
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
### ✅ Correct: Batch processing
|
|
624
|
+
```
|
|
625
|
+
Schedule → SELECT with pagination → Split In Batches → Process
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### 5. ❌ Wrong: Hardcoded dates
|
|
629
|
+
```javascript
|
|
630
|
+
query: "SELECT * FROM orders WHERE date = '2024-01-15'"
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
### ✅ Correct: Dynamic dates
|
|
634
|
+
```javascript
|
|
635
|
+
query: "SELECT * FROM orders WHERE date = CURRENT_DATE - INTERVAL '1 day'"
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
640
|
+
## Real Template Examples
|
|
641
|
+
|
|
642
|
+
From n8n template library:
|
|
643
|
+
|
|
644
|
+
**Template #2947** (Weather to Slack):
|
|
645
|
+
```
|
|
646
|
+
Schedule (daily 8 AM)
|
|
647
|
+
→ HTTP Request (weather API)
|
|
648
|
+
→ Set (format message)
|
|
649
|
+
→ Slack (post to #general)
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
**Daily backup**:
|
|
653
|
+
```
|
|
654
|
+
Schedule (nightly 2 AM)
|
|
655
|
+
→ Postgres (export data)
|
|
656
|
+
→ Google Drive (upload)
|
|
657
|
+
→ Email (confirmation)
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
**Monitoring**:
|
|
661
|
+
```
|
|
662
|
+
Schedule (every 5 min)
|
|
663
|
+
→ HTTP Request (health check)
|
|
664
|
+
→ IF (down) → PagerDuty alert
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
Use `search_templates({query: "schedule"})` to find more!
|
|
668
|
+
|
|
669
|
+
---
|
|
670
|
+
|
|
671
|
+
## Checklist for Scheduled Workflows
|
|
672
|
+
|
|
673
|
+
### Planning
|
|
674
|
+
- [ ] Define schedule frequency (interval, cron, days & hours)
|
|
675
|
+
- [ ] Set workflow timezone
|
|
676
|
+
- [ ] Estimate execution duration
|
|
677
|
+
- [ ] Plan for failures and retries
|
|
678
|
+
- [ ] Consider timezone and DST
|
|
679
|
+
|
|
680
|
+
### Implementation
|
|
681
|
+
- [ ] Configure Schedule Trigger
|
|
682
|
+
- [ ] Set workflow timezone in settings
|
|
683
|
+
- [ ] Add early exit for no-op cases
|
|
684
|
+
- [ ] Implement batch processing for large data
|
|
685
|
+
- [ ] Add execution logging
|
|
686
|
+
|
|
687
|
+
### Error Handling
|
|
688
|
+
- [ ] Create Error Trigger workflow
|
|
689
|
+
- [ ] Implement retry logic
|
|
690
|
+
- [ ] Add alert notifications
|
|
691
|
+
- [ ] Log errors for analysis
|
|
692
|
+
- [ ] Handle partial failures gracefully
|
|
693
|
+
|
|
694
|
+
### Monitoring
|
|
695
|
+
- [ ] Log each execution (start, end, status)
|
|
696
|
+
- [ ] Track metrics (duration, records, success rate)
|
|
697
|
+
- [ ] Set up daily/weekly summaries
|
|
698
|
+
- [ ] Alert on consecutive failures
|
|
699
|
+
- [ ] Monitor resource usage
|
|
700
|
+
|
|
701
|
+
### Testing
|
|
702
|
+
- [ ] Test with Manual Trigger first
|
|
703
|
+
- [ ] Verify timezone behavior
|
|
704
|
+
- [ ] Test error scenarios
|
|
705
|
+
- [ ] Check for overlapping executions
|
|
706
|
+
- [ ] Validate output quality
|
|
707
|
+
|
|
708
|
+
### Deployment
|
|
709
|
+
- [ ] Document workflow purpose
|
|
710
|
+
- [ ] Set up monitoring
|
|
711
|
+
- [ ] Configure alerts
|
|
712
|
+
- [ ] Activate workflow in n8n UI ⚠️ **Manual activation required** (API/MCP cannot activate)
|
|
713
|
+
- [ ] Test in production (short interval first)
|
|
714
|
+
- [ ] Monitor first few executions
|
|
715
|
+
|
|
716
|
+
---
|
|
717
|
+
|
|
718
|
+
## Advanced Patterns
|
|
719
|
+
|
|
720
|
+
### Dynamic Scheduling
|
|
721
|
+
**Change schedule based on conditions**:
|
|
722
|
+
|
|
723
|
+
```
|
|
724
|
+
Schedule (check every hour) → Code (check if it's time to run)
|
|
725
|
+
→ IF (business hours AND weekday)
|
|
726
|
+
└─ Execute workflow
|
|
727
|
+
→ ELSE
|
|
728
|
+
└─ Skip
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
### Dependent Schedules
|
|
732
|
+
**Chain workflows**:
|
|
733
|
+
|
|
734
|
+
```
|
|
735
|
+
Workflow A (daily 2 AM): Data sync
|
|
736
|
+
→ On completion → Trigger Workflow B
|
|
737
|
+
|
|
738
|
+
Workflow B: Generate report (depends on fresh data)
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### Conditional Execution
|
|
742
|
+
**Skip based on external factors**:
|
|
743
|
+
|
|
744
|
+
```
|
|
745
|
+
Schedule → HTTP Request (check feature flag)
|
|
746
|
+
→ IF (feature enabled)
|
|
747
|
+
└─ Execute
|
|
748
|
+
→ ELSE
|
|
749
|
+
└─ Skip
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
---
|
|
753
|
+
|
|
754
|
+
## Summary
|
|
755
|
+
|
|
756
|
+
**Key Points**:
|
|
757
|
+
1. **Set workflow timezone** explicitly
|
|
758
|
+
2. **Batch processing** for large datasets
|
|
759
|
+
3. **Error handling** is critical (Error Trigger + retries)
|
|
760
|
+
4. **Prevent overlaps** with execution locks
|
|
761
|
+
5. **Monitor and log** all executions
|
|
762
|
+
|
|
763
|
+
**Pattern**: Schedule → Fetch → Process → Deliver → Log
|
|
764
|
+
|
|
765
|
+
**Schedule Modes**:
|
|
766
|
+
- **Interval**: Simple recurring (every X minutes/hours)
|
|
767
|
+
- **Days & Hours**: Specific days and times
|
|
768
|
+
- **Cron**: Advanced complex schedules
|
|
769
|
+
|
|
770
|
+
**Related**:
|
|
771
|
+
- [http_api_integration.md](http_api_integration.md) - Fetching data on schedule
|
|
772
|
+
- [database_operations.md](database_operations.md) - Scheduled database tasks
|
|
773
|
+
- [webhook_processing.md](webhook_processing.md) - Alternative to scheduling
|