-
-
Notifications
You must be signed in to change notification settings - Fork 5
Background cron tasks
When WebEngine projects need work to happen outside the normal request cycle, use background cron tasks.
A browser request should render a page, return an API response, or accept user input. It should not wait while the application refreshes a remote cache, sends a digest email, imports a feed, or cleans old generated files. Those jobs belong in the project, but they should run on their own schedule.
WebEngine uses the PHP.GT/Cron component for this. The schedule lives in a project-level crontab file, and the task entry points usually live in the project's cron/ directory.
Here's an example project with two background cron tasks:
.
├── class/
│ └── ServiceLoader.php
├── cron/
├───├── cleanup/
│ │ └── cache.php
│ └── refresh-news.php
├── page/
├── www/
└── crontab
The crontab file decides when jobs are due. The cron/ directory contains the project code that runs when those jobs fire.
Create a file named crontab in the project root. It follows the standard unix crontab format. Example:
# Refresh remote content every 15 minutes.
*/15 * * * * refresh-news?source=php
# Clear generated cache files every night.
30 2 * * * cleanup/cache
# Run a normal shell command at the top of every hour.
0 * * * * bash bin/report-status.sh
The first five fields use familiar crontab syntax:
* * * * * command
| | | | |
| | | | +-- day of week
| | | +---- month
| | +------ day of month
| +-------- hour
+---------- minute
The command after the schedule is interpreted relative to the project. It can be a cron/ script, a go() cron script with query-string input, a static PHP method, or a shell command.
PHP.GT/Cron also provides a few helper extensions that are not part of every Unix cron implementation. For sub-minute jobs, add an s suffix to the first field, such as */10s * * * * refresh-news, to run every 10 seconds. It also supports special @ schedule names such as @hourly, @daily, @weekly, @monthly, @yearly, and @annually. These helpers are convenient for WebEngine projects, but keep in mind that they are interpreted by PHP.GT/Cron rather than by the system crontab command.
The most WebEngine-friendly style is a PHP file in cron/ that defines a go() function. It feels similar to page logic: declare the services you need as parameters and let the container provide them.
crontab:
*/15 * * * * refresh-news?source=php
cron/refresh-news.php:
<?php
use GT\Input\Input;
use App\NewsImporter;
function go(Input $input, NewsImporter $newsImporter):void {
$source = $input->getString("source");
$newsImporter->refresh($source);
}The ?source=php part is parsed as query-string input and is available through Input. Other parameters are resolved through the same service-loading conventions used by WebEngine page logic.
This makes go() scripts a good fit for application tasks that need repositories, API clients, configuration, logging, or other project services.
Cron scripts can be organised into subdirectories:
30 2 * * * cleanup/cache
This can point at:
cron/cleanup/cache.php
Nested paths are for go() cron scripts. In this example, cron/cleanup/cache.php should define function go(...).
For simple jobs that do not need service injection, create a standalone script:
crontab:
0 * * * * build-index --quiet
cron/build-index.php:
<?php
[$script, $mode] = $argv + [null, null];
// Build generated files, warm a cache, or call application code here.The runner resolves build-index to cron/build-index.php and passes any trailing arguments through to the script. Ordinary script aliases are direct children of cron/; use a go() script when you want nested paths such as cleanup/cache.
The command can also call a static PHP method, loaded using the project's autoloader:
0 9 * * MON-FRI App\Task\Digest::send("team@example.com")
Or it can run a shell command exactly as written:
30 2 * * * php bin/nightly-maintenance.php
Use a go() script for application-integrated work, a normal cron/ script for standalone PHP scripts, and a shell command when the job naturally belongs to another executable.
When running the application locally, gt run starts the WebEngine development server and can run the cron watcher alongside it.
gt runIf a project has cron tasks but you only want the web server and other development processes, start without cron:
gt run --no-cronIf you only want the scheduler, run:
gt cronWith no flags, gt cron reads ./crontab, runs jobs that are due now, prints the current time, prints the next scheduled job, and exits.
Example output:
Current time: 16:49:52 (15:49:52 UTC)
Just ran 0 jobs
Next job at: 17:00:00 (16:00:00 UTC) [build-index]
Use watch mode to keep the scheduler running:
gt cron --watchUseful local checks:
gt cron --validate
gt cron --now
gt cron --now --watch--validate checks the crontab file without running jobs. --now runs every task once before normal scheduling begins, which is useful when testing new task code.
gt run is for local development. In production, the web server handles requests and the cron runner should be managed as a separate long-running process.
Use the process manager provided by your hosting environment, such as systemd, Supervisor, a container process, or a platform-specific worker service. The important part is that the process starts from the project root and runs the scheduler in watch mode:
gt cron --watchThe process manager should restart it after deploys, reboots, or crashes. Keep only one active scheduler process per environment unless a task is explicitly designed to run concurrently.
Move back to Run an application, or continue to the request-response lifecycle.
- File-based routing
- Page views
- Page logic
- Dynamic URIs
- Headers and footers
- Custom HTML components
- Page partials
- Binding data to the DOM
- DOM manipulation
- Hello You tutorial
- Todo list tutorial
- Address book tutorial WIP
- Blueprints
- Application architecture
- Coding styleguide WIP
- PHP environment setup WIP
- Web servers WIP
- Background cron tasks
- Database setup WIP
- Client-side compilation WIP
- Testing WebEngine applications WIP
- Production checklist WIP
- Security WIP