laravel-workflow
laravel-workflow copied to clipboard
Wrong announce events
Workflow:
public static function getWorkflowDefinition(): array
{
return [
'type' => self::WORKFLOW_TYPE,
'supports' => [self::class],
'places' => [
self::PLACE_DRAFT,
self::PLACE_NEW,
self::PLACE_PAID => ['metadata' => ['bg_color' => '#FF00AA']],
self::PLACE_PROVISIONED,
self::PLACE_EXPIRED,
],
'initial_places' => [self::PLACE_DRAFT],
'transitions' => [
self::TRANSITION_START => ['from' => self::PLACE_DRAFT, 'to' => self::PLACE_NEW, 'metadata' => ['kyp1']],
self::TRANSITION_NOTIFY => ['from' => self::PLACE_NEW, 'to' => self::PLACE_NEW, 'metadata' => ['kyp2']],
self::TRANSITION_PAYMENT => ['from' => self::PLACE_NEW, 'to' => self::PLACE_PAID, 'metadata' => ['kyp3']],
self::TRANSITION_PROVISION => ['from' => self::PLACE_PAID, 'to' => self::PLACE_PROVISIONED, 'metadata' => ['kyp4']],
self::TRANSITION_EXPIRE => ['from' => self::PLACE_NEW, 'to' => self::PLACE_EXPIRED, 'metadata' => ['kyp5']],
],
];
}
When workflow_apply('startProcess')
we receive the following events:
- Entered event for place "New" - this is OK
- Announce event for "startProcess" - this is not OK
[2022-08-10 15:20:44] local.DEBUG: Entered "New" for subject of class "App\Crm\Models\Orders\Order" in workflow "CrmOrder".
[2022-08-10 15:20:45] local.DEBUG: Announce "startProcess" for subject of class "App\Crm\Models\Orders\Order" in workflow "CrmOrder".
Expected are 3 announce events for the following transitions:
sendNotification receivedPayment expireOrder
Hi, sorry for the radio silence on this one. At first glance, this might be because from a null state, the initial state is "entered" first, and that does fire all the relevant workflow events because of that.
Can you try this with a non-null starting state (i.e. explicitly give it the "Draft" state to start with), and see if that still triggers that unexpected announce?
Hi Zack,
I did the requested test and I still think it is not working properly. Here is a dump of the workflow and log of events. What I do is when in "Active" place, do transition "recalculateBalance". It is protected by guard that would not allow it to reenter there for the next hour. "chargeVoucher" is always enabled as long as we have credit (this voucher has credit so this transition is always enabled).
What happened after the transition is completed is that only event "available recalculate Balance" is fired. Not "chargeVoucher" fired as expected.
but I give up on digging this. I can't find consistent behaviour to rely upon, so I made my own code to periodically poll all open workflows and execute available transitions that I have information that I want to be auto executed.
You may close the ticket. Thank you very much for all efforts and time.
[2022-08-31 16:33:40] local.DEBUG: Available transition: recalculateBalance
[2022-08-31 16:33:40] local.DEBUG: Autoexec transition: recalculateBalance
[2022-08-31 16:33:40] local.DEBUG: Event: Entered place "Active" for subject of class "Domain\BulkSms\Models\Senders\Voucher" in workflow "BulkSmsVoucher".
[2022-08-31 16:33:40] local.DEBUG: Available transition: chargeVoucher
[2022-08-31 16:33:40] local.DEBUG: Event: Completed transition "recalculateBalance" for subject of class "Domain\BulkSms\Models\Senders\Voucher" in workflow "BulkSmsVoucher".
[2022-08-31 16:33:41] local.DEBUG: Event: Available transition "recalculateBalance" for subject of class "Domain\BulkSms\Models\Senders\Voucher" in workflow "BulkSmsVoucher".
[2022-08-31 16:33:41] local.DEBUG: Available transition: chargeVoucher
PS. To make it brighter, for above log. " Event: " lines are generated by events generated by Symfony componend, that I'm hooked up to. " Available transition" line is logged by my own code from subscriber in "entered" events.
<?php
namespace Domain\Workflow\Listeners;
use Domain\Workflow\Services\WorkflowService;
use Illuminate\Support\Facades\Log;
use Symfony\Component\Workflow\Event\TransitionEvent;
use ZeroDaHero\LaravelWorkflow\Events\AnnounceEvent;
use ZeroDaHero\LaravelWorkflow\Events\CompletedEvent;
use ZeroDaHero\LaravelWorkflow\Events\EnteredEvent;
class WorkflowSubscriber
{
public function __construct(
private WorkflowService $workflowService
) {
}
public function enteredPlace(EnteredEvent $enteredEvent)
{
foreach ($enteredEvent->getMarking()->getPlaces() as $place => $key) {
Log::debug(sprintf(
'Event: Entered place "%s" for subject of class "%s" in workflow "%s".',
$place,
\get_class($enteredEvent->getSubject()),
$enteredEvent->getWorkflowName()
));
}
$subject = $enteredEvent->getSubject();
$this->workflowService->storeMarking($subject);
$this->workflowService->processExecute($subject);
}
public function completedTransition(CompletedEvent $completedEvent)
{
$subject = $completedEvent->getSubject();
$transition = $completedEvent->getTransition();
Log::debug(sprintf(
'Event: Completed transition "%s" for subject of class "%s" in workflow "%s".',
$transition->getName(),
\get_class($subject),
$completedEvent->getWorkflowName()
));
$this->workflowService->updateSVG($subject);
}
public function announceTransition(AnnounceEvent $announceEvent)
{
$subject = $announceEvent->getSubject();
$transition = $announceEvent->getTransition();
Log::debug(sprintf(
'Event: Available transition "%s" for subject of class "%s" in workflow "%s".',
$transition->getName(),
\get_class($subject),
$announceEvent->getWorkflowName()
));
}
}