Scheduling Execution in PHP

We often need to schedule execution of given business functionality in our applications.
The timing depends on what we want to achieve. It may be monthly executed invoices or notification sent after user was registered on the website.
And in this article we will deep into different ways of scheduling execution in PHP.
This article assume basic knowledge about Commands and Events.
Scheduled Batch Job
The most common approach are scheduled batch jobs.
This is a process that rises at specific hour, in most of the cases executes big database Query, fetches large portion of data and execute related actions.
In PHP world Scheduled Batch Jobs are mostly implemented by Cron Jobs, that executes process at given time.
Batches are pretty straight forward in implementation, access to database, iterate and execute.
What we could achieve by that?
- We could fetch all users that have registered within last 15 minutes, to send them an welcome notification.
- We could fetch all the orders to recalculate company earning statistics.
- For particular user we may have agreement to invoice him at given date, so we would look for over due dates to generate it
Scheduled Jobs Implementation
Having system cron job often creates problems with tracking if something went wrong and requires running non PHP process.
If this is problematic for you, Ecotone brings Scheduled Jobs into PHP.
Scheduled Method
EndpointId
in #[Scheduled]
defines the name, that will be used to execute the process. #[Poller]
defines how this method should be executed.
This method will be scheduled for execution every 10 seconds.
The process can be now run:
# Symfony
bin/console ecotone:run notificationSender -vvv
# Laravel
artisan ecotone:run notificationSender -vvv
# Lite
$messagingSystem->run("notificationSender");
Scheduled Handler
You may also schedule execution of given Command Handler
.
The first parameter of #[Scheduled]
indicated routing to Command Handler
.
In this case we have set up Cron to execute every minute and call our Command Handler.
Problems with Scheduled Batch Jobs
There may be moment in time when Scheduled Batch Jobs will become problematic.
- Batch Jobs often generate huge load on database, which affect end users of the system.
- What if batch job will fail at midnight?
If we can catch it and notify, then users of the system are in luck, however developers may have another sleepless night.
This becomes even more problematic, if our script break in the middle of processing. As we need to recover from that and run the job only for part of the data, that was not yet processed. - And what if we want to perform actions during the day?
We either need to increase the system resources or agree that it may affect end users during that time.
So there must be a better approach right?
Messaging
Messaging architecture
provides us with solid and stable platform to handle such problems.
It help us in building applications that can scale and perform well on high load.
So what is Message
?
Message is a letter that can inform about recent event that happened in the system or command an action that system should perform.
With Messaging we are dealing with one message (record) at time and to keep system stable, we can queue messages up and deal with them when we are ready.
This solves the problem of being overloaded and handling many record at time. As we can just queue messages up and work on them one by one.
Messaging provides more stability to the system as, if we fail we fail at specific Message, we can retry this message or put it for review and continue with processing other ones.
Static Message Schedules
Suppose that we want to send notification to new registered user 5 minutes after registration.
After registration we are publishing event UserWasRegistered
.
Now we can handle this Event asynchronously and delay the execution.
#[Delayed]
describes in milliseconds how long we want to delay the execution.
Ecotone delivers copy of a message to each Event Handler. Thanks to that you may delay one Handler yet execute other one instantly
Dynamic Message Schedules
In case we would like to dynamically decide, when given process should be executed, we can define it when sending message.
Suppose user made an order and if he does a quick product shipping, we want to delay it for 3 days or otherwise 7 days.
And our Command Handler
We are using asynchronous to have storage for the message we send.
We may for example back it by RabbitMQ or DBAL (Database).
Periodic Message Schedules
We may also want to do recurring action, like invoicing. To perform given execution after given periods of time.
Let's implement invoicing for a user.
After user was registered, we will register first attempt to generate the invoice.
When invoice was generated, we will register another attempt with delay.
We are joining new user to the flow, after he registers.
In case user would be blocked, then in generateInvoice
we could just do return without publishing the event and the flow for given user would simply end.
This will create a message flow, where we will keep generating the invoices for given user at time, till the moment when we will decide to stop it.
If you put#[Asynchronous]
attribute on top of the class, it will apply to all theHandlers
.
Summary
Ecotone brings true Messaging Platform to PHP. It provides easily to follow tools to glue things together, in a solid and stable way.
Messaging is a powerful concept and once developer get used to that, it can save a lot of sleepless nights, especially in business critical components.
You may read more about Ecotone here.
If you want to see implementation of following article using Ecotone Lite go here.