Skip to content

Commit 521dc47

Browse files
committed
feat(story-1-11): implement webhook trigger with GORM storage
- Add pkg/trigger package: types, filter engine, GORM models, store, manager - Add trigger/webhook HTTP handlers and register 9 API endpoints - Add schedule handler (story-1-10) - Refactor storage layer from SQLite to GORM + PostgreSQL - Update database.go to auto-migrate triggers and webhook_logs tables - Fix duplicate trigger HTTP status 404 -> 409 Conflict - Add GET /v1/workflows/{name}/triggers/{id}/logs endpoint - Update OpenAPI spec, docs and sprint artifacts
1 parent efb5596 commit 521dc47

27 files changed

Lines changed: 7005 additions & 950 deletions

agent

43.8 MB
Binary file not shown.

api/openapi.yaml

Lines changed: 433 additions & 0 deletions
Large diffs are not rendered by default.

deployments/docker-compose.yaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ services:
103103
WATERFLOW_TEMPORAL_TASKQUEUE: ${WATERFLOW_TEMPORAL_TASKQUEUE:-waterflow-server}
104104
WATERFLOW_LOG_LEVEL: ${WATERFLOW_LOG_LEVEL:-info}
105105
WATERFLOW_LOG_FORMAT: ${WATERFLOW_LOG_FORMAT:-json}
106+
107+
# Database Configuration (for workflow definitions storage)
108+
WATERFLOW_DATABASE_ENABLED: ${WATERFLOW_DATABASE_ENABLED:-true}
109+
WATERFLOW_DATABASE_HOST: ${WATERFLOW_DATABASE_HOST:-postgresql}
110+
WATERFLOW_DATABASE_PORT: ${WATERFLOW_DATABASE_PORT:-5432}
111+
WATERFLOW_DATABASE_USER: ${WATERFLOW_DATABASE_USER:-temporal}
112+
WATERFLOW_DATABASE_PASSWORD: ${WATERFLOW_DATABASE_PASSWORD:-temporal}
113+
WATERFLOW_DATABASE_DATABASE: ${WATERFLOW_DATABASE_DATABASE:-waterflow}
114+
WATERFLOW_DATABASE_SSLMODE: ${WATERFLOW_DATABASE_SSLMODE:-disable}
106115
ports:
107116
- "${WATERFLOW_SERVER_PORT:-8080}:8080"
108117
healthcheck:
@@ -155,7 +164,7 @@ services:
155164
volumes:
156165
- agent-plugins:/app/plugins:ro
157166
healthcheck:
158-
test: [ "CMD", "wget", "-q", "--spider", "http://localhost:9090/metrics", "||", "exit", "1" ]
167+
test: [ "CMD-SHELL", "wget -q -O /dev/null http://localhost:6061/debug/pprof/ || exit 1" ]
159168
interval: 15s
160169
timeout: 5s
161170
retries: 5

docs/api-inventory.md

Lines changed: 129 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
| **基础设施** | 4 | Story 1.2 |
2020
| **工作流定义** | 5 | Story 1.9 |
2121
| **工作流执行** | 7 | Story 1.9 |
22-
| **定时调度** | 6 | Story 1.10 |
22+
| **定时调度** | 9 | Story 1.10 |
2323
| **Webhook 触发** | 5 | Story 1.11 |
2424
| **模板管理** | 2 | Story 6.4 |
2525
| **节点管理** | 1 | Story 5.6 |
2626
| **YAML 验证** | 1 | Story 5.2 |
2727
| **审计日志** | 1 | Story 9.3 |
28-
| **总计** | **32** | - |
28+
| **总计** | **35** | - |
2929

3030
---
3131

@@ -267,24 +267,25 @@ Content-Type: application/json
267267

268268
---
269269

270-
## 4️⃣ 定时调度 API (6 个) - Story 1.10
270+
## 4️⃣ 定时调度 API (9 个) - Story 1.10
271271

272-
> **说明**: Schedule 挂载在工作流定义下,引用而非复制 YAML。
272+
> **说明**: Schedule 挂载在工作流定义下,引用而非复制 YAML。
273+
> **架构**: 完全基于 Temporal Schedules API,无数据库依赖。
273274
274275
### 4.1 创建 Schedule
275276
```
276277
POST /v1/workflows/{name}/schedules
277278
Content-Type: application/json
278279
279280
{
280-
"schedule_id": "nightly-deploy",
281+
"name": "nightly-deploy",
281282
"cron": "0 2 * * *",
282283
"timezone": "Asia/Shanghai",
283284
"vars": {
284285
"env": "production"
285286
},
286287
"overlap_policy": "skip",
287-
"enabled": true
288+
"memo": "每日凌晨 2 点部署"
288289
}
289290
```
290291
- **用途**: 为工作流定义创建定时调度
@@ -295,27 +296,72 @@ Content-Type: application/json
295296
"workflow_name": "deploy-app",
296297
"cron": "0 2 * * *",
297298
"timezone": "Asia/Shanghai",
299+
"overlap_policy": "skip",
300+
"status": "active",
298301
"vars": {"env": "production"},
299-
"next_run_time": "2026-02-04T02:00:00+08:00",
300-
"enabled": true
302+
"memo": "每日凌晨 2 点部署",
303+
"next_run_time": "2026-02-06T02:00:00+08:00",
304+
"created_at": "2026-02-05T10:00:00Z"
301305
}
302306
```
303-
- **vars**: 执行时覆盖 YAML 默认值
307+
- **vars**: 执行时覆盖 YAML 默认值(优先级: Trigger vars > Schedule vars > YAML vars)
308+
- **overlap_policy**: `skip`(跳过)、`allow_all`(并发)、`buffer_one`(缓冲一次)
304309
- **404**: 工作流定义不存在
310+
- **409**: Schedule 名称冲突
305311

306312
### 4.2 列出 Schedules
307313
```
308314
GET /v1/workflows/{name}/schedules
315+
GET /v1/workflows/{name}/schedules?status=active&page=1&limit=20
309316
```
310317
- **用途**: 列出工作流的所有 Schedules
311-
- **返回**: Schedule 列表
318+
- **过滤参数**:
319+
- `status`: active, paused
320+
- `page`, `limit`: 分页参数
321+
- **返回**: Schedule 列表 + 分页元数据
322+
```json
323+
{
324+
"schedules": [
325+
{
326+
"schedule_id": "nightly-deploy",
327+
"workflow_name": "deploy-app",
328+
"cron": "0 2 * * *",
329+
"status": "active",
330+
"next_run_time": "2026-02-06T02:00:00+08:00"
331+
}
332+
],
333+
"meta": {
334+
"total": 3,
335+
"page": 1,
336+
"limit": 20,
337+
"total_pages": 1
338+
}
339+
}
340+
```
312341

313342
### 4.3 查询 Schedule 详情
314343
```
315344
GET /v1/workflows/{name}/schedules/{schedule_id}
316345
```
317-
- **用途**: 查询单个 Schedule
318-
- **返回**: 完整 Schedule 信息 + 最近执行历史
346+
- **用途**: 查询单个 Schedule 详细信息
347+
- **返回**: 完整 Schedule 信息 + 下次执行时间
348+
```json
349+
{
350+
"schedule_id": "nightly-deploy",
351+
"workflow_name": "deploy-app",
352+
"cron": "0 2 * * *",
353+
"timezone": "Asia/Shanghai",
354+
"overlap_policy": "skip",
355+
"status": "active",
356+
"vars": {"env": "production"},
357+
"memo": "每日凌晨 2 点部署",
358+
"next_run_time": "2026-02-06T02:00:00+08:00",
359+
"last_run_time": "2026-02-05T02:00:00+08:00",
360+
"created_at": "2026-02-01T10:00:00Z",
361+
"updated_at": "2026-02-03T15:30:00Z"
362+
}
363+
```
364+
- **404**: Schedule 不存在
319365

320366
### 4.4 更新 Schedule
321367
```
@@ -324,33 +370,96 @@ Content-Type: application/json
324370
325371
{
326372
"cron": "0 3 * * *",
373+
"timezone": "America/New_York",
327374
"vars": {"env": "staging"},
328-
"enabled": false
375+
"memo": "改为纽约时区凌晨 3 点"
329376
}
330377
```
331-
- **用途**: 更新 Schedule 配置
378+
- **用途**: 更新 Schedule 配置(支持部分更新)
332379
- **返回**: 200 OK + 更新后的 Schedule
380+
- **404**: Schedule 不存在
333381

334382
### 4.5 删除 Schedule
335383
```
336384
DELETE /v1/workflows/{name}/schedules/{schedule_id}
337385
```
338386
- **用途**: 删除 Schedule
339387
- **返回**: 204 No Content
340-
- **行为**: 不影响正在运行的执行
388+
- **行为**:
389+
- 立即停止后续触发
390+
- 不影响正在运行的工作流执行
391+
- 从 Temporal 中永久删除
392+
- **404**: Schedule 不存在
341393

342-
### 4.6 手动触发 Schedule
394+
### 4.6 暂停 Schedule
395+
```
396+
POST /v1/workflows/{name}/schedules/{schedule_id}/pause
397+
Content-Type: application/json
398+
399+
{
400+
"reason": "系统维护中"
401+
}
402+
```
403+
- **用途**: 暂停 Schedule(不再触发新执行)
404+
- **返回**: 204 No Content
405+
- **行为**:
406+
- Status 变为 `paused`
407+
- 不删除 Schedule,可恢复
408+
- **404**: Schedule 不存在
409+
410+
### 4.7 恢复 Schedule
411+
```
412+
POST /v1/workflows/{name}/schedules/{schedule_id}/resume
413+
```
414+
- **用途**: 恢复已暂停的 Schedule
415+
- **返回**: 204 No Content
416+
- **行为**:
417+
- Status 变为 `active`
418+
- 按 Cron 表达式正常触发
419+
- **404**: Schedule 不存在
420+
421+
### 4.8 手动触发 Schedule
343422
```
344423
POST /v1/workflows/{name}/schedules/{schedule_id}/trigger
345424
Content-Type: application/json
346425
347426
{
348-
"vars": {"version": "1.2.4"}
427+
"vars": {"version": "1.2.4", "urgent": true}
428+
}
429+
```
430+
- **用途**: 立即触发一次执行(不影响 Cron 计划)
431+
- **返回**: 202 Accepted
432+
```json
433+
{
434+
"workflow_id": "wf_20260205_abc123"
435+
}
436+
```
437+
- **vars**: 可选,最高优先级覆盖(Trigger vars > Schedule vars > YAML vars)
438+
- **404**: Schedule 不存在
439+
440+
### 4.9 列出 Schedule 执行历史
441+
```
442+
GET /v1/workflows/{name}/schedules/{schedule_id}/executions
443+
GET /v1/workflows/{name}/schedules/{schedule_id}/executions?limit=10
444+
```
445+
- **用途**: 查询 Schedule 触发的工作流执行历史
446+
- **返回**: 执行列表(按时间倒序)
447+
```json
448+
{
449+
"executions": [
450+
{
451+
"workflow_id": "wf_20260205_abc123",
452+
"status": "completed",
453+
"started_at": "2026-02-05T02:00:00Z",
454+
"completed_at": "2026-02-05T02:05:23Z"
455+
}
456+
],
457+
"meta": {
458+
"total": 30,
459+
"limit": 10
460+
}
349461
}
350462
```
351-
- **用途**: 立即触发一次执行
352-
- **返回**: 202 Accepted + execution_id
353-
- **vars**: 可选,覆盖 Schedule 绑定的 vars
354463

355464
---
356465

docs/quick-start.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,129 @@ curl -X POST http://localhost:8080/v1/workflows \
332332

333333
**完整模板文档:** [工作流模板库](./templates/README.md)
334334

335+
## ⏰ 创建定时调度
336+
337+
### 基础调度示例
338+
339+
为工作流创建定时任务,实现自动化执行:
340+
341+
```bash
342+
# 1. 创建工作流定义
343+
curl -X POST http://localhost:8080/v1/workflows/definitions \
344+
-H "Content-Type: application/json" \
345+
-d '{
346+
"name": "daily-backup",
347+
"content": "name: daily-backup\nvars:\n backup_dir: /tmp\njobs:\n backup:\n runs-on: default\n steps:\n - name: Run Backup\n uses: exec@v1\n with:\n command: echo \"Backup to ${backup_dir}\""
348+
}'
349+
350+
# 2. 创建每日调度(凌晨 2 点执行)
351+
curl -X POST http://localhost:8080/v1/workflows/daily-backup/schedules \
352+
-H "Content-Type: application/json" \
353+
-d '{
354+
"name": "nightly-backup",
355+
"cron": "0 2 * * *",
356+
"timezone": "Asia/Shanghai",
357+
"vars": {
358+
"backup_dir": "/data/backups"
359+
},
360+
"memo": "每日凌晨 2 点自动备份"
361+
}'
362+
363+
# 3. 查看调度详情
364+
curl http://localhost:8080/v1/workflows/daily-backup/schedules/nightly-backup
365+
```
366+
367+
### 常用 Cron 表达式
368+
369+
| 表达式 | 说明 |
370+
|--------|------|
371+
| `0 * * * *` | 每小时整点 |
372+
| `0 2 * * *` | 每天凌晨 2 点 |
373+
| `0 9 * * 1` | 每周一上午 9 点 |
374+
| `0 0 1 * *` | 每月 1 号零点 |
375+
| `*/15 * * * *` | 每 15 分钟 |
376+
377+
### 参数覆盖机制
378+
379+
调度支持三层参数合并(优先级从低到高):
380+
381+
```yaml
382+
# 1. 工作流 YAML 定义的默认参数
383+
name: backup-workflow
384+
vars:
385+
backup_dir: /tmp # 默认值
386+
retention_days: 7 # 默认值
387+
```
388+
389+
```bash
390+
# 2. 调度创建时绑定的参数(覆盖 YAML vars)
391+
curl -X POST http://localhost:8080/v1/workflows/backup-workflow/schedules \
392+
-d '{
393+
"name": "prod-backup",
394+
"cron": "0 2 * * *",
395+
"vars": {
396+
"backup_dir": "/data/backups", # 覆盖默认值
397+
"retention_days": 30 # 覆盖默认值
398+
}
399+
}'
400+
401+
# 3. 手动触发时提供的参数(最高优先级)
402+
curl -X POST http://localhost:8080/v1/workflows/backup-workflow/schedules/prod-backup/trigger \
403+
-d '{
404+
"vars": {
405+
"backup_dir": "/mnt/emergency" # 临时覆盖
406+
}
407+
}'
408+
```
409+
410+
### 调度管理操作
411+
412+
```bash
413+
# 暂停调度(系统维护)
414+
curl -X POST http://localhost:8080/v1/workflows/daily-backup/schedules/nightly-backup/pause \
415+
-d '{"reason": "系统维护中"}'
416+
417+
# 恢复调度
418+
curl -X POST http://localhost:8080/v1/workflows/daily-backup/schedules/nightly-backup/resume
419+
420+
# 更新调度(修改 Cron 表达式)
421+
curl -X PUT http://localhost:8080/v1/workflows/daily-backup/schedules/nightly-backup \
422+
-d '{
423+
"cron": "0 3 * * *",
424+
"memo": "改为凌晨 3 点执行"
425+
}'
426+
427+
# 删除调度
428+
curl -X DELETE http://localhost:8080/v1/workflows/daily-backup/schedules/nightly-backup
429+
```
430+
431+
### 多调度场景
432+
433+
一个工作流可以创建多个调度:
434+
435+
```bash
436+
# 工作日备份(周一到周五)
437+
curl -X POST http://localhost:8080/v1/workflows/backup-workflow/schedules \
438+
-d '{
439+
"name": "weekday-backup",
440+
"cron": "0 2 * * 1-5",
441+
"vars": {"env": "production"}
442+
}'
443+
444+
# 周末备份(周六、周日)
445+
curl -X POST http://localhost:8080/v1/workflows/backup-workflow/schedules \
446+
-d '{
447+
"name": "weekend-backup",
448+
"cron": "0 4 * * 0,6",
449+
"vars": {"env": "staging"}
450+
}'
451+
452+
# 列出所有调度
453+
curl http://localhost:8080/v1/workflows/backup-workflow/schedules
454+
```
455+
456+
**详细文档:** [Schedule API 参考](api-guide.md#schedule-api)
457+
335458
## 📚 下一步
336459

337460
- 📖 [完整部署文档](deployment.md) - 详细配置和故障排查

0 commit comments

Comments
 (0)