4: Runtime helpers and scheduling
Two consumers ride the daemon without you calling /dispatch yourself: the async runtime helpers, and the scheduler.
4.1: The runtime helpers
Phlo's helpers for running a target out of band all use the pool when the app opts in, and fall back to a one-shot subprocess otherwise:
| Helper | Does |
|---|---|
phlo_sync('Class::method', ...$args) |
Run a target and wait for its return value |
phlo_async('Class::method', ...$args) |
Queue a target fire-and-forget; returns once accepted |
await($job, $job, ...) |
Run many targets concurrently and collect their results |
phlo_stream('Class::method', ...$args) |
Yield a target's output line by line |
The opt-in is one constant in the app entrypoint:
phlo_app(
id: 'Api',
host: 'api.example.com',
daemon: 3001,
);
With daemon set, the helpers dispatch by app path onto the pool; without it, they spawn a one-shot process exactly as before. The app code is identical either way, so adopting the daemon only changes throughput.
The gain is largest when one request fans out. await() over a hundred jobs is a hundred app boots on the one-shot path, but a hundred dispatches onto a resident pool with the daemon, bounded by the worker count instead of an unbounded burst of subprocesses:
$results = await(
['translate::run', 'nl', $text],
['translate::run', 'de', $text],
['translate::run', 'fr', $text],
)4.2: Scheduling without cron
The daemon can run targets on an interval, which replaces the per-app cron entry behind the tasks resource. Each schedule entry is {app, target, every, build}: the absolute app.php path, the target, the interval in seconds, and whether to run it one-shot. Each fires on its interval with the first run one interval after boot, just like a cron tick:
[
{ app: '/srv/api/www/app.php', target: 'tasks::run', every: 60, build: false },
{ app: '/srv/dashboard/www/app.php', target: 'fleet::poll', every: 120, build: true },
]
Everything downstream is unchanged: the same %app->tasks matching, the same due-check, the same on-disk state. Cron stays the fallback for hosts without a daemon; you pick one trigger, not both.