mcpField
U
upstash-workflow

upstash-workflow

github.com/lobehub开发83.6k2.3k 次安装今天更新
代码仓库

关于 upstash-workflow

为 LobeHub 代码库提供 Upstash Workflow 与 QStash 异步工作流实现指南,面向开发者。内容围绕预演、分批扇出和单项执行,涵盖分层结构与实现参考。

主要功能

  1. 01预演模式与处理统计
  2. 02大批次分页和扇出
  3. 03每次执行处理单个项目
  4. 04三层工作流架构
  5. 05实现与部署参考指南

适用场景

  1. 01提交前查看待处理项目数量
  2. 02拆分批次以避免步骤限制
  3. 03实现可重试且避免重复处理的流程

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/lobehub/lobehub --skill upstash-workflow

安装后在 Claude Code 中输入/upstash-workflow确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
best-practices.md
cloud.md
examples.md
implementation.md

详细介绍

Upstash Workflow 实现指南

在 LobeHub 代码库中实现 Upstash Workflow + QStash 异步工作流的标准模式。

🎯 三种核心模式

LobeHub 中的每个工作流都结合了这三种模式。它们之所以存在,是因为平台有三方面的限制:速率限制意味着盲目扇出存在风险,步骤数量限制了单个工作流的规模,而幂等性要求重试时不能重复处理。

  1. 🔍 Dry-Run 模式 — 获取统计信息,但不触发实际执行
  2. 🌟 扇出模式 — 将大型批次拆分为较小的块,以便并行处理
  3. 🎯 单任务执行 — 每次工作流执行恰好处理一项

架构概览

所有工作流都遵循相同的三层架构:

Layer 1: Entry Point (process-*)
  ├─ Validates prerequisites
  ├─ Calculates total items to process
  ├─ Filters existing items
  ├─ Supports dry-run mode (statistics only)
  └─ Triggers Layer 2 if work is needed

Layer 2: Pagination (paginate-*)
  ├─ Handles cursor-based pagination
  ├─ Implements fan-out for large batches
  ├─ Recursively processes all pages
  └─ Triggers Layer 3 for each item

Layer 3: Single Task Execution (execute-* / generate-*)
  └─ Performs actual business logic for ONE item

此代码库中的实际示例: topicAutoSummary、agentEvalRun — 请参阅 references/examples.md。


60 秒了解三种模式

1. Dry-Run 模式

在产生任何副作用之前,于第 1 层提前返回,让调用方预览将要发生的操作:

if (dryRun) {
  return {
    ...result,
    dryRun: true,
    message: `[DryRun] Would process ${itemsNeedingProcessing.length} items`,
  };
}

适用场景:在确认执行前检查将处理多少项。

2. 扇出模式

第 2 层将超大批次拆分为多个块,并使用每个块递归地重新触发自身。当单页包含过多项目时,这可以避免触及工作流步骤数量限制:

const CHUNK_SIZE = 20;

if (itemIds.length > CHUNK_SIZE) {
  const chunks = chunk(itemIds, CHUNK_SIZE);
  await Promise.all(
    chunks.map((ids, idx) =>
      context.run(`workflow:fanout:${idx + 1}/${chunks.length}`, () =>
        WorkflowClass.triggerPaginateItems({ itemIds: ids }),
      ),
    ),
  );
}

默认值:PAGE_SIZE = 50(每页的项目数),CHUNK_SIZE = 20(每个扇出块的项目数)。

3. 单任务执行

第 3 层每次调用始终恰好处理一项。并行处理由第 2 层扇出并调用多个第 3 层实例实现,并通过 flowControl 控制:

app.post(
  '/execute-item',
  serve<ExecutePayload>(
    async (context) => {
      const { itemId } = context.requestPayload ?? {};
      if (!itemId) return { success: false, error: 'Missing itemId' };

      const item = await context.run('workflow:get-item', () => getItem(itemId));
      const result = await context.run('workflow:execute', () => processItem(item));
      await context.run('workflow:save', () => saveResult(itemId, result));

      return { success: true, itemId, result };
    },
    {
      flowControl: { key: 'workflow.execute', parallelism: 10, ratePerSecond: 5 },
    },
  ),
);

文件结构

src/app/(backend)/api/workflows/
└── [[...route]]/route.ts             # Single catch-all — forwards every request to the Hono app below

apps/server/src/router-hono/workflows/
├── index.ts                          # Mounts each workflow's Hono app at /api/workflows/{workflow-name}
└── {workflow-name}/
    ├── index.ts                       # Hono app — one `app.post('/{layer}', serve(handler, options))` per layer
    ├── dispatch.ts / paginate-*.ts    # Layer 1 + 2 handler(s) — entry point, dry-run, pagination, fan-out
    └── execute.ts / execute-*.ts      # Layer 3 handler — single-task execution

apps/server/src/workflows/
└── {workflowName}/
    └── index.ts                       # Workflow class — static trigger*() methods that POST to the routes above

每一层都是挂载在 apps/server/src/router-hono/workflows/ 下、按工作流划分的 Hono 应用上的处理器;src/app 下的 Next.js 路由只负责向其分发请求。


后续阅读

选择与你当前任务对应的参考文档:

你想要……阅读
从头编写 Workflow 类和 3 个路由references/implementation.md
调整 flowControl、错误处理、日志和测试references/best-practices.md
查看两个完整的实际工作流references/examples.md
在 lobehub-cloud 上部署(重新导出、仅限云端的操作)references/cloud.md

环境变量

# Required for all workflows
APP_URL=https://your-app.com # Base URL for workflow endpoints
QSTASH_TOKEN=qstash_xxx      # QStash authentication token

# Optional (for custom QStash URL)
QSTASH_URL=https://custom-qstash.com

新建工作流检查清单

规划
  • 确定要处理的实体(用户、Agent、项目等)
  • 定义每项的业务逻辑
  • 确定筛选逻辑(Redis 缓存、数据库状态等)
实现
  • 使用 TypeScript 接口定义负载类型
  • 创建包含静态触发方法的工作流类
  • 第 1 层: 支持 dry-run 的入口
  • 第 1 层: 避免重复处理的筛选逻辑
  • 第 2 层: 使用 扇出 进行分页
  • 第 3 层: 单任务执行(每次运行处理一项)
  • 为每一层配置适当的 flowControl
  • 使用工作流前缀保持日志一致
  • 验证所有必需的负载参数
  • 确保 context.run() 步骤名称唯一
质量与部署
  • 返回结构一致的响应
  • 配置云端部署(如果使用 lobehub-cloud,请参阅 references/cloud.md)
  • 编写集成测试(dryRun 路径和完整路径)
  • 先使用 dry-run 进行冒烟测试
  • 全面上线前先使用小批次进行测试

其他资源

评论

支持 Markdown