更新记录

1.0.1(2026-11-11)

1.0.1

  • 重新打包上传,使云函数被平台正确识别并加密
  • 代码与 1.0.0 一致,无功能改动

1.0.0(2026-11-11)

首个版本。

  • 十个 action:register / begin / heartbeat / finish / retry / runs / detail / stats / clean
  • 任务配置与执行记录共用一个集合,只需上传一个 Schema
  • 同名防重,超时未心跳自动标记 timeout 并允许接管
  • 长任务心跳续期,重复 finish 不覆盖首次结果
  • 失败可按 attempt 重试,同一条失败只重试一次
  • 成功率、平均耗时、失败排行统计,附管理页

平台兼容性

云端兼容性

支付宝云 腾讯云 阿里云
× √ √

uniCloud 定时任务调度与执行留痕

零第三方依赖的 uniCloud 云端一体工具:任务注册、同名防重、执行开始与结束留痕、失败重试、超时接管、成功率与耗时统计,附一个开箱即用的管理页。

uniCloud 的定时触发负责「什么时候跑」,本插件负责「谁在跑、跑了多久、成功没有、失败了要不要重试」。适合有多个定时任务、需要知道昨晚那次结算到底跑没跑、以及怕重复执行的场景。

特性

  • 任务注册:每个任务可配超时时间、最大重试次数、是否允许并发
  • 同名防重:begin 时若已有未超时的 running 执行则拒绝;超时未心跳的自动标记 timeout 并允许接管
  • 完整留痕:开始 / 心跳 / 结束时间、耗时、尝试次数、状态、错误摘要、结果摘要
  • 失败重试:finish 返回是否可重试,retry 基于失败执行创建下一次尝试
  • 统计:成功率、平均耗时、运行中数量、失败排行
  • 不存业务正文:result 是摘要并有大小上限,error 截断,插件不执行业务代码
  • 零依赖:只用 uniCloud.database(),不引 npm 包或扩展库
  • 自带管理页:注册、开始、标记成功/失败、重试、统计、执行记录、清理过期

目录结构

uni_modules/aliang-schedule/
├── package.json                       插件配置(含定价与加密清单,只列 1 个 js)
├── pages_init.json                    自动注册管理页
├── readme.md / changelog.md
├── uniCloud/
│   ├── cloudfunctions/aliang-schedule/index.js   单文件云函数
│   └── database/
│       ├── cloud_schedule_runs.schema.json
│       └── cloud_schedule_runs.index.json    三个索引
└── pages/schedule/list.vue            管理页

任务配置与执行记录共用一个集合,用 kind 区分 task / run。单文件云函数的理由同系列产品:加密清单按文件配置,多文件漏配会明文外泄。

五分钟接入

第 0 步:在 uniCloud 服务空间配置环境变量:

SCHEDULE_TOKEN = 一个足够长的随机字符串

未配置时除 ping 外所有 action 拒绝,这是默认安全。

  1. 导入插件到 uni-app 项目。
  2. 上传 uniCloud/database/cloud_schedule_runs.schema.json。
  3. 右键 uniCloud/cloudfunctions/aliang-schedule → 上传部署。
  4. pages_init.json 会自动提示注册「任务调度」页。
  5. 在你的定时触发云函数里调用本插件(示例见下),管理平台只用来看结果。

试用 5 分钟自检(7 天试用内照做即可判定插件是否合用)

步骤 操作 预期结果
1 action: 'ping' configured: true,返回默认超时与重试次数
2 管理页填任务名,点「注册任务」 提示已注册,显示超时与最大重试
3 点「开始一次执行」 返回 runId,状态 running
4 不标记完成,再点一次「开始一次执行」 返回 acquired: false / already-running(同名防重生效)
5 点「标记失败」 提示可重试,执行记录状态 failed
6 点「重试」 生成新的 runId,attempt 加 1
7 统计卡片 成功率、运行中、失败数、平均耗时随操作变化

任一步不符,先看页面错误提示,再检查 SCHEDULE_TOKEN 与 Schema 是否上传。

环境变量

变量 默认 说明
SCHEDULE_TOKEN 空(必填) 所有 action 的令牌,只从环境变量读
SCHEDULE_COLLECTION cloud_schedule_runs 记录集合名,只从环境变量读
SCHEDULE_DEFAULT_TIMEOUT_MS 300000 默认执行超时(5 分钟)
SCHEDULE_DEFAULT_MAX_RETRIES 3 默认最大重试次数
SCHEDULE_MAX_RESULT 4000 结果摘要序列化上限,超限只记长度标记
SCHEDULE_RETENTION_DAYS 14 执行记录保留天数

超时、重试、结果上限、保留天数可用 data.config 覆盖;令牌与集合名不接受请求侧覆盖。

API 参考

云函数名 aliang-schedule,统一返回 { errCode: 0 | 字符串, errMsg, data },失败错误码以 aliang-schedule- 开头。

action 说明 主要参数 需要 token
ping 健康检查 — 否
register 注册 / 更新任务配置 name timeoutMs maxRetries allowConcurrent 是
begin 开始一次执行 name owner attempt 是
heartbeat 长任务心跳续期 runId 是
finish 结束执行 runId status(success/failed) result error 是
retry 基于失败执行创建下一次尝试 runId owner 是
runs 执行记录列表 task status page pageSize 是
detail 执行详情 + 任务配置 runId 是
stats 成功率、平均耗时、失败排行 — 是
clean 清理过期的已结束记录 — 是

状态:running / success / failed / timeout / abandoned。

在定时触发云函数里接入

const sched = (action, extra) => uniCloud.callFunction({
  name: 'aliang-schedule',
  data: Object.assign({ action, token: SCHEDULE_TOKEN }, extra)
}).then(r => r.result)

exports.main = async () => {
  const b = await sched('begin', { name: 'daily-settlement', owner: 'cron-settlement' })
  if (!b.data.acquired) return { errCode: 'skipped', errMsg: b.data.reason }

  const timer = setInterval(() => {
    sched('heartbeat', { runId: b.data.runId }).catch(() => {})
  }, 60000)

  try {
    const result = await doSettlement()
    clearInterval(timer)
    await sched('finish', { runId: b.data.runId, status: 'success', result: { count: result.count } })
    return { errCode: 0 }
  } catch (e) {
    clearInterval(timer)
    const f = await sched('finish', { runId: b.data.runId, status: 'failed', error: e.message })
    if (f.data.retryable) {
      // 可交给下一次触发,或立即调 retry 创建下一次尝试
    }
    throw e
  }
}

定时触发的参数由 uniCloud 控制台配置,令牌不要写进前端代码。heartbeat 用于长任务续期,短任务可以省掉。

安全与限制

  • 令牌与集合名只从环境变量读;任务名做了控制字符与长度约束。
  • 记录集合 permission 全为 false,前端无法直连。
  • 结果摘要有大小上限,超限只保留长度标记;error 截断到 1000 字符;不存业务正文。
  • clean 只删除已结束且过期的 run 记录,不会删除任务配置,也不会删除 running 状态的执行。
  • 同名防重是尽力而为:begin 先查再写,两个触发极端并发时仍可能同时通过。业务侧仍应自己保证幂等,或配合分布式锁插件。
  • 超时判断基于 heartbeat_at / started_at,长任务不心跳会被判定超时并允许被接管。
  • stats 的平均耗时基于最近 200 条记录,不是全量统计。
  • 第一版不提供 cron 表达式解析、任务编排与依赖链;调度时机由 uniCloud 定时触发负责。

常见问题

Q:报 token-required / unauthorized。 没配 SCHEDULE_TOKEN 或传的不一致,用 ping 确认。 Q:begin 返回 already-running。 同名任务已有执行中且未超时;确认上一次是否卡住,或调大 timeoutMs,或等待超时后自动接管。 Q:重复 finish 会怎样。 返回 updated: false 与当前状态,不会覆盖首次结果。 Q:retry 报 retry-exhausted。 已达任务的最大重试次数,可在 register 里调大 maxRetries。 Q:统计里成功率一直是 0。 需要有 success 或 failed 的已结束记录;只有 running 不计入。 Q:报 collection-missing。 Schema 没上传。

版本要求与授权

HBuilderX 4.71+,uniCloud 阿里云 / 腾讯云;JavaScript 普通云函数(CommonJS),零扩展库。付费普通授权版按服务空间 spaceId 绑定,提供 7 天试用。

授权按 DCloud 插件市场的标准条款,可用于自己的任意商业项目,项目数量不限;禁止把插件本身(含换皮版本)作为插件 / 源码 / 模板再次分发或转售。

运行时行为要点

  • 一次失败只会被重试一次:retry 先用条件更新抢占父执行的 retried 标记。同一条失败执行重复调用会返回 alreadyRetried: true 并带上已创建那条的 runId,不会重复起新执行。想再试一次,请对最新那条失败的执行调用 retry。
  • 同名防重是尽力而为:begin 的「先查后写」不是原子操作,极端并发下两个触发都可能通过。业务侧仍需保证幂等,或配合分布式锁插件。allowConcurrent: true 时本来就不做防重。
  • 超时接管带条件:只在 heartbeat_at 没变时才把执行标记为 timeout,刚续期的执行不会被误杀。
  • stats 是近似值:平均耗时与失败排行基于最近 200 条已结束记录,不是全量聚合。
  • 令牌会出现在云函数日志里:callFunction 的参数在日志中可见,这是 uniCloud 的既有行为。定时触发函数请从环境变量读令牌,不要硬编码;怀疑泄露时改环境变量即可。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

本插件把任务配置与执行记录写入使用者自己的 uniCloud 服务空间集合(默认 cloud_schedule_runs),字段包含任务名、执行状态、尝试次数、持有者标识、开始与结束时间、耗时、结果摘要与错误摘要。结果摘要有大小上限,超限只保留长度标记;不执行业务代码、不存储业务正文。不向任何第三方服务器发送数据,不内置统计或上报 SDK。必须通过 SCHEDULE_TOKEN 才能读写。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。