Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions blog/2022-10-29-email-verifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,9 @@ The `verify-email` route receives a workflow id, loads it and then calls the `ve
Now let’s take a look at the actual workflow.

```php
use Workflow\ActivityStub;
use Workflow\SignalMethod;
use Workflow\Workflow;
use Workflow\WorkflowStub;
use function Workflow\{activity, await};

class VerifyEmailWorkflow extends Workflow
{
Expand All @@ -78,11 +77,11 @@ class VerifyEmailWorkflow extends Workflow

public function execute($email = '', $password = '')
{
yield ActivityStub::make(SendEmailVerificationEmailActivity::class, $email);
yield activity(SendEmailVerificationEmailActivity::class, $email);

yield WorkflowStub::await(fn () => $this->verified);
yield await(fn () => $this->verified);

yield ActivityStub::make(VerifyEmailActivity::class, $email, $password);
yield activity(VerifyEmailActivity::class, $email, $password);
}
}
```
Expand All @@ -100,9 +99,9 @@ Step By Step

The first time the workflow executes, it will reach the call to `SendEmailVerificationEmailActivity` , start that activity, and then exit. Workflows suspend execution while an activity is running. After the `SendEmailVerificationEmailActivity` finishes, it will resume execution of the workflow. This brings us to…

The second time the workflow is executed, it will reach the call to `SendEmailVerificationEmailActivity` and skip it because it will already have the result of that activity. Then it will reach the call to `WorkflowStub::await()` which allows the workflow to wait for an external signal. In this case, it will come from the user clicking on the verification link they receive in their email. Once the workflow is signaled then it will execute for…
The second time the workflow is executed, it will reach the call to `SendEmailVerificationEmailActivity` and skip it because it will already have the result of that activity. Then it will reach the call to `await()` which allows the workflow to wait for an external signal. In this case, it will come from the user clicking on the verification link they receive in their email. Once the workflow is signaled then it will execute for…

The third time, both the calls to `SendEmailVerificationEmailActivity` and `WorkflowStub::await()` are skipped. This means that the `VerifyEmailActivity` will be started. After the final activity has executed we still have…
The third time, both the calls to `SendEmailVerificationEmailActivity` and `await()` are skipped. This means that the `VerifyEmailActivity` will be started. After the final activity has executed we still have…

The final time the workflow is called, there is nothing left to do so the workflow completes.

Expand Down
4 changes: 2 additions & 2 deletions blog/2022-10-31-converting-videos-with-ffmpeg.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ For simplicity, the workflow we are making today will only contain the most inte
```php
namespace App\Workflows\ConvertVideo;

use Workflow\ActivityStub;
use function Workflow\activity;
use Workflow\Workflow;

class ConvertVideoWorkflow extends Workflow
{
public function execute()
{
yield ActivityStub::make(
yield activity(
ConvertVideoWebmActivity::class,
storage_path('app/oceans.mp4'),
storage_path('app/oceans.webm'),
Expand Down
11 changes: 5 additions & 6 deletions blog/2022-11-15-invalidating-cloud-images.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,22 @@ The workflow looks as follows and is the same process as outlined before.
```php
namespace App\Workflows\InvalidateCache;

use Workflow\ActivityStub;
use Workflow\Workflow;
use Workflow\WorkflowStub;
use function Workflow\{activity, timer};

class InvalidateCacheWorkflow extends Workflow
{
public function execute($url)
{
$oldDate = yield ActivityStub::make(CheckImageDateActivity::class, $url);
$oldDate = yield activity(CheckImageDateActivity::class, $url);

while (true) {
yield ActivityStub::make(InvalidateCacheActivity::class, $url);
yield activity(InvalidateCacheActivity::class, $url);

for ($i = 0; $i < 3; ++$i) {
yield WorkflowStub::timer(30);
yield timer(30);

$newDate = yield ActivityStub::make(CheckImageDateActivity::class, $url);
$newDate = yield activity(CheckImageDateActivity::class, $url);

if ($oldDate !== $newDate) return;
}
Expand Down
12 changes: 6 additions & 6 deletions blog/2022-12-06-job-chaining-vs-fan-out-fan-in.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ The workflow divides the task of creating a PDF into activities, with each activ
```php
namespace App\Workflows\BuildPDF;

use Workflow\ActivityStub;
use Workflow\Workflow;
use function Workflow\{activity, all};

class BuildPDFWorkflow extends Workflow
{
public function execute()
{
$page1 = ActivityStub::make(ConvertURLActivity::class, 'https://example.com/');
$page2 = ActivityStub::make(ConvertURLActivity::class, 'https://example.com/');
$page1 = activity(ConvertURLActivity::class, 'https://example.com/');
$page2 = activity(ConvertURLActivity::class, 'https://example.com/');

$pages = yield ActivityStub::all([$page1, $page2]);
$pages = yield all([$page1, $page2]);

$result = yield ActivityStub::make(MergePDFActivity::class, $pages);
$result = yield activity(MergePDFActivity::class, $pages);

return $result;
}
Expand Down Expand Up @@ -76,7 +76,7 @@ class ConvertURLActivity extends Activity
}
```

Next, the `BuildPDFWorkflow` uses `ActivityStub::all` to wait for both `ConvertURLActivity` instances to complete. This is an example of the fan-in part of the fan-out/fan-in pattern, as it collects the results of the parallel activities and combines them into a single array of PDF files.
Next, the `BuildPDFWorkflow` uses `all()` to wait for both `ConvertURLActivity` instances to complete. This is an example of the fan-in part of the fan-out/fan-in pattern, as it collects the results of the parallel activities and combines them into a single array of PDF files.

Finally, the `BuildPDFWorkflow` executes the`MergePDFActivity`, which is passed the array of PDFs that were generated by the `ConvertURLActivity` instances, and merges them into a single PDF document.

Expand Down
13 changes: 8 additions & 5 deletions blog/2022-12-22-new-laravel-workflow-feature-side-effects.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,32 @@ Recently, Laravel Workflow added support for [side effects](https://laravel-work
Here is an example workflow that demonstrates side effects.

```php
use Workflow\Workflow;
use function Workflow\{activity, sideEffect};

class SideEffectWorkflow extends Workflow
{
public function execute()
{
$sideEffect = yield WorkflowStub::sideEffect(
$sideEffect = yield sideEffect(
fn () => random\_int(PHP\_INT\_MIN, PHP\_INT\_MAX)
);

$badSideEffect = random\_int(PHP\_INT\_MIN, PHP\_INT\_MAX);

$result1 = yield ActivityStub::make(SimpleActivity::class, $sideEffect);
$result1 = yield activity(SimpleActivity::class, $sideEffect);

$result2 = yield ActivityStub::make(SimpleActivity::class, $badSideEffect);
$result2 = yield activity(SimpleActivity::class, $badSideEffect);

if ($sideEffect !== $result1) {
throw new Exception(
'These side effects should match because it was properly wrapped in WorkflowStub::sideEffect().'
'These side effects should match because it was properly wrapped in sideEffect().'
);
}

if ($badSideEffect === $result2) {
throw new Exception(
'These side effects should not match because it was not wrapped in WorkflowStub::sideEffect().'
'These side effects should not match because it was not wrapped in sideEffect().'
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Laravel Workflow has introduced an exciting new feature called “Child Workflow
What are Child Workflows?
=========================

In Laravel Workflow, child workflows are a way to manage complex processes by breaking them down into smaller, more manageable units. They enable developers to create hierarchical and modular structures for their workflows, making them more organized and easier to maintain. A child workflow is essentially a separate workflow that is invoked within a parent workflow using the `ChildWorkflowStub::make()` method.
In Laravel Workflow, child workflows are a way to manage complex processes by breaking them down into smaller, more manageable units. They enable developers to create hierarchical and modular structures for their workflows, making them more organized and easier to maintain. A child workflow is essentially a separate workflow that is invoked within a parent workflow using the `child()` helper function.

Benefits of Using Child Workflows
=================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ use Finite\StatefulInterface;
use Finite\StateMachine\StateMachine;
use Finite\State\State;
use Finite\State\StateInterface;
use function Workflow\await;
use Workflow\Models\StoredWorkflow;
use Workflow\SignalMethod;
use Workflow\WorkflowStub;
use Workflow\Workflow;

class LoanApplicationWorkflow extends Workflow implements StatefulInterface
Expand Down Expand Up @@ -127,11 +127,11 @@ class LoanApplicationWorkflow extends Workflow implements StatefulInterface
{
// loan created

yield WorkflowStub::await(fn () => $this->isSubmitted());
yield await(fn () => $this->isSubmitted());

// loan submitted

yield WorkflowStub::await(fn () => $this->isApproved() || $this->isDenied());
yield await(fn () => $this->isApproved() || $this->isDenied());

// loan approved/denied

Expand Down
36 changes: 21 additions & 15 deletions blog/2023-05-21-saga-pattern-and-laravel-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,17 @@ class BookingSagaWorkflow extends Workflow
Next, we’ll imbue our saga with logic, by adding booking steps:

```php
use function Workflow\activity;
use Workflow\Workflow;

class BookingSagaWorkflow extends Workflow
{
public function execute()
{
try {
$flightId = yield ActivityStub::make(BookFlightActivity::class);
$hotelId = yield ActivityStub::make(BookHotelActivity::class);
$carId = yield ActivityStub::make(BookRentalCarActivity::class);
$flightId = yield activity(BookFlightActivity::class);
$hotelId = yield activity(BookHotelActivity::class);
$carId = yield activity(BookRentalCarActivity::class);
} catch (Throwable $th) {
}
}
Expand All @@ -81,19 +84,22 @@ Adding Compensations
--------------------

```php
use function Workflow\activity;
use Workflow\Workflow;

class BookingSagaWorkflow extends Workflow
{
public function execute()
{
try {
$flightId = yield ActivityStub::make(BookFlightActivity::class);
$this->addCompensation(fn () => ActivityStub::make(CancelFlightActivity::class, $flightId));
$flightId = yield activity(BookFlightActivity::class);
$this->addCompensation(fn () => activity(CancelFlightActivity::class, $flightId));

$hotelId = yield ActivityStub::make(BookHotelActivity::class);
$this->addCompensation(fn () => ActivityStub::make(CancelHotelActivity::class, $hotelId));
$hotelId = yield activity(BookHotelActivity::class);
$this->addCompensation(fn () => activity(CancelHotelActivity::class, $hotelId));

$carId = yield ActivityStub::make(BookRentalCarActivity::class);
$this->addCompensation(fn () => ActivityStub::make(CancelRentalCarActivity::class, $carId));
$carId = yield activity(BookRentalCarActivity::class);
$this->addCompensation(fn () => activity(CancelRentalCarActivity::class, $carId));
} catch (Throwable $th) {
}
}
Expand All @@ -113,14 +119,14 @@ class BookingSagaWorkflow extends Workflow
public function execute()
{
try {
$flightId = yield ActivityStub::make(BookFlightActivity::class);
$this->addCompensation(fn () => ActivityStub::make(CancelFlightActivity::class, $flightId));
$flightId = yield activity(BookFlightActivity::class);
$this->addCompensation(fn () => activity(CancelFlightActivity::class, $flightId));

$hotelId = yield ActivityStub::make(BookHotelActivity::class);
$this->addCompensation(fn () => ActivityStub::make(CancelHotelActivity::class, $hotelId));
$hotelId = yield activity(BookHotelActivity::class);
$this->addCompensation(fn () => activity(CancelHotelActivity::class, $hotelId));

$carId = yield ActivityStub::make(BookRentalCarActivity::class);
$this->addCompensation(fn () => ActivityStub::make(CancelRentalCarActivity::class, $carId));
$carId = yield activity(BookRentalCarActivity::class);
$this->addCompensation(fn () => activity(CancelRentalCarActivity::class, $carId));
} catch (Throwable $th) {
yield from $this->compensate();
throw $th;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ In a microservices architecture, decoupling is the name of the game. You want ea

#### 1. Create a workflow.
```php
use Workflow\ActivityStub;
use function Workflow\activity;
use Workflow\Workflow;

class MyWorkflow extends Workflow
{
public function execute($name)
{
$result = yield ActivityStub::make(MyActivity::class, $name);
$result = yield activity(MyActivity::class, $name);
return $result;
}
}
Expand Down Expand Up @@ -159,7 +159,7 @@ class MyWorkflow extends Workflow

public function execute($name)
{
yield ActivityStub::make(MyActivity::class, $name);
yield activity(MyActivity::class, $name);
}
}
class MyActivity extends Activity
Expand Down
15 changes: 7 additions & 8 deletions blog/2023-08-20-ai-image-moderation-with-laravel-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,9 @@ class ClarifAI
```php
namespace App\Workflows;

use Workflow\ActivityStub;
use Workflow\SignalMethod;
use Workflow\WorkflowStub;
use Workflow\Workflow;
use function Workflow\{activity, all, awaitWithTimeout};

class ImageModerationWorkflow extends Workflow
{
Expand Down Expand Up @@ -124,23 +123,23 @@ class ImageModerationWorkflow extends Workflow

private function check($imagePath)
{
return yield ActivityStub::make(AutomatedImageCheckActivity::class, $imagePath);
return yield activity(AutomatedImageCheckActivity::class, $imagePath);
}

private function unsafe($imagePath)
{
yield ActivityStub::all([
ActivityStub::make(LogUnsafeImageActivity::class, $imagePath),
ActivityStub::make(DeleteImageActivity::class, $imagePath),
yield all([
activity(LogUnsafeImageActivity::class, $imagePath),
activity(DeleteImageActivity::class, $imagePath),
]);
}

private function moderate($imagePath)
{
while (true) {
yield ActivityStub::make(NotifyImageModeratorActivity::class, $imagePath);
yield activity(NotifyImageModeratorActivity::class, $imagePath);

$signaled = yield WorkflowStub::awaitWithTimeout('24 hours', fn () => $this->approved || $this->rejected);
$signaled = yield awaitWithTimeout('24 hours', fn () => $this->approved || $this->rejected);

if ($signaled) break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,16 @@ class Playwright extends Command
```php
namespace App\Workflows\Playwright;

use Workflow\ActivityStub;
use function Workflow\activity;
use Workflow\Workflow;

class CheckConsoleErrorsWorkflow extends Workflow
{
public function execute(string $url)
{
$result = yield ActivityStub::make(CheckConsoleErrorsActivity::class, $url);
$result = yield activity(CheckConsoleErrorsActivity::class, $url);

$mp4 = yield ActivityStub::make(ConvertVideoActivity::class, $result['video']);
$mp4 = yield activity(ConvertVideoActivity::class, $result['video']);

return [
'errors' => $result['errors'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,16 @@ class Prism extends Command

2. Define the Workflow Logic
```php
use Workflow\ActivityStub;
use function Workflow\activity;
use Workflow\Workflow;

class PrismWorkflow extends Workflow
{
public function execute()
{
do {
$user = yield ActivityStub::make(GenerateUserActivity::class);
$valid = yield ActivityStub::make(ValidateUserActivity::class, $user);
$user = yield activity(GenerateUserActivity::class);
$valid = yield activity(ValidateUserActivity::class, $user);
} while (!$valid);

return $user;
Expand Down