tobento / service-schedule
A task schedule system for running tasks at specific intervals.
Requires
- php: >=8.0
- butschster/cron-expression-generator: ^1.10
- dragonmantank/cron-expression: ^3.1
- psr/clock: ^1.0
- psr/container: ^2.0
- psr/event-dispatcher: ^1.0
- psr/simple-cache: 2 - 3
- tobento/service-autowire: ^1.0.9
- tobento/service-collection: ^1.0.5
- tobento/service-file-creator: ^1.0.1
Requires (Dev)
- guzzlehttp/guzzle: ^7.8
- mockery/mockery: ^1.6
- phpunit/phpunit: ^9.5
- symfony/process: ^4.4|^5.4|^6.0
- tobento/service-cache: ^1.0
- tobento/service-clock: ^1.0
- tobento/service-console: ^1.0.3
- tobento/service-container: ^1.0.6
- tobento/service-event: ^1.0
- tobento/service-mail: ^1.0
- vimeo/psalm: ^4.0
Suggests
- guzzlehttp/guzzle: Required to support the ping task and parameter
- symfony/process: Required to support the process task
- tobento/service-cache: May be used to support task without overlapping
- tobento/service-console: To support command tasks
- tobento/service-event: May be used to support schedule and task events
- tobento/service-mail: May be used to support sending mails
README
A task schedule system for running tasks at specific intervals.
Table of Contents
- Getting started
- Documentation
- Credits
Getting started
Add the latest version of the schedule service project running this command.
composer require tobento/service-schedule
Requirements
- PHP 8.0 or greater
Highlights
- Framework-agnostic, will work with any project
- Decoupled design
Documentation
Usage
Scheduling Tasks
To schedule a task you may use the default Schedule or create your own fitting your needs.
Running Scheduled Tasks
The most common way to run the schedule processor is a Cron job that runs the schedule:run every minute. The following should be added to your production server's crontab:
* * * * * cd /path-to-your-project && php console.php schedule:run >> /dev/null 2>&1
Example of console.php
Example using the Console Service, Clock Service and Container Service:
composer require tobento/service-console
composer require tobento/service-clock
composer require tobento/service-container
use Tobento\Service\Clock\SystemClock; use Tobento\Service\Container\Container; use Tobento\Service\Console\Console; use Tobento\Service\Console\Command; use Tobento\Service\Console\InteractorInterface; use Tobento\Service\Console\Symfony; use Tobento\Service\Schedule\Task; use Tobento\Service\Schedule\Parameter; use Tobento\Service\Schedule\TaskProcessor; use Tobento\Service\Schedule\TaskProcessorInterface; use Tobento\Service\Schedule\ScheduleProcessor; use Tobento\Service\Schedule\ScheduleProcessorInterface; use Tobento\Service\Schedule\Schedule; use Tobento\Service\Schedule\ScheduleInterface; use Psr\Container\ContainerInterface; use Psr\Clock\ClockInterface; // Container bindings: $container = new Container(); $container->set(ClockInterface::class, new SystemClock()); $container->set(TaskProcessorInterface::class, TaskProcessor::class); $container->set(ScheduleProcessorInterface::class, ScheduleProcessor::class); // Schedule: $container->set(ScheduleInterface::class, function() { $schedule = new Schedule(name: 'default'); $schedule->task( (new Task\CallableTask( callable: static function (): string { // do something: return 'task output'; }, ))->name('demo') ); return $schedule; }); // Console: $console = new Symfony\Console( name: 'app', container: $container, ); $console->addCommand(\Tobento\Service\Schedule\Console\ScheduleRunCommand::class); $console->addCommand(\Tobento\Service\Schedule\Console\ScheduleListCommand::class); $console->run();
Tasks
Callable Task
use Tobento\Service\Schedule\Task\CallableTask; use Tobento\Service\Schedule\Task\TaskInterface; $task = new CallableTask( callable: static function (SomeService $service, $option): string { // do something // you may return the task output or nothing at all (void): return 'task output'; }, // you may set data passed to the function: params: ['option' => 'value'], ); var_dump($task instanceof TaskInterface); // bool(true) // Specific task methods: $callable = $task->getCallable(); $params = $task->getParams();
Check out the Task Methods section to learn more about the available methods as well as the Task Parameters.
Invokable objects
You may consider using invokable objects that contain an __invoke
method:
use Tobento\Service\Schedule\Task\CallableTask; class SampleInvokable { public function __invoke(SomeService $service, $option): string { // do something // you may return the task output or nothing at all (void): return 'task output'; } } $task = new CallableTask( callable: new SampleInvokable(), // you may set data passed to the __invoke method: params: ['option' => 'value'], );
Command Task
The command task may be used to run the provided command using the Console Service.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Task\TaskInterface; use Tobento\Service\Console\ConsoleInterface; use Tobento\Service\Console\ExecutedInterface; $task = new CommandTask( command: 'command:name', // you may set command input data: input: [ // passing arguments: 'username' => 'Tom', // with array value: 'username' => ['Tom', 'Tim'], // passing options: '--some-option' => 'value', // with array value: '--some-option' => ['value'], ], ); var_dump($task instanceof TaskInterface); // bool(true) // Specific task methods: $command = $task->getCommand(); $input = $task->getInput(); // Returning null if task is not processed yet, otherwise the console. $console = $task->getConsole(); // null|ConsoleInterface // Returning null if task is not processed yet, otherwise the executed. $executed = $task->getExecuted(); // null|ExecutedInterface
Check out the Task Methods section to learn more about the available methods as well as the Task Parameters.
Requirements
This command task requires the Console Service:
composer require tobento/service-console
Invokable Task
You may create invokable tasks by simply extending the InvokableTask::class
. The __invoke
method will be called when the task is being processed.
use Tobento\Service\Schedule\Task\InvokableTask; use Tobento\Service\Schedule\Task\Schedule\CronExpression; class SampleTask extends InvokableTask { public function __construct() { // you may set default parameters: $this->id('A unique id'); $this->name('A task name'); $this->description('A task description'); // you may set a default schedule: $this->schedule(new CronExpression('* * * * *')); // or $this->cron('* * * * *'); } public function __invoke(SomeService $service): string { // do something // you may return the task output or nothing at all (void): return 'task output'; } } $task = (new SampleTask())->cron('* * * * *');
Check out the Task Methods section to learn more about the available methods as well as the Task Parameters.
Ping Task
The ping task may be used to ping the provided URI.
use Tobento\Service\Schedule\Task\PingTask; use Tobento\Service\Schedule\Task\TaskInterface; use Psr\Http\Message\ResponseInterface; $task = new PingTask( uri: 'https://example.com/ping', method: 'GET', // default options: [], ); var_dump($task instanceof TaskInterface); // bool(true) // Specific task methods: $uri = $task->getUri(); $method = $task->getMethod(); $options = $task->getOptions(); // Returning null if task is not processed yet, otherwise the response. $response = $task->getResponse(); // null|ResponseInterface
Check out the Task Methods section to learn more about the available methods as well as the Task Parameters.
Requirements
This ping task requires Guzzle, PHP HTTP client:
composer require guzzlehttp/guzzle
Process Task
The process task may be used to execute shell commands using the Symfony Process Component.
use Tobento\Service\Schedule\Task\ProcessTask; use Tobento\Service\Schedule\Task\TaskInterface; use Symfony\Component\Process\Process; $task = new ProcessTask( process: '/bin/script', ); // or with a process instance: $task = new ProcessTask( process: Process::fromShellCommandline('/bin/script') ->setTimeout(20), ); var_dump($task instanceof TaskInterface); // bool(true) // Specific task methods: $process = $task->getProcess();
Check out the Task Methods section to learn more about the available methods as well as the Task Parameters.
Requirements
This process task requires the Symfony Process Component:
composer require symfony/process
Task Methods
All of the available Tasks supporting the following methods.
General Task Methods
// You may set a unique task id: $task->id('taskId'); // You may set a task name: $task->name('A task name'); // You may set a description: $task->description('A task description');
Schedule Task Methods
use Tobento\Service\Schedule\TaskScheduleInterface; use Tobento\Service\Schedule\Task\Schedule\CronExpression; // you may set the schedule implementing TaskScheduleInterface $task->schedule(new CronExpression( expression: '* * * * *', // you may specify a timezone: timezone: 'Europe/Berlin', // string|\DateTimeZone )); // or you may use the cron method: $task->cron( expression: '* * * * *', // you may specify a timezone: timezone: 'Europe/Berlin', // string|\DateTimeZone );
Check out the Task Schedule section for the available task schedules.
You may consider using the cron generator already available:
use Butschster\CronExpression\Generator; $task->cron(Generator::create()->daily());
Check out the Cron Expression Generator for more examples.
Task Schedule
Cron Expression
You may use the CronExpression::class
to define at which interval you want to run the task.
use Tobento\Service\Schedule\Task\Schedule\CronExpression; use Tobento\Service\Schedule\TaskScheduleInterface; $cron = new CronExpression( expression: '* * * * *', // you may specify a timezone: timezone: 'Europe/Berlin', // string|\DateTimeZone ); var_dump($cron instanceof TaskScheduleInterface); // bool(true)
You may consider using the cron generator already available:
use Tobento\Service\Schedule\Task\Schedule\CronExpression; use Butschster\CronExpression\Generator; $cron = new CronExpression( expression: Generator::create()->daily(), );
Check out the Cron Expression Generator for more examples.
Dates
You may use the Dates::class
to run tasks at specific dates every year.
use Tobento\Service\Schedule\Task\Schedule\Dates; use Tobento\Service\Schedule\TaskScheduleInterface; $dates = new Dates( // Every year yyyy-05-12 15:38 new \DateTime('2023-05-12 15:38:45'), // Every year yyyy-08-24 10:15 new \DateTimeImmutable('2023-08-24 10:15:33'), ); var_dump($dates instanceof TaskScheduleInterface); // bool(true)
Task Parameters
You may use the available parameters providing basic features for tasks or create custom parameters to add new features or customizing existing to suit your needs.
All of the available Tasks supporting the following parameters and its helper methods.
After Parameter
The after parameter executes the specified handler after the task is processed.
The TaskResultInterface::class
will be passed to your handler. In addition, you may request any service being resolved (autowired) by the container passed to the task processor.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; use Tobento\Service\Schedule\TaskResultInterface; // any callable handler: $task = (new CommandTask('command:name')) ->parameter(new Parameter\After(static function(TaskResultInterface $result, SomeService $service): void { // executes after the task is processed })) // or using the helper method: ->after(static function (TaskResultInterface $result, SomeService $service): void { // executes after the task is processed }); // or a handler implementing Parameter\AfterTaskHandler $task = (new CommandTask('command:name')) ->parameter(new Parameter\After(handler: $handler)) // or using the helper method: ->after(handler: $handler);
Before Parameter
The before parameter executes the specified handler before the task is processed.
The TaskInterface::class
will be passed to your handler. In addition, you may request any service being resolved (autowired) by the container passed to the task processor.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; use Tobento\Service\Schedule\TaskInterface; // any callable handler: $task = (new CommandTask('command:name')) ->parameter(new Parameter\Before(static function(TaskInterface $task, SomeService $service): void { // executes before the task is processed })) // or using the helper method: ->before(static function (TaskInterface $task, SomeService $service): void { // executes before the task is processed }); // or a handler implementing Parameter\BeforeTaskHandler $task = (new CommandTask('command:name')) ->parameter(new Parameter\Before(handler: $handler)) // or using the helper method: ->before(handler: $handler);
Skip Task
You may throw a TaskSkipException::class
if you want to prevent the task from being processed not resulting in a failure.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\TaskSkipException; // any callable handler: $task = (new CommandTask('command:name')) ->before(static function (): void { throw new TaskSkipException('Skipped because ...'); });
Failed Parameter
The failed parameter executes the specified handler if the task fails.
The TaskResultInterface::class
will be passed to your handler. In addition, you may request any service being resolved (autowired) by the container passed to the task processor.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; use Tobento\Service\Schedule\TaskResultInterface; // any callable handler: $task = (new CommandTask('command:name')) ->parameter(new Parameter\Failed(static function(TaskResultInterface $result, SomeService $service): void { // executes if the task failed })) // or using the helper method: ->failed(static function (TaskResultInterface $result, SomeService $service): void { // executes if the task failed }); // or a handler implementing Parameter\FailedTaskHandler $task = (new CommandTask('command:name')) ->parameter(new Parameter\Failed(handler: $handler)) // or using the helper method: ->failed(handler: $handler);
Mail Parameter
The mail parameter may be used to send mails using the Mail Service before and/or after tasks are processed or when a task fails.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; use Tobento\Service\Mail\Message; $task = (new CommandTask('command:name')) ->parameter(new Parameter\Mail( message: (new Message())->to('admin@example.com'), handle: ['before', 'after', 'failed'], // default // send mail only if task failed: // handle: ['failed'], ));
In addition, you may use the before
, after
and failed
helper methods:
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; use Tobento\Service\Mail\Message; $task = (new CommandTask('command:name')) ->before(new Parameter\Mail( message: (new Message())->to('admin@example.com'), )) ->after(new Parameter\Mail( message: (new Message())->to('admin@example.com'), )) ->failed(new Parameter\Mail( message: (new Message())->to('admin@example.com'), ));
Requirements
This parameter requires the Mail Service:
First, install the mail service:
composer require tobento/service-mail
Finally, it requires the MailerInterface::class
to be binded to your container passed to the Task Processor:
Example using the Container Service:
use Tobento\Service\Mail\MailerInterface; use Tobento\Service\Schedule\TaskProcessor; use Tobento\Service\Container\Container; $container = new Container(); $container->set(MailerInterface::class, function() { // create mailer: return $mailer; }); $taskProcessor = new TaskProcessor($container);
Message From Address
If you do not have defined a default from address, you will need to set it:
use Tobento\Service\Mail\Message; $message = (new Message()) ->from('from@example.com') ->to('admin@example.com');
Message Contents
You may set a message subject otherwise the task name will be used instead:
use Tobento\Service\Mail\Message; $message = (new Message()) ->subject('Some task subject') ->to('admin@example.com');
A sent mail looks like:
Task Status: Failed Task ID: task-id Task Name: Task's name Task Description: Task's description (if any) Task Output: Failed task's output (if any) Task Exception: Failed task's exception stack trace (if any)
Monitor Parameter
The monitor parameter may be used to monitor tasks processes such as the start time, running time and memeory usage.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; $task = (new CommandTask('command:name')) ->parameter(new Parameter\Monitor()) // or using the helper method: ->monitor();
Ping Parameter
The ping parameter may be used to ping the provided URI.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; $task = (new CommandTask('command:name')) ->parameter(new Parameter\Ping( uri: 'https://example.com/task', method: 'GET', // default options: [], handle: ['before', 'after', 'failed'], // default // pings only if task failed: // handle: ['failed'], ));
A X-Task-Status
header will be added to the request with a Starting
, Success
or Failed
value depending on its processing state.
In addition, you may use the before
, after
and failed
helper methods:
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; $task = (new CommandTask('command:name')) ->before(new Parameter\Ping( uri: 'https://example.com/task-before', )) ->after(new Parameter\Ping( uri: 'https://example.com/task-after', )) ->failed(new Parameter\Ping( uri: 'https://example.com/task-failed', ));
Requirements
This parameter requires Guzzle, PHP HTTP client:
composer require guzzlehttp/guzzle
Send Result To Parameter
The send result to parameter may be used to send the task result to the specified file.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; use Tobento\Service\Schedule\TaskInterface; $task = (new CommandTask('command:name')) ->parameter(new Parameter\SendResultTo( file: 'dir/to/file.log', // if true sends only output, otherwise the whole result: onlyOutput: false, // default // if true appends result to file otherwise overwrites file: append: true, // default handle: ['after', 'failed'], // default // send result only after task is processed: // handle: ['after'], ));
In addition, you may use the after
and failed
helper methods:
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; $task = (new CommandTask('command:name')) ->after(new Parameter\SendResultTo( file: 'dir/to/file-success.log', )) ->failed(new Parameter\SendResultTo( file: 'dir/to/file-failed.log', ));
Skip Parameter
The skip parameter may be used to skip tasks if the skip
parameter evalutes to true
. The parameter has a default priority of 100000
whereby it gets handled before any lower prioritized task parameters.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; use Tobento\Service\Schedule\TaskInterface; // using a boolean: $task = (new CommandTask('command:name')) ->parameter(new Parameter\Skip( skip: true, // You may specify a reason for skipping: reason: 'Because of ...' )); // using a callable: $task = (new CommandTask('command:name')) ->parameter(new Parameter\Skip( skip: static function(TaskInterface $task, SomeService $service) // skips if return value is true return true; }, // You may specify a reason for skipping: reason: 'Because of ...' )); // or using the helper method: $task = (new CommandTask('command:name')) ->skip(skip: $skip, reason: 'Because of ...');
If using a callable, the TaskInterface::class
will be passed to your callback function. In addition, you may request any service being resolved (autowired) by the container passed to the task processor.
Without Overlapping Parameter
The without overlapping parameter may be used to prevent tasks from overlapping.
use Tobento\Service\Schedule\Task\CommandTask; use Tobento\Service\Schedule\Parameter; $task = (new CommandTask('command:name')) ->parameter(new Parameter\WithoutOverlapping( // You may set a unique id. If null it uses the task id. id: 'unique-task-id', // null|string // You may set a maximum expected lock duration in seconds: ttl: 86400, // default )) // or using the helper method: ->withoutOverlapping() // with id and ttl: ->withoutOverlapping(id: 'unique-task-id', ttl: 86400);
Requirements
The parameter requires a CacheInterface::class
to be binded to your container passed to the Task Processor:
Example using the Cache Service and Container Service:
use Psr\SimpleCache\CacheInterface; use Tobento\Service\Schedule\TaskProcessor; use Tobento\Service\Container\Container; use Tobento\Service\Cache\Simple\Psr6Cache; use Tobento\Service\Cache\ArrayCacheItemPool; use Tobento\Service\Clock\SystemClock; $container = new Container(); $container->set(CacheInterface::class, function() { // create cache: return new Psr6Cache( pool: new ArrayCacheItemPool( clock: new SystemClock(), ), namespace: 'default', ttl: null, ); }); $taskProcessor = new TaskProcessor($container);
Task Processor
The TaskProcessor::class
is responsible for processing tasks.
use Tobento\Service\Schedule\TaskProcessor; use Tobento\Service\Schedule\TaskProcessorInterface; use Psr\Container\ContainerInterface; $taskProcessor = new TaskProcessor( container: $container // ContainerInterface ); var_dump($taskProcessor instanceof TaskProcessorInterface); // bool(true)
Process Task
use Tobento\Service\Schedule\TaskInterface; use Tobento\Service\Schedule\TaskResultInterface; $result = $taskProcessor->processTask($task); // TaskInterface var_dump($result instanceof TaskResultInterface); // bool(true)
Check out the Task Result to learn more.
Task Result
use Tobento\Service\Schedule\TaskResult; use Tobento\Service\Schedule\TaskResultInterface; use Tobento\Service\Schedule\TaskInterface; $result = new TaskResult( task: $task, output: 'task output', exception: null, // null|\Throwable ); var_dump($result instanceof TaskResultInterface); // bool(true) // Get the task: $task = $result->task(); // TaskInterface // Get the output: $output = $result->output(); // string // Get the exception: $output = $result->exception(); // null|\Throwable var_dump($result->isSuccessful()); // bool(true) var_dump($result->isFailure()); // bool(false) var_dump($result->isSkipped()); // bool(false)
Task Results
use Tobento\Service\Schedule\TaskResults; use Tobento\Service\Schedule\TaskResultsInterface; use Tobento\Service\Schedule\TaskResultInterface; $results = new TaskResults(); var_dump($results instanceof TaskResultsInterface); // bool(true) // Add a task result: $results->add($result); // TaskResultInterface // Get all task results: $taskResults = $results->all(); // iterable<int, TaskResultInterface> // or just: foreach($taskResults as $taskResult) {} // Count all task results: $number = $results->count(); // int(0) // Filter all successful task results returning a new instance: $taskResults = $results->successful(); // TaskResultsInterface // Filter all failed task results returning a new instance: $taskResults = $results->failed(); // TaskResultsInterface // Filter all skipped task results returning a new instance: $taskResults = $results->skipped(); // TaskResultsInterface // You may use the filter method for filtering task results // returning a new instance: $taskResults = $results->filter(fn(TaskResultInterface $r): bool => is_null($r->exception())); // TaskResultsInterface
Schedule
use Tobento\Service\Schedule\Schedule; use Tobento\Service\Schedule\ScheduleInterface; use Tobento\Service\Schedule\TaskInterface; $schedule = new Schedule(name: 'default'); var_dump($schedule instanceof ScheduleInterface); // bool(true) // Schedule any task implementing TaskInterface $schedule->task($task); // You may get a task by its id returning null if task is not found: $task = $schedule->getTask(id: 'taskId'); // null|TaskInterface // You may get all tasks: $tasks = $schedule->all(); // iterable<int, TaskInterface>
Example adding tasks
use Tobento\Service\Schedule\Task; use Tobento\Service\Schedule\Parameter; use Butschster\CronExpression\Generator; $schedule->task( (new Task\CommandTask( command: 'command:name', )) // schedule task: ->cron(Generator::create()->everyTenMinutes()) // adding parameters: ->parameter(Parameter\SendResultTo( file: 'dir/to/file.log', )) // or using helper methods: ->withoutOverlapping() ); $schedule->task( (new Task\CallableTask( callable: static function (SomeService $service, $option): string { // do something // you may return the task output or nothing at all (void): return 'task output'; }, // you may set data passed to the function: params: ['option' => 'value'], )) ->name('Some name') ->description('Some description') // schedule task: ->cron(Generator::create()->everyTenMinutes()) // adding parameters: ->parameter(Parameter\SendResultTo( file: 'dir/to/file.log', )) // or using helper methods: ->withoutOverlapping() );
Check out the Tasks section for more information about the individual tasks.
Schedule Processor
The schedule processor is responsible for processing the scheduled tasks which are due.
use Tobento\Service\Schedule\ScheduleProcessor; use Tobento\Service\Schedule\ScheduleProcessorInterface; use Tobento\Service\Schedule\TaskProcessorInterface; use Psr\EventDispatcher\EventDispatcherInterface; $scheduleProcessor = new ScheduleProcessor( taskProcessor: $taskProcessor, // TaskProcessorInterface // you may set an event dispatcher if you want to support events: eventDispatcher: null, // null|EventDispatcherInterface ); var_dump($scheduleProcessor instanceof ScheduleProcessorInterface); // bool(true)
Process Scheduled Task
use Tobento\Service\Schedule\ScheduleInterface; use Tobento\Service\Schedule\TaskResultsInterface; $results = $scheduleProcessor->processSchedule( schedule: $schedule, // ScheduleInterface now: new \DateTime(), // \DateTimeInterface ); var_dump($results instanceof TaskResultsInterface); // bool(true)
To process tasks when they are due, the processSchedule
method should be called every minute indefinitely.
You may create a custom schedule processor fitting your needs though.
Check out the Task Results to learn more.
Console
You may use the following commands using the Console Service.
To get quickly started consider using the following two app bundles:
Otherwise, you need to install the Console Service and set up your console by yourself. Check out the Running Scheduled Tasks section to see a possible implementation.
Run Command
Running due tasks
php app schedule:run
Running specific tasks by its id
php app schedule:run --id=taskId --id=anotherTaskId
List Command
Lists all tasks.
php app schedule:list
Events
Available Events
use Tobento\Service\Schedule\Event;
Just make sure you pass an event dispatcher to the Schedule Processor!
Learn More
Running Scheduled Tasks Without Console
Another way to run the schedule processor is a Cron job that runs your schedule.php script every minute. The following should be added to your production server's crontab:
* * * * * cd /path-to-your-project && php schedule.php >> /dev/null 2>&1
Example of schedule.php
Example using the Container Service:
composer require tobento/service-container
use Tobento\Service\Container\Container; use Tobento\Service\Schedule\Task; use Tobento\Service\Schedule\Parameter; use Tobento\Service\Schedule\TaskProcessor; use Tobento\Service\Schedule\TaskProcessorInterface; use Tobento\Service\Schedule\ScheduleProcessor; use Tobento\Service\Schedule\ScheduleProcessorInterface; use Tobento\Service\Schedule\Schedule; use Tobento\Service\Schedule\ScheduleInterface; use Psr\Container\ContainerInterface; // Container bindings: $container = new Container(); $container->set(TaskProcessorInterface::class, TaskProcessor::class); $container->set(ScheduleProcessorInterface::class, ScheduleProcessor::class); // Schedule tasks: $schedule = new Schedule(name: 'default'); $schedule->task( (new Task\CallableTask( callable: static function (): string { // do something: return 'task output'; }, ))->name('demo') ); // Process the schedule: $container->get(ScheduleProcessorInterface::class)->processSchedule( schedule: $schedule, // ScheduleInterface now: new \DateTime(), // \DateTimeInterface );