Temporal is the simple, scalable open source way to write and run reliable cloud applications.
- Sentry: Send throwable events (if the
SentryBundle
use) - Doctrine: clear opened managers and check connection is still usable after each request (
if
DoctrineBundle
is use) - Serializer: Deserialize and serialize messages (if
Symfony/Serializer
is use, Recommend use)
- php >= 8.2
- symfony >= 6.0
- Connect recipes
composer config --json extra.symfony.endpoint '["https://raw.githubusercontent.com/VantaFinance/temporal-bundle/main/.recipie/index.json", "flex://defaults"]'
- Install package
composer req temporal serializer
-
Configure docker-compose-temporal.yml/Dockerfile
-
Added Workflow/Activity. See examples to get started.
If DoctrineBundle
is use, the following finalizer is available to you:
temporal.doctrine_ping_connection_<entity-mananger-name>.finalizer
temporal.doctrine_clear_entity_manager.finalizer
And interceptors:
temporal.doctrine_ping_connection_<entity-mananger-name>_activity_inbound.interceptor
Example config:
temporal:
defaultClient: default
pool:
dataConverter: temporal.data_converter
roadrunnerRPC: '%env(RR_RPC)%'
workers:
default:
taskQueue: default
exceptionInterceptor: temporal.exception_interceptor
finalizers:
- temporal.doctrine_ping_connection_default.finalizer
- temporal.doctrine_clear_entity_manager.finalizer
interceptors:
- temporal.doctrine_ping_connection_default_activity_inbound.interceptor
clients:
default:
namespace: default
address: '%env(TEMPORAL_ADDRESS)%'
dataConverter: temporal.data_converter
cloud:
namespace: default
address: '%env(TEMPORAL_ADDRESS)%'
dataConverter: temporal.data_converter
clientKey: '%env(TEMPORAL_CLIENT_KEY_PATH)%'
clientPem: '%env(TEMPORAL_CLIENT_CERT_PATH)%'
Install packages:
composer require sentry temporal-sentry
If SentryBundle
is use, the following interceptors is available to you:
temporal.sentry_workflow_outbound_calls.interceptor
temporal.sentry_activity_inbound.interceptor
Example config:
temporal:
defaultClient: default
pool:
dataConverter: temporal.data_converter
roadrunnerRPC: '%env(RR_RPC)%'
workers:
default:
taskQueue: default
exceptionInterceptor: temporal.exception_interceptor
interceptors:
- temporal.sentry_workflow_outbound_calls.intercepto
- temporal.sentry_activity_inbound.interceptor
clients:
default:
namespace: default
address: '%env(TEMPORAL_ADDRESS)%'
dataConverter: temporal.data_converter
By default the Temporal\WorkerFactory
is used to instantiate the workers. However when you are unit-testing you
may wish to override the default factory with the one provided by the 'Testing framework'
Example Config:
temporal:
defaultClient: default
pool:
dataConverter: temporal.data_converter
roadrunnerRPC: '%env(RR_RPC)%'
workers:
default:
taskQueue: default
exceptionInterceptor: temporal.exception_interceptor
interceptors:
- temporal.sentry_workflow_outbound_calls.intercepto
- temporal.sentry_activity_inbound.interceptor
clients:
default:
namespace: default
address: '%env(TEMPORAL_ADDRESS)%'
dataConverter: temporal.data_converter
when@test:
temporal:
workerFactory: Temporal\Testing\WorkerFactory
Running workflows and activities with different task queue
Add a AssignWorker
attribute to your Workflow or Activity with the name of the
worker. This Workflow or Activity will be processed by the specified worker.
Workflow example:
<?php
declare(strict_types=1);
namespace App\Workflow;
use Vanta\Integration\Symfony\Temporal\Attribute\AssignWorker;
use Temporal\Workflow\WorkflowInterface;
#[AssignWorker(name: 'worker1')]
#[WorkflowInterface]
final class MoneyTransferWorkflow
{
#[WorkflowMethod]
public function transfer(...): \Generator;
#[SignalMethod]
function withdraw(): void;
#[SignalMethod]
function deposit(): void;
}
Activity example:
<?php
declare(strict_types=1);
namespace App\Workflow;
use Vanta\Integration\Symfony\Temporal\Attribute\AssignWorker;
use Temporal\Activity\ActivityInterface;
use Temporal\Activity\ActivityMethod;
#[AssignWorker(name: 'worker1')]
#[ActivityInterface(...)]
final class MoneyTransferActivity
{
#[ActivityMethod]
public function transfer(...): int;
#[ActivityMethod]
public function cancel(...): bool;
}
- E2E test
- documentation