15: 任务

Phlo 内置了跨应用的 cron 运行器。每个应用的系统 cron 条目每分钟触发一次 tasks::runtasks 资源以声明方式与 %app->tasks 匹配。您的应用中没有 cron 语法,也没有外部调度程序。

15.1: 设置

三个步骤。

1. 在 data/app.json 中激活资源

{
    "resources": [..., "tasks"]
}

2. 在 app.phlo 中描述你的任务

prop tasks => arr(
    cleanup: arr(do: 'account::cleanup', every: '5 minutes'),
    poll:    arr(do: fn() => external::pull(), every: 'minute'),
    backup:  arr(do: 'backup::run', daily: '03:00'),
    report:  arr(do: 'report::weekly', weekly: 'monday 09:00'),
)

3. 每个应用一个 cron 条目,使用绝对路径:

* * * * * php-zts <app>/www/app.php tasks::run

将其放置在 /etc/cron.d/example-tasks(系统,6 个字段包括用户)或通过 crontab -u <user>(每用户,5 个字段)。

15.2: 日程安排

每个任务选择一个调度键:

格式 示例
every: PHP 可读的持续时间字符串 'minute''5 minutes''2 hours''1 day'
daily: 'HH:MM' '03:00'
weekly: '<weekday> HH:MM' 'monday 09:00'

every: 'minute'(没有前导数字)在内部变为'1 minute'。通过 strtotime("+$every", 0) 进行解析。

15.3: 可调用的 (`do:`)

do: 字段接受三种形式:

类型 示例 被调用为
Closure fn() => external::pull() 直接
'Class::method' 'account::cleanup' account::cleanup()
资源名称 'backup' phlo('backup')

与正常请求不同,任务在 HTTP 生命周期之外运行:没有 %req,没有 %session。编写任务时请确保其自包含。

15.4: 磁盘上的状态 (`data/tasks/`)

tasks::run 会自动创建 data/tasks/ 并用三个文件保护每个任务:

文件 内容 何时
<name>.last 原始 Unix 时间戳 每次成功运行时,用于到期检查
<name>.json {schedule, return} 用于 Control Center 每次成功运行时
<name>.lock 空(mtime 计数) 在运行期间,TTL 1 小时

锁定防止慢任务自我重叠。TTL 故意设置为 1 小时:失败的任务会被停放,直到锁定过期;其他任务会照常运行。

15.5: 错误流程

tasks::run 中没有 try/catch。一个 Throwable 会冒泡到 Phlo 的框架异常处理程序,并写入 data/errors.json,就像构建错误一样。Phlo Control Center 在任务选项卡中显示它们。

15.6: Phlo 控制中心

Phlo 控制中心自动检测 data/tasks/

15.7: 示例

prop tasks => arr(
    heartbeat: arr(do: 'app::heartbeat', every: 'minute'),
)

static heartbeat => file_put_contents(data.'heartbeat.log', date('Y-m-d H:i:s').' tasks::run fired'.lf, FILE_APPEND | LOCK_EX)

Cron entry:

* * * * * php-zts <app>/www/app.php tasks::run

每分钟调用一次 tasks::run,检查 heartbeat 是否为 every: 'minute'lastRun < 60s 之前,然后运行 app::heartbeat()。文件 data/tasks/heartbeat.last.json.lock 会被更新;在任务运行时,中间的 cron 触发会跳过该任务。

我们使用必要的cookie来使该网站正常工作。在您的许可下,我们还使用分析工具来改善网站。