作业、cron 和死信队列
如何在请求之外运行工作:什么是作业、如何重试、cron 如何创建作业以及如何处理最终失效的作业。
1. 入队作业
作业是对函数的一次后台调用。使用 service_role 键将其从服务器排队。
| 选项 | 默认 | 含义 |
|---|---|---|
payload | null | JSON 作为请求正文提供给函数 |
delaySecs | 0 | 第一次尝试前等待的秒数。在此之前,该作业将保持 pending 状态。 |
maxAttempts | 3 | 尝试总数,包括第一次 |
您使用 getJob(id) 或 listJobs({ status, limit }) 读回作业(limit 介于 1 到 500 之间,默认为 50)。该作业有 status、 attempts、 max_attempts、 error 和日期 scheduled_at、 started_at、 completed_at。
enqueueJob、 getJob 和 listJobs 需要 service_role 密钥。公钥接收 403。
2. 你的函数接收到什么
作业像任何其他请求一样调用您的函数,但您必须处理三个差异:
| 部分 | 价值 |
|---|---|
| 方法 | JOB (不是 POST) |
| 路径 | /jobs/<job id> |
| 身体 | 该作业的 payload,作为 JSON |
| 身份标头 | 无:x-aura-role 和 x-aura-user-id 不存在 |
记录了真实的呼叫 {"method":"JOB","path":"/jobs/d443d541-…","role":null,"userId":null,"body":"{\"items\":[\"a\",\"b\"],\"order\":42}"}。
作业在没有用户的情况下运行:不要依赖 x-aura-user-id。如果作品属于用户,则将用户的 ID 放入有效负载中。
3. 生命周期和重试
- 作业至少运行一次 。如果工作线程在运行时停止,它可以运行两次,因此请使该函数具有幂等性。
- 失败的尝试会在 5 秒的固定延迟后重试,直到达到
maxAttempts。那么工作就是dead。延迟和默认尝试计数是服务设置(JOB_RETRY_DELAY_SECS、JOB_MAX_RETRIES)。 - 租约后(默认为 450 秒)仍为
running的作业将由服务回收。 - 已完成的作业默认保留 14 天。
只要您的函数 回答,无论状态代码是什么,作业都是 completed 。在实际运行中,返回 500 的函数在一次尝试后生成了 completed 作业,并且从未重试。
作业失败并仅在调用本身失败时重试:函数不存在或不活动、运行时无法访问或调用超时。如果您希望在自己的代码检测到错误时重试,请从处理程序中排队新作业(使用 delaySecs 进行退避),而不是依赖状态代码。
在同一次实际运行中,不存在的函数的作业经历了以下序列:尝试 1 在 3 秒时失败,且 Fonction 'ghost' introuvable,尝试 2 在大约 9 秒时失败,作业变成 dead ,其中 attempts 等于 max_attempts。
4. 死信队列
失效的作业会保留在队列中,可以列出并重试。这些路由还没有 SDK 方法:使用带有 service_role 密钥的 HTTP。
重试会将作业返回到 pending ,而不重置其尝试计数器,因此它会再进行一次尝试,如果再次失败,则返回到 dead 。在重试之前修复原因(例如,部署缺少的功能)。
5. 使用 cron 进行调度
cron 条目不会调用函数本身:每次触发时,它都会将作业排入队列。
- 该明细表具有 5 个字段 (
min hour day month weekday) 或 6 个字段 (sec min hour day month weekday)。 5 场时间表前面有0秒:*/1 * * * *存储为0 */1 * * * *。 - 诸如
@daily之类的别名将被拒绝,并使用声明预期格式的400来拒绝。 - 时间采用 UTC 时间。
last_run和next_run是null直到第一次触发。在实际运行中,在 15:40 创建的计划在 15:41:00 触发,然后显示next_run15:42:00。- 当您创建条目时,有效负载将被冻结。
- 删除未知名称会返回
404。删除 cron 条目也会阻止其触发。 - SDK 没有
getCronJob或updateCronJob:删除该条目并重新创建。
对于纯粹的数据库工作,Postgres pg_cron 扩展避免了函数的往返:请参阅 Cron 页面。