Mental model¶
BTU is one product with four runtime pieces:
flowchart TB
subgraph desk [Frappe Desk - BTU app]
Task[BTU Task]
Schedule[BTU Task Schedule]
RunLater[BTU Run Later]
Config[BTU Configuration]
Log[BTU Task Log]
end
subgraph daemon [btu_scheduler_py]
Cron[Cron evaluator]
end
subgraph redis [Redis]
RQ[RQ queues]
RPC[Scheduler RPC]
RLKeys[run_later keys]
end
subgraph workers [RQ Workers]
Runner[run_task_by_id]
end
Schedule --> Cron
Cron -->|HTTP enqueue| Task
Task --> RQ
RQ --> Runner
Runner --> Log
RunLater -->|poll_for_ready_work| Task
RLKeys -->|poll_for_ready_work| Task
Config --> RPC
RPC --> daemon
Data flow for a scheduled task¶
- User creates a BTU Task (function path + arguments) and BTU Task Schedule (cron, timezone).
- Scheduler daemon reads enabled schedules from the database, computes next run times.
- At fire time, scheduler calls Frappe to enqueue the task on RQ.
- RQ worker runs
btu.btu_core.task_runner.run_task_by_id, which executes the Python function and writes a BTU Task Log.
Control vs execution¶
| Plane | Component | Responsibility |
|---|---|---|
| System of record | Frappe app | Tasks, Schedules, Logs, permissions, Desk |
| Time engine | Scheduler daemon | Cron evaluation, fire-at-time enqueue |
| Execution | RQ workers | Run Python callables |
| Transport | Redis | Job queues + scheduler RPC |
Why two GitHub repos?¶
See Why BTU and Technical design.