Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next #31

Merged
merged 53 commits into from
Feb 16, 2024
Merged

Next #31

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
8643a6f
drop support for Arrayable and Jsonable payloads and add base support…
cappuc Oct 5, 2023
040ea03
drop support for laravel 9.0 and temporal <2.6
cappuc Oct 5, 2023
bf1fb97
wip
cappuc Oct 5, 2023
1332dd1
wip
cappuc Oct 6, 2023
ace7751
wip
cappuc Oct 6, 2023
e803605
Merge branch 'main' into next
cappuc Dec 28, 2023
c568ac1
require temporal sdk 2.7
cappuc Dec 28, 2023
6457d28
Merge branch 'main' into next
cappuc Jan 2, 2024
cd63800
fixed tests
cappuc Jan 2, 2024
3b579f9
phpstan level 7
cappuc Jan 2, 2024
ac40d1e
improved phpstan extension
cappuc Jan 2, 2024
8998e8b
Merge branch 'main' into next
cappuc Jan 3, 2024
9843810
added temporal registry
cappuc Jan 3, 2024
e73d4da
interceptors
cappuc Jan 3, 2024
67c6f8d
pass interceptors to workflow client
cappuc Jan 4, 2024
8efa93b
fix tests with lowest dependencies
cappuc Jan 4, 2024
b320078
set timeout for tests job
cappuc Jan 4, 2024
85857ff
updated rector
cappuc Jan 4, 2024
5fdbd92
run workflow and activities inside a sandbox app
cappuc Jan 4, 2024
f601968
fix app sandbox interceptor
cappuc Jan 14, 2024
4421833
update
cappuc Jan 14, 2024
cf486a0
interceptor make command
cappuc Jan 15, 2024
853bfa7
refactoring make commands
cappuc Jan 15, 2024
954624b
added command attribute
cappuc Jan 15, 2024
18fe356
fix
cappuc Jan 15, 2024
69e9655
use dev server from temporal cli by default
cappuc Jan 16, 2024
14c4cdc
fix
cappuc Jan 17, 2024
153ca21
updated README
cappuc Jan 17, 2024
cae8830
Fix styling
cappuc Jan 17, 2024
6854f31
update
cappuc Jan 19, 2024
c9fca8e
update
cappuc Feb 5, 2024
4950746
fix ci
cappuc Feb 5, 2024
8ab1f6d
updated rector
cappuc Feb 14, 2024
bc81383
setup laravel data tests
cappuc Feb 14, 2024
d75d663
support laravel data v4
cappuc Feb 14, 2024
0da4749
Fix styling
cappuc Feb 14, 2024
1bdf424
wip
cappuc Feb 14, 2024
9d31213
extracted serializer
cappuc Feb 14, 2024
e1b42ec
fix ci
cappuc Feb 15, 2024
23a6afc
wip
cappuc Feb 15, 2024
5888703
exclude cast & transformer from phpstan
cappuc Feb 15, 2024
159d3da
test data items with collections
cappuc Feb 15, 2024
3963313
wip: merge cast and transformer
cappuc Feb 16, 2024
3b539b7
v3 implementation
cappuc Feb 16, 2024
32616fa
updated readme
cappuc Feb 16, 2024
5c463bf
fix serializer return type
cappuc Feb 16, 2024
0691eba
test data collection with v4
cappuc Feb 16, 2024
4fc80fa
restored old cast/transformed as deprecated
cappuc Feb 16, 2024
9b237dc
Merge pull request #32 from keepsuit/laravel-data-v4
cappuc Feb 16, 2024
b090080
add support for laravel 11
cappuc Feb 16, 2024
dbbd593
run tests on laravel 11
cappuc Feb 16, 2024
7694c6f
skip laravel data v3 with laravel 11
cappuc Feb 16, 2024
ae22251
Merge pull request #33 from keepsuit/laravel-11
cappuc Feb 16, 2024
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
6 changes: 5 additions & 1 deletion .github/workflows/fix-php-code-style-issues.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Fix PHP code style issues

on: [push]
on:
push:
branches:
- main
pull_request:

jobs:
php-code-styling:
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ name: PHPStan

on:
pull_request:
branches: [ main ]
push:
branches:
- main
paths:
- '**.php'
- 'phpstan.neon'
Expand All @@ -20,7 +21,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
php-version: '8.2'
coverage: none

- name: Install composer dependencies
Expand Down
24 changes: 16 additions & 8 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,28 @@ name: run-tests

on:
push:
branches: [main]
branches:
- main
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: true
fail-fast: false
matrix:
php: [8.1, 8.2, 8.3]
laravel: [^9.0, ^10.0]
stability: [prefer-stable]

name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }}
php: [ 8.1, 8.2 , 8.3 ]
laravel: [ ^10.0, ^11.0 ]
stability: [ prefer-stable, prefer-lowest ]
laravelData: [ ^3.0, ^4.0 ]
exclude:
- php: 8.1
laravel: ^11.0
- laravel: ^11.0
laravelData: ^3.0

name: P${{ matrix.php }} - L${{ matrix.laravel }} - D${{ matrix.laravelData }} - ${{ matrix.stability }}

steps:
- name: Checkout code
Expand All @@ -37,6 +44,7 @@ jobs:
- name: Install dependencies
run: |
composer require "illuminate/contracts:${{ matrix.laravel }}" --no-interaction --no-update
composer require "spatie/laravel-data:${{ matrix.laravelData }}" --no-interaction --no-update
composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress

- name: Execute tests
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.idea
.phpunit.cache
.phpunit.result.cache
build
composer.lock
Expand Down
64 changes: 56 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ architecture_.

This package provides:

- Commands to create a new workflow and activity
- Commands to create a new workflow, activity and interceptor
- Command to start the worker which will execute workflows and activities from the provided task queue
- Command to start a temporal dev server
- Testing helpers that allows mock of workflows and activities executions

## Installation
Expand All @@ -25,6 +26,12 @@ composer require keepsuit/laravel-temporal

Then download the latest `roadrunner` executable for your platform:

```bash
php artisan temporal:install
```

or

```bash
./vendor/bin/rr get-binary
```
Expand Down Expand Up @@ -122,6 +129,12 @@ return [
'maximum_attempts' => null,
],
],

/**
* Interceptors (middlewares) registered in the worker
*/
'interceptors' => [
],

/**
* Manual register workflows
Expand Down Expand Up @@ -164,7 +177,7 @@ return [
*/
'deserialize_attribute_case' => null,

/*
/**
* If true adds a `__exists` attribute to the serialized model
* which indicate that the model is saved to database and it is used on deserialization when creating the model.
* If false (or `__exists` is not present) the model will be created as existing model if primary key is present.
Expand All @@ -183,18 +196,37 @@ the [official documentation](https://docs.temporal.io/application-development/?l

### Create workflows and activities

To create a new workflow, you can use the `make:workflow {name}` command, which will create a new workflow interface & relative class in
To create a new workflow, you can use the `temporal:make:workflow {name}` command, which will create a new workflow interface & relative class in
the `app/Temporal/Workflows` directory.

To create a new activity, you can use the `make:activity {name}` command, which will create a new activity interface & relative class in
To create a new activity, you can use the `temporal:make:activity {name}` command, which will create a new activity interface & relative class in
the `app/Temporal/Activities` directory.

> [!NOTE]
> If you already have workflow/activities in `app/Workflows` and `app/Activities` directories,
> the make commands will create the new workflow/activity in the these directories.

Workflows in `app/Temporal/Workflows` and `app/Workflows` and activities in `app/Temporal/Activities`, `app/Activities`, `app/Temporal/Workflows` and `app/Workflows` are automatically registered.
If you put your workflows and activities in other directories, you can register them manually in the `workflows` and `activities` config keys.
If you put your workflows and activities in other directories, you can register them manually in the `workflows` and `activities` config keys or with `TemporalRegistry` in your service provider.

```php
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->callAfterResolving(\Keepsuit\LaravelTemporal\TemporalRegistry::class, function (\Keepsuit\LaravelTemporal\TemporalRegistry $registry) {
$registry->registerWorkflows(YourWorkflowInterface::class)
->registerActivities(YourActivityInterface::class);
}

// or

Temporal::registry()
->registerWorkflows(YourWorkflowInterface::class)
->registerActivities(YourActivityInterface::class);
}
}
```

### Build and start a workflow

Expand All @@ -209,7 +241,7 @@ $workflow = Temporal::newWorkflow()
$result = $workflow->yourMethod();

// This will start a new workflow execution and return immediately
app(\Temporal\Client\WorkflowClientInterface::class)->start($workflow);
Temporal::workflowClient()->start($workflow);
```

### Build and start an activity
Expand Down Expand Up @@ -247,9 +279,17 @@ This package adds some laravel specific options for serialization/deserializatio
- Eloquent models can be correctly serialized/deserialized (with relations) adding `TemporalSerializable` interface and `TemporalEloquentSerialize` trait.
- [spatie/laravel-data](https://github.com/spatie/laravel-data) data objects are supported out of the box.

> To improve laravel-data support, this package provides `TemporalSerializableCast` and `TemporalSerializableTransformer`
> To improve laravel-data support, this package provides `TemporalSerializableCastAndTransformer` (which implements cast and transformer for laravel-data).
> to add support for serialization/deserialization of `TemporalSerializable` objects used as `Data` properties.
> You can add them to `data.casts` and `data.transformers` config to add support globally.
> You can add them to `data.casts` and `data.transformers` config to add support globally,
> or use it with `WithCast`, `WithTransformer` attributes to add support to specific data objects (in v4 the attributes can be combined with `WithCastAndTransform`).

### Interceptors

Temporal interceptors are similar to laravel middleware and can be used to modify inbound and outbound SDK calls.
Interceptors can be registered in the `interceptors` config key.
See [temporal sdk v2.7](https://github.com/temporalio/sdk-php/releases/tag/v2.7.0) release notes for more information.
To create a new interceptor, you can use the `temporal:make:interceptor {name}` command, which will create a new interceptor class in the `app/Temporal/Interceptors` directory.

### Run the temporal worker

Expand All @@ -266,6 +306,14 @@ This package provides two options to run a temporal server for testing purposes:
> When using `WithTemporal` trait, you can set `TEMPORAL_TESTING_SERVER` env variable to `false`
> to disable the testing server and run only the worker.

### Time skipping

The default temporal server implementation is the dev server included in the temporal cli and this doesn't support time skipping.
In order to enable time skipping, you must:

- Run the `temporal:server` command with the `--enable-time-skipping` flag.
- Set `TEMPORAL_TESTING_SERVER_TIME_SKIPPING` env variable to `true` when using `WithTemporal` trait.

### Mocking workflows

Mocking a workflow can be useful when the workflow should be executed in another service or simply when you want to test other parts of your code
Expand Down
20 changes: 15 additions & 5 deletions bin/roadrunner-temporal-worker
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@
<?php
declare(strict_types=1);

use Keepsuit\LaravelTemporal\Interceptors\ApplicationSandboxInterceptor;
use Keepsuit\LaravelTemporal\Support\ApplicationFactory;
use Keepsuit\LaravelTemporal\TemporalDiscovery;
use Keepsuit\LaravelTemporal\Support\CurrentApplication;
use Keepsuit\LaravelTemporal\TemporalRegistry;
use Spiral\Goridge\Exception\RelayException;
use Temporal\DataConverter\DataConverterInterface;
use Temporal\Interceptor\SimplePipelineProvider;
use Temporal\WorkerFactory;

$basePath = require __DIR__.'/bootstrap.php';

$app = (new ApplicationFactory($basePath))->createApplication();
CurrentApplication::setRootApp($app);

if ($app->environment() !== 'production' && env('TEMPORAL_TESTING_ENV')) {
\Keepsuit\LaravelTemporal\Facade\Temporal::initFakeWorker();
}

/** @var TemporalDiscovery $discovery */
$discovery = $app->make(TemporalDiscovery::class);
/** @var TemporalRegistry $registry */
$registry = $app->make(TemporalRegistry::class);

// factory initiates and runs task queue specific activity and workflow workers
$factory = WorkerFactory::create(
Expand All @@ -27,13 +31,19 @@ $factory = WorkerFactory::create(
// Worker that listens on a Task Queue and hosts both workflow and activity implementations.
$worker = $factory->newWorker(
taskQueue: env('TEMPORAL_QUEUE'),
interceptorProvider: new SimplePipelineProvider(array_map(
fn (string $className) => $app->make($className),
array_merge([
ApplicationSandboxInterceptor::class,
], $app['config']->get('temporal.interceptors', []))
))
);

foreach ($discovery->getWorkflows() as $workflow) {
foreach ($registry->workflows() as $workflow) {
$worker->registerWorkflowTypes($workflow);
}

foreach ($discovery->getActivities() as $activity) {
foreach ($registry->activities() as $activity) {
$worker->registerActivity($activity, fn (ReflectionClass $class) => $app->make($class->getName()));
}

Expand Down
40 changes: 20 additions & 20 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,35 @@
"require": {
"php": "^8.1",
"composer/class-map-generator": "^1.0",
"illuminate/contracts": "^9.0 || ^10.0",
"spatie/laravel-package-tools": "^1.9.2",
"spiral/roadrunner-cli": "^2.2 || ^3.0",
"symfony/process": "^6.0",
"temporal/sdk": "^2.0"
"illuminate/contracts": "^10.0 || ^11.0",
"spatie/laravel-package-tools": "^1.14.0",
"spiral/roadrunner": "^2023.2.0",
"spiral/roadrunner-cli": "^2.5",
"symfony/process": "^6.0 || ^7.0",
"temporal/sdk": "~2.7.4",
"thecodingmachine/safe": "^2.0"
},
"require-dev": {
"driftingly/rector-laravel": "^0.26.0",
"dereuromark/composer-prefer-lowest": "^0.1.10",
"larastan/larastan": "^2.8.1",
"laravel/pint": "^1.0",
"nesbot/carbon": "^2.63.0",
"nunomaduro/collision": "^6.0",
"larastan/larastan": "^2.0.1",
"orchestra/testbench": "^7.0 || ^8.0",
"pestphp/pest": "^1.21",
"pestphp/pest-plugin-laravel": "^1.1",
"mockery/mockery": "^1.6",
"nesbot/carbon": "^2.63 || ^3.0",
"nunomaduro/collision": "^7.0 || ^8.0",
"orchestra/testbench": "^8.0 || ^9.0",
"pestphp/pest": "^2.30",
"pestphp/pest-plugin-laravel": "^2.2",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
"rector/rector": "^0.18.2",
"rector/rector": "^1.0",
"spatie/invade": "^2.0",
"spatie/laravel-data": "^2.0 || ^3.0",
"spatie/laravel-ray": "^1.26"
"spatie/laravel-data": "^4.0",
"spatie/laravel-ray": "^1.26",
"thecodingmachine/phpstan-safe-rule": "^1.2"
},
"suggest": {
"spatie/laravel-data": "Can be used for workflows payloads (^2.0 || ^3.0)"
},
"conflict": {
"temporal/sdk": ">=2.7.0",
"orchestra/testbench-core": "> 8.15.0"
"spatie/laravel-data": "Can be used for workflows payloads (^3.0 || ^4.0)"
},
"autoload": {
"psr-4": {
Expand Down
6 changes: 6 additions & 0 deletions config/temporal.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@
],
],

/**
* Interceptors (middlewares) registered in the worker
*/
'interceptors' => [
],

/**
* Manual register workflows
*/
Expand Down
8 changes: 8 additions & 0 deletions extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ services:
class: Keepsuit\LaravelTemporal\PHPStan\TemporalChildWorkflowProxyExtension
tags:
- phpstan.broker.methodsClassReflectionExtension
-
class: Keepsuit\LaravelTemporal\PHPStan\TemporalWorkflowContextInterfaceExtension
tags:
- phpstan.broker.dynamicMethodReturnTypeExtension
-
class: Keepsuit\LaravelTemporal\PHPStan\TemporalWorkflowClientInterfaceExtension
tags:
- phpstan.broker.dynamicMethodReturnTypeExtension

parameters:
stubFiles:
Expand Down
7 changes: 5 additions & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ includes:
- phpstan-baseline.neon

parameters:
level: 6
level: 7
paths:
- src
- config
Expand All @@ -12,6 +12,9 @@ parameters:
checkModelProperties: true
checkMissingIterableValueType: false
checkGenericClassInNonGenericObjectType: false
treatPhpDocTypesAsCertain: false

excludePaths:
- src/Integrations/LaravelData/TemporalSerializableCastAndTransformer.php

ignoreErrors:
- '#Unable to resolve the template type TMergeRecursiveValue in call to method Illuminate\\Support\\Collection.*::mergeRecursive#'
Loading
Loading