s14
Cron スケジューラ
タスクランタイム時間でも仕事を起動できるようにする|452 LOC|7 ツール
タスクがバックグラウンド実行できるようになると、時間そのものも起動入口の一つになります。
s00 > s01 > s02 > s03 > s04 > s05 > s06 > s07 > s08 > s09 > s10 > s11 > s12 > s13 > [ s14 ] > s15 > s16 > s17 > s18 > s19
バックグラウンドタスクが「遅い仕事をどう続けるか」を扱うなら、スケジューラは「未来のいつ仕事を始めるか」を扱う。
この章が解決する問題
s13 で、遅い処理をバックグラウンドへ逃がせるようになりました。
でもそれは「今すぐ始める仕事」です。
現実には:
- 毎晩実行したい
- 毎週決まった時刻にレポートを作りたい
- 30 分後に再確認したい
といった未来トリガーが必要になります。
この章の核心は:
未来の意図を今記録して、時刻が来たら新しい仕事として戻す
ことです。
教学上の境界
この章の中心は cron 構文の暗記ではありません。
本当に理解すべきなのは:
schedule record が通知になり、通知が主ループへ戻る流れ
です。
主線とどう併読するか
schedule、task、runtime taskがまだ同じ object に見えるなら、s13a-runtime-task-model.mdに戻ります。- 1 つの trigger が最終的にどう主線へ戻るかを見たいなら、
s00b-one-request-lifecycle.mdと一緒に読みます。 - 未来トリガーが別の実行系に見えてきたら、
data-structures.mdで schedule record と runtime record を分け直します。
最小の心智モデル
1. schedule records
2. time checker
3. notification queue
流れ:
schedule_create(...)
->
記録を保存
->
time checker が定期的に一致判定
->
一致したら scheduled notification を積む
->
主ループがそれを新しい仕事として受け取る
重要なのは:
scheduler 自体は第二の agent ではない
ということです。
重要なデータ構造
1. schedule record
schedule = {
"id": "job_001",
"cron": "0 9 * * 1",
"prompt": "Run the weekly status report.",
"recurring": True,
"durable": True,
"created_at": 1710000000.0,
"last_fired_at": None,
}
2. scheduled notification
{
"type": "scheduled_prompt",
"schedule_id": "job_001",
"prompt": "Run the weekly status report.",
}
3. check interval
教学版なら分単位で十分です。
最小実装
def create(self, cron_expr: str, prompt: str, recurring: bool = True):
job = {
"id": new_id(),
"cron": cron_expr,
"prompt": prompt,
"recurring": recurring,
"created_at": time.time(),
"last_fired_at": None,
}
self.jobs.append(job)
return job
def check_loop(self):
while True:
now = datetime.now()
self.check_jobs(now)
time.sleep(60)
def check_jobs(self, now):
for job in self.jobs:
if cron_matches(job["cron"], now):
self.queue.put({
"type": "scheduled_prompt",
"schedule_id": job["id"],
"prompt": job["prompt"],
})
job["last_fired_at"] = now.timestamp()
最後に主ループへ戻します。
notifications = scheduler.drain()
for item in notifications:
messages.append({
"role": "user",
"content": f"[scheduled:{item['schedule_id']}] {item['prompt']}",
})
なぜ s13 の後なのか
この 2 章は近い問いを扱います。
| 仕組み | 中心の問い |
|---|---|
| background tasks | 遅い仕事を止めずにどう続けるか |
| scheduling | 未来の仕事をいつ始めるか |
この順序の方が、初学者には自然です。
初学者がやりがちな間違い
1. cron 構文だけに意識を取られる
2. last_fired_at を持たない
3. スケジュールをメモリにしか置かない
4. 未来トリガーの仕事を裏で黙って全部実行する
より分かりやすい主線は:
- trigger
- notify
- main loop が処理を決める
です。
Try It
cd learn-claude-code
python agents/s14_cron_scheduler.py