Easy methods to automate workflows that stay up for exterior and time prerequisites with out exploding complexity
So it’s important to program stuff like:
- Ship a reminder electronic mail after sooner or later
- Procedure an order after the supply date has been reached
- Mark a record as signed in accordance with the standing of an exterior carrier
Those processes want some type of group since you’ll’t simply
sleep your procedure for an hour to proceed a task. That is the place the Tick development is available in.
You may already know the time period “tick.” Wikipedia describes it lovely neatly:
A unmarried replace of a recreation simulation is referred to as a tick […]
We in most cases aren’t programming video games in Symfony, however we will nonetheless borrow this idea and use the catchy title.
I recommend development a command/activity/task that plays “the tick.”
“The tick” is only a periodic test if a state system transition is conceivable. That permits you to outline all kinds of prerequisites (date, stock, consumer affirmation) in undeniable code with no need to search out tactics to execute your common sense as soon as the situation is met.
Here’s a checklist of causes you could need to deal with duties like this:
- One access level: You simplest want one cron task in comparison to a cron task for each async activity.
- More practical tooling: You simplest wish to construct tracking and logging round one asynchronous duties
- Robustness. If one thing fails, it’ll simply rerun at the subsequent tick. Consider unavailable apis or SMTP servers. With this development, it’ll simply retry.
- Changeable: Converting supply dates at once within the database or converting delays in a brand new model. All the ones adjustments are right away mirrored with out migrations or particular code paths
However, the development has some issues:
- Scaling: The extra entities there are, the longer the tick will take.
- Wasteful: Each entity in some states shall be checked on each tick.
I’ll now get explicit to the symfony workflow element, however you’ll most probably adapt it to different state machines.
You need so as to simply learn the conduct for your utility. State system definitions already assist, however do you know that you’ll upload arbitrary metadata to a symfony workflow definition?
to: handing over
It actually is simply arbitrary information, however that suggests we will describe new conduct for utilization later. On this case, I’ll outline
on_tick, which is only a flag for us that we need to test later.
I extensively utilized the
guard assets to outline a situation on when the state is permitted to modify. That is well readable however relatively restricted, you can use Guard Occasions as a substitute.
You’ll need to simply carry out a tick, so let’s construct a small
Carrier to do it. Right here’s the code:
With this straightforward carrier, you’ll simply run
$service->tick($order) to run pending transitions. This may also be helpful proper after developing the entity to begin a procedure straight away. Or no longer, if there’s a situation these days blocking off it.
Issues that would additionally make sense on this carrier:
- A dry run means like
simulateso you’ll test if there’s something pending with out in fact doing it
- One way to go back all transition blockers so you’ll give explanations why an Order is caught
We’ll now desire a command to cause ticks from outdoor our methods global, in most cases a cron task. However you’ll additionally need so as to manually cause unmarried ticks, so the CLI will have to be just a little fancy.
The command must be explicit to the underlying database, so I create the tick command for my instance of an
Order, however you’ll modify it to no matter you favor and even let it run thru more than one entity varieties. Right here’s extra code:
With this command, you’ll now run
order:tick and all transitions marked as
on_tick: true shall be performed in the event that they aren’t blocked through different prerequisites.
One small tick I take advantage of this is injecting the state system at once the use of named autowiring with the argument
$orderStateMachine to explicitly inject the state system with the title
order. You in most cases get your state machines shape the
Registry carrier, however that has no manner of gaining access to the state system with no need the thing. And right here, we wish the state system first to create a listing of states, that experience an
This command additionally accepts a listing of ids as a controversy. That manner, you’ll run a tick on a particular order. That is actually helpful for trying out.
Issues you could need to make stronger your self:
- Prioritizing of explicit entities (eg. procedure older orders first)
- Loading entities/orders in batch to make stronger throughput
- You might want to attempt to run throughout the identification checklist the use of more than one processes. Both through spawning processes your self or through piping all identification’s even though
echo [id list] |xargs -P4 -n100 php bin/console order:tick.
Did I pass over anything else? Did I let you? Inform me within the feedback.