vanta / temporal-bundle
Integration temporal with symfony
Installs: 6 470
Dependents: 0
Suggesters: 0
Security: 0
Stars: 10
Watchers: 0
Forks: 6
Open Issues: 1
Type:symfony-bundle
Requires
- php: ^8.2
- symfony/dependency-injection: ^6.0|^7.0
- symfony/http-kernel: ^6.0|^7.0
- symfony/runtime: ^6.0|^7.0
- temporal/sdk: ^2.9
Requires (Dev)
- doctrine/doctrine-bundle: ^2.10
- doctrine/orm: ^2.15
- friendsofphp/php-cs-fixer: 3.65.0
- nyholm/symfony-bundle-test: ^3.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^10.3
- psr/log: ^3.0
- sentry/sentry-symfony: ^4.10
- symfony/monolog-bundle: ^3.8
- symfony/serializer: ^6.0|^7.0
- symfony/web-profiler-bundle: ^6.0|^7.0
- vanta/temporal-sentry: ^0.1.1
Suggests
- vanta/temporal-sentry: Integration for sentry
README
Temporal is the simple, scalable open source way to write and run reliable cloud applications.
Features
- 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)
Requirements:
- php >= 8.2
- symfony >= 6.0
Installation:
- 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.
Doctrine integrations
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)%'
Sentry integrations
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
Worker Factory
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
Assign worker
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; }
TODO
- E2E test
- documentation