Services
Tina4 supports a synchronous process queue system. The service is easily run from the command line or a daemon service. Processes can be registered and removed from anywhere in your process code or from a web applicatioin running on the same server. Process timing can be set simply in the .env or with more advanced linux style cron timing notifications.
The service runner
The service runner tina4service
usually resides in bin
folder in the root of the project. Once it has loaded
the Tina4 environment, it then enters a continuous loop with the important following steps
- Creates a new service object
- Engages a sleep timer, the default timing
- Gets all the active processes
- For each process
- It loads the process
- Checks for advanced timing
- Checks for any conditions that would stop the process from running
- If all good, then runs the process
Service and Process hot tips
- As the service loads the Tina4 environment before entering the loop, any changes to the Tina4 code requires a service restart.
- As the loop creates a new service object and new process objects, no variables can be persisted in the loop on the service or process objects.
- Any process code changed while a service is running should reload on the next run
Starting the service runner - command line
The service can be started simply from the command line when in the project folder
php bin/tina4service
Tina4 also has a composer script for the same thing
composer start-service
Stopping the service runner - command line
There are occasions when the service runner needs to be stopped in code or from the command line. This is simply achieved by
placing an empty file named stop
in the folder where the tina4service is being run. While often done from the command line,
this could also be done in the process or application code.
Controlling the service runner - daemon service
To run the service as a linux daemon service, one first needs to create the daemon class file and save it the appropriate server daemon folder.
[Unit]
Description=Tina4Service MyService
After=mysqld.service
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=3
User=serveruser
WorkingDirectory=/home/serveruser/public_html
ExecStart=php bin/tina4service
[Install]
WantedBy=multi-user.target
This file saved as myservice.service
creates a service runner that should restart after server shutdown, after the mysql
service has started. The following commands are often used on the server for controlling the runner.
systemctl start myservice.service
systemctl stop myservice.service
systemctl restart myservice.service
systemctl status myservice.service
For a more in depth view on linux services please consult this helpful tutorial by DigitalOcean
Creating the process
Each process class must consist of at least the following two functions. Each service runner can run multiple processes.
class MyProcess extends \Tina4\Process implements \Tina4\ProcessInterface
{
/**
* Code to decide if the process can run.
* This should not be timing related but functionality related
* See below for timing control
*/
public function canRun(): bool
{
// TODO: Implement canRun() method.
}
/**
* The code that will run when this process can run
*/
public function run()
{
// TODO: Implement run() method.
}
}
Adding the process to the service runner
Processes can be added to the service runner from any code, be it in a webhook, another class, even in another process.
An instantiated Process object is given to the service addProcess function. This adds the process information to a file
services.data
which resides in the bin
folder.
$process = (new MyProcess("Process Call Name"))
$service = (new \Tina4\Service());
$service->addProcess($process);
Removing the process from the service runner
Processes that are removed as below, are removed from the services.data
$service = (new \Tina4\Service());
$service->removeProcess("Process Call Name");
Services timing - default
The default wait time between each service run is set at 5 seconds. This can be overwritten in the .env
file
TINA4_SERVICE_TIME=5
Services timing - advanced
Due to the default timing being set for the entire service, all processes run after each other once the sleep timer is passed. This makes process level timing impossible. From version 2.0.82 linux style cron timing has been introduced and can be set when instantiating the process.
// runs approximately every 2 hours
$process = (new MyProcess("Process Call Name", "* 2 * * *"));
The timing string is set as follows
minute hour day month weekday
// Accepts wild card '*' - runs on every timing
// Accepts interval '*/5' - runs every 5 units of timing
// Accepts list '1,4,34,57' - runs every given unit of timing
// Accepts value '3' - runs on the given unit of timing
As the service runner can attempt to run a process, more than once in an advanced timing setting, it keeps track of the last
timed run in the servicesLastTime.data
file to avoid duplications.
Timing hot tips
- Should the default service timing be set at greater than 60 seconds, it might result in missed runs due to the sleep timer being longer than the advanced timing.
- It is important to note that these advance timings are approximate, with an error equal to the default timer and the time it takes to run all the processes in the service.
- To avoid large delays on service processes, one can combine services with triggers, to keep the process time short and let the trigger deal with the delay of the code being run.
Danger
Should precise timing be required, it is probably better to look at using server based cron mechanisms.