diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index c592f27..caff662 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -1,17 +1,20 @@ on: - push: - branches: - - master + pull_request: null + push: + branches: + - master + - '*.*' name: phpunit jobs: - phpunit: - uses: spiral/gh-actions/.github/workflows/phpunit.yml@master - with: - os: >- - ['ubuntu-latest'] - php: >- - ['8.1', '8.2'] - stability: >- - ['prefer-stable'] + phpunit: + uses: spiral/gh-actions/.github/workflows/phpunit.yml@master + with: + extensions: sockets, grpc + os: >- + ['ubuntu-latest'] + php: >- + ['8.1', '8.2'] + stability: >- + ['prefer-stable'] diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index 75c416b..96e14a6 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -1,15 +1,17 @@ on: - push: - branches: - - master + pull_request: null + push: + branches: + - master + - '*.*' name: static analysis jobs: - psalm: - uses: spiral/gh-actions/.github/workflows/psalm.yml@master - with: - os: >- - ['ubuntu-latest'] - php: >- - ['8.1'] + psalm: + uses: spiral/gh-actions/.github/workflows/psalm.yml@master + with: + os: >- + ['ubuntu-latest'] + php: >- + ['8.1'] diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml deleted file mode 100644 index 22e258b..0000000 --- a/.github/workflows/run-tests.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: run-tests - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - test: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: true - matrix: - os: [ ubuntu-latest ] - php: [ 8.0, 8.1 ] - stability: [ prefer-lowest, prefer-stable ] - - name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }} - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: sockets, grpc - coverage: none - - - name: Validate Composer - run: composer validate - - - name: Get Composer Cache Directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Restore Composer Cache - uses: actions/cache@v3.3.1 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-${{ matrix.php }}-${{ matrix.stability }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-${{ matrix.php }}-${{ matrix.stability }}-composer - - - name: Install Dependencies - uses: nick-invision/retry@v2.8.3 - with: - timeout_minutes: 5 - max_attempts: 5 - command: composer update --prefer-dist --no-interaction --no-progress - - - name: Execute tests - run: vendor/bin/phpunit diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml deleted file mode 100644 index 86350fc..0000000 --- a/.github/workflows/static-analysis.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: run-tests - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - static-analysis: - name: Psalm - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - php: [ 8.0 ] - os: [ ubuntu-latest ] - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup PHP ${{ matrix.php }} - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - - - name: Validate Composer - run: composer validate - - - name: Get Composer Cache Directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Restore Composer Cache - uses: actions/cache@v3.3.1 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-${{ matrix.php }}-composer - - - name: Install Dependencies - uses: nick-invision/retry@v2.8.3 - with: - timeout_minutes: 5 - max_attempts: 5 - command: composer update --prefer-dist --no-interaction --no-progress - - - name: Static Analysis - run: vendor/bin/psalm --no-cache diff --git a/composer.json b/composer.json index a7c158f..d463880 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "spiral/tokenizer": "^3.0", "spiral/roadrunner-bridge": "^2.0 || ^3.0", "nette/php-generator": "^4.0", - "temporal/sdk": "^1.3 || ^2.0" + "temporal/sdk": "dev-interceptors" }, "require-dev": { "spiral/framework": "^3.0", diff --git a/src/Bootloader/TemporalBridgeBootloader.php b/src/Bootloader/TemporalBridgeBootloader.php index 7c2fb86..09429ed 100644 --- a/src/Bootloader/TemporalBridgeBootloader.php +++ b/src/Bootloader/TemporalBridgeBootloader.php @@ -8,7 +8,6 @@ use Spiral\Boot\AbstractKernel; use Spiral\Boot\Bootloader\Bootloader; use Spiral\Boot\EnvironmentInterface; -use Spiral\Boot\FinalizerInterface; use Spiral\Config\ConfiguratorInterface; use Spiral\Config\Patch\Append; use Spiral\Console\Bootloader\ConsoleBootloader; @@ -20,6 +19,8 @@ use Spiral\TemporalBridge\Dispatcher; use Spiral\TemporalBridge\Preset\PresetRegistry; use Spiral\TemporalBridge\Preset\PresetRegistryInterface; +use Spiral\TemporalBridge\WorkerFactory; +use Spiral\TemporalBridge\WorkerFactoryInterface; use Spiral\TemporalBridge\WorkersRegistry; use Spiral\TemporalBridge\WorkersRegistryInterface; use Spiral\TemporalBridge\Workflow\WorkflowManager; @@ -33,22 +34,26 @@ use Temporal\Client\WorkflowClientInterface; use Temporal\DataConverter\DataConverter; use Temporal\DataConverter\DataConverterInterface; +use Temporal\Interceptor\SimplePipelineProvider; +use Temporal\Interceptor\PipelineProvider; use Temporal\Worker\Transport\Goridge; -use Temporal\Worker\WorkerFactoryInterface; +use Temporal\Worker\WorkerFactoryInterface as TemporalWorkerFactoryInterface; use Temporal\Worker\WorkerOptions; -use Temporal\WorkerFactory; +use Temporal\WorkerFactory as TemporalWorkerFactory; class TemporalBridgeBootloader extends Bootloader { protected const SINGLETONS = [ WorkflowPresetLocatorInterface::class => [self::class, 'initWorkflowPresetLocator'], WorkflowManagerInterface::class => WorkflowManager::class, - WorkerFactoryInterface::class => [self::class, 'initWorkerFactory'], + TemporalWorkerFactoryInterface::class => [self::class, 'initWorkerFactory'], DeclarationLocatorInterface::class => [self::class, 'initDeclarationLocator'], WorkflowClientInterface::class => [self::class, 'initWorkflowClient'], - WorkersRegistryInterface::class => [self::class, 'initWorkersRegistry'], + WorkersRegistryInterface::class => WorkersRegistry::class, PresetRegistryInterface::class => PresetRegistry::class, DataConverterInterface::class => [self::class, 'initDataConverter'], + WorkerFactoryInterface::class => WorkerFactory::class, + PipelineProvider::class => SimplePipelineProvider::class, ]; protected const DEPENDENCIES = [ @@ -99,7 +104,7 @@ protected function initConfig(EnvironmentInterface $env): void [ 'address' => $env->get('TEMPORAL_ADDRESS', '127.0.0.1:7233'), 'namespace' => 'App\\Workflow', - 'defaultWorker' => (string)$env->get('TEMPORAL_TASK_QUEUE', WorkerFactoryInterface::DEFAULT_TASK_QUEUE), + 'defaultWorker' => (string)$env->get('TEMPORAL_TASK_QUEUE', TemporalWorkerFactory::DEFAULT_TASK_QUEUE), 'workers' => [], ] ); @@ -123,8 +128,8 @@ protected function initDataConverter(): DataConverterInterface protected function initWorkerFactory( DataConverterInterface $dataConverter - ): WorkerFactoryInterface { - return new WorkerFactory( + ): TemporalWorkerFactoryInterface { + return new TemporalWorkerFactory( dataConverter: $dataConverter, rpc: Goridge::create() ); @@ -138,12 +143,4 @@ classes: $classes, reader: new AttributeReader() ); } - - protected function initWorkersRegistry( - WorkerFactoryInterface $workerFactory, - FinalizerInterface $finalizer, - TemporalConfig $config - ): WorkersRegistryInterface { - return new WorkersRegistry($workerFactory, $finalizer, $config); - } } diff --git a/src/Commands/MakePresetCommand.php b/src/Commands/MakePresetCommand.php index 82f9f91..7172b56 100644 --- a/src/Commands/MakePresetCommand.php +++ b/src/Commands/MakePresetCommand.php @@ -8,14 +8,19 @@ use Spiral\TemporalBridge\Generator\Generator; use Spiral\TemporalBridge\Preset\PresetRegistryInterface; use Spiral\TemporalBridge\WorkflowPresetLocatorInterface; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; final class MakePresetCommand extends Command { use WithContext; - protected const SIGNATURE = 'temporal:make-preset {preset : Workflow preset} {name : Workflow name}'; + protected const NAME = 'temporal:make-preset'; protected const DESCRIPTION = 'Make a new Temporal workflow preset'; + protected const ARGUMENTS = [ + ['name', InputArgument::REQUIRED, 'Workflow name'], + ['preset', InputArgument::REQUIRED, 'Workflow preset'], + ]; public function perform( Generator $generator, diff --git a/src/Commands/MakeWorkflowCommand.php b/src/Commands/MakeWorkflowCommand.php index 3a7e1c2..5b97bfd 100644 --- a/src/Commands/MakeWorkflowCommand.php +++ b/src/Commands/MakeWorkflowCommand.php @@ -13,14 +13,18 @@ use Spiral\TemporalBridge\Generator\HandlerInterfaceGenerator; use Spiral\TemporalBridge\Generator\WorkflowGenerator; use Spiral\TemporalBridge\Generator\WorkflowInterfaceGenerator; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; final class MakeWorkflowCommand extends Command { use WithContext; - protected const SIGNATURE = 'temporal:make-workflow {name : Workflow name}'; + protected const NAME = 'temporal:make-workflow'; protected const DESCRIPTION = 'Make a new Temporal workflow'; + protected const ARGUMENTS = [ + ['name', InputArgument::REQUIRED, 'Workflow name'], + ]; public function perform(Generator $generator): int { diff --git a/src/Config/TemporalConfig.php b/src/Config/TemporalConfig.php index 3a84343..c3679ba 100644 --- a/src/Config/TemporalConfig.php +++ b/src/Config/TemporalConfig.php @@ -4,10 +4,30 @@ namespace Spiral\TemporalBridge\Config; +use Spiral\Core\Container\Autowire; use Spiral\Core\InjectableConfig; +use Temporal\Exception\ExceptionInterceptorInterface; +use Temporal\Internal\Interceptor\Interceptor; use Temporal\Worker\WorkerFactoryInterface; use Temporal\Worker\WorkerOptions; +/** + * @psalm-type TInterceptor = Interceptor|class-string|Autowire + * @psalm-type TExceptionInterceptor = ExceptionInterceptorInterface|class-string|Autowire + * @psalm-type TWorker = array{ + * options?: WorkerOptions, + * interceptors?: TInterceptor[], + * exception_interceptor?: TExceptionInterceptor + * } + * + * @property array{ + * address: non-empty-string, + * namespace: non-empty-string, + * temporalNamespace: non-empty-string, + * defaultWorker: non-empty-string, + * workers: array + * } $config + */ final class TemporalConfig extends InjectableConfig { public const CONFIG = 'temporal'; @@ -20,29 +40,43 @@ final class TemporalConfig extends InjectableConfig 'workers' => [], ]; + /** + * @return non-empty-string + */ public function getDefaultNamespace(): string { return $this->config['namespace']; } + /** + * @return non-empty-string + */ public function getTemporalNamespace(): string { return $this->config['temporalNamespace']; } + /** + * @return non-empty-string + */ public function getAddress(): string { return $this->config['address']; } + /** + * @return non-empty-string + */ public function getDefaultWorker(): string { return $this->config['defaultWorker']; } - /** @psalm-return array */ + /** + * @return array + */ public function getWorkers(): array { - return (array) $this->config['workers']; + return $this->config['workers'] ?? []; } } diff --git a/src/WorkerFactory.php b/src/WorkerFactory.php new file mode 100644 index 0000000..c21f757 --- /dev/null +++ b/src/WorkerFactory.php @@ -0,0 +1,111 @@ + */ + private array $workers = []; + + public function __construct( + private readonly TemporalWorkerFactory $workerFactory, + private readonly FinalizerInterface $finalizer, + private readonly FactoryInterface $factory, + private readonly TemporalConfig $config + ) { + $this->workers = $this->config->getWorkers(); + } + + /** + * @param non-empty-string $name + */ + public function create(string $name): WorkerInterface + { + /** @psalm-suppress TooManyArguments */ + $worker = $this->workerFactory->newWorker( + $name, + $this->getWorkerOptions($name), + $this->getExceptionInterceptor($name), + $this->getPipelineProvider($name) + ); + $worker->registerActivityFinalizer(fn() => $this->finalizer->finalize()); + + return $worker; + } + + /** + * @param non-empty-string $name + */ + private function getWorkerOptions(string $name): ?WorkerOptions + { + $worker = $this->workers[$name] ?? null; + + return match (true) { + $worker instanceof WorkerOptions => $worker, + isset($worker['options']) && $worker['options'] instanceof WorkerOptions => $worker['options'], + default => null + }; + } + + /** + * @param non-empty-string $name + */ + private function getExceptionInterceptor(string $name): ?ExceptionInterceptorInterface + { + $worker = $this->workers[$name] ?? null; + if (!\is_array($worker) || !isset($worker['exception_interceptor'])) { + return null; + } + + $exceptionInterceptor = $this->wire($worker['exception_interceptor']); + \assert($exceptionInterceptor instanceof ExceptionInterceptorInterface); + + return $exceptionInterceptor; + } + + /** + * @param non-empty-string $name + */ + private function getPipelineProvider(string $name): ?PipelineProvider + { + $worker = $this->workers[$name] ?? null; + if (!\is_array($worker) || !isset($worker['interceptors'])) { + return null; + } + + $interceptors = []; + foreach ($worker['interceptors'] as $interceptor) { + $interceptor = $this->wire($interceptor); + \assert($interceptor instanceof Interceptor); + + $interceptors[] = $interceptor; + } + + return $this->factory->make(PipelineProvider::class, ['interceptors' => $interceptors]); + } + + private function wire(mixed $alias): object + { + return match (true) { + \is_string($alias) => $this->factory->make($alias), + $alias instanceof Autowire => $alias->resolve($this->factory), + default => $alias + }; + } +} diff --git a/src/WorkerFactoryInterface.php b/src/WorkerFactoryInterface.php new file mode 100644 index 0000000..34aa9c8 --- /dev/null +++ b/src/WorkerFactoryInterface.php @@ -0,0 +1,17 @@ + $options */ public function __construct( - private readonly WorkerFactoryInterface $workerFactory, + private readonly WorkerFactoryInterface|TemporalWorkerFactory $workerFactory, private readonly FinalizerInterface $finalizer, private readonly TemporalConfig $config ) { @@ -34,18 +34,22 @@ public function register(string $name, ?WorkerOptions $options): void ); } - $this->workers[$name] = $this->workerFactory->newWorker($name, $options); - $this->workers[$name]->registerActivityFinalizer(fn() => $this->finalizer->finalize()); + if ($this->workerFactory instanceof WorkerFactoryInterface) { + $this->workers[$name] = $this->workerFactory->create($name); + } else { + $this->workers[$name] = $this->workerFactory->newWorker($name, $options); + $this->workers[$name]->registerActivityFinalizer(fn() => $this->finalizer->finalize()); + } } public function get(string $name): WorkerInterface { \assert($name !== ''); - $options = $this->config->getWorkers(); + $options = $this->config->getWorkers()[$name] ?? null; if (! $this->has($name)) { - $this->register($name, $options[$name] ?? null); + $this->register($name, $options instanceof WorkerOptions ? $options : null); } return $this->workers[$name]; diff --git a/src/Workflow/Workflow.php b/src/Workflow/Workflow.php index 48ef8f7..2f33a5e 100644 --- a/src/Workflow/Workflow.php +++ b/src/Workflow/Workflow.php @@ -44,6 +44,9 @@ public function backoffRetryCoefficient(float $coefficient): self return $this; } + /** + * @param positive-int $attempts + */ public function maxRetryAttempts(int $attempts): self { $this->retryOptions = $this->getRetryOptions() diff --git a/tests/app/src/SomeInterceptor.php b/tests/app/src/SomeInterceptor.php new file mode 100644 index 0000000..ba447ca --- /dev/null +++ b/tests/app/src/SomeInterceptor.php @@ -0,0 +1,15 @@ +assertContainerBoundAsSingleton( WorkflowPresetLocatorInterface::class, @@ -38,7 +42,7 @@ public function testWorkflowPresetLocator() ); } - public function testWorkflowManager() + public function testWorkflowManager(): void { $this->mockContainer(ReaderInterface::class); @@ -48,7 +52,15 @@ public function testWorkflowManager() ); } - public function testWorkerFactory() + public function testTemporalWorkerFactory(): void + { + $this->assertContainerBoundAsSingleton( + TemporalWorkerFactoryInterface::class, + TemporalWorkerFactory::class + ); + } + + public function testWorkerFactory(): void { $this->assertContainerBoundAsSingleton( WorkerFactoryInterface::class, @@ -56,7 +68,7 @@ public function testWorkerFactory() ); } - public function testDataConverter() + public function testDataConverter(): void { $this->assertContainerBoundAsSingleton( DataConverterInterface::class, @@ -64,7 +76,7 @@ public function testDataConverter() ); } - public function testDeclarationLocator() + public function testDeclarationLocator(): void { $this->assertContainerBoundAsSingleton( DeclarationLocatorInterface::class, @@ -72,7 +84,7 @@ public function testDeclarationLocator() ); } - public function testWorkflowClient() + public function testWorkflowClient(): void { $this->assertContainerBoundAsSingleton( WorkflowClientInterface::class, @@ -80,7 +92,7 @@ public function testWorkflowClient() ); } - public function testPresetRegistry() + public function testPresetRegistry(): void { $this->assertContainerBoundAsSingleton( PresetRegistryInterface::class, @@ -96,6 +108,14 @@ public function testWorkersRegistry(): void ); } + public function testPipelineProvider(): void + { + $this->assertContainerBound( + PipelineProvider::class, + SimplePipelineProvider::class + ); + } + public function testAddWorkerOptions(): void { $configs = new ConfigManager($this->createMock(LoaderInterface::class)); diff --git a/tests/src/Config/TemporalConfigTest.php b/tests/src/Config/TemporalConfigTest.php index 6f56142..b9427a1 100644 --- a/tests/src/Config/TemporalConfigTest.php +++ b/tests/src/Config/TemporalConfigTest.php @@ -79,7 +79,25 @@ public function testGetsWorkers(): void { $workers = [ 'first' => WorkerOptions::new(), - 'second' => WorkerOptions::new() + 'second' => WorkerOptions::new(), + 'withOptions' => [ + 'options' => WorkerOptions::new(), + ], + 'withInterceptors' => [ + 'interceptors' => [ + 'foo' + ], + ], + 'withExceptionInterceptor' => [ + 'exception_interceptor' => 'bar' + ], + 'all' => [ + 'options' => WorkerOptions::new(), + 'interceptors' => [ + 'foo' + ], + 'exception_interceptor' => 'bar' + ], ]; $config = new TemporalConfig([ diff --git a/tests/src/WorkerFactoryTest.php b/tests/src/WorkerFactoryTest.php new file mode 100644 index 0000000..6acc5fa --- /dev/null +++ b/tests/src/WorkerFactoryTest.php @@ -0,0 +1,178 @@ +temporalWorkerFactory = $this->createMock(TemporalWorkerFactory::class); + } + + public function testCreateWithoutAnyOptions(): void + { + $this->temporalWorkerFactory + ->expects($this->once()) + ->method('newWorker') + ->with('without-any-options') + ->willReturn($worker = $this->createMock(WorkerInterface::class)); + + $factory = $this->createWorkerFactory($this->temporalWorkerFactory); + + $this->assertSame($worker, $factory->create('without-any-options')); + } + + public function testCreateWithOptionsAsValue(): void + { + $this->temporalWorkerFactory + ->expects($this->once()) + ->method('newWorker') + ->with('with-options-as-value', $this->equalTo(WorkerOptions::new()->withEnableSessionWorker())) + ->willReturn($worker = $this->createMock(WorkerInterface::class)); + + $factory = $this->createWorkerFactory($this->temporalWorkerFactory); + + $this->assertSame($worker, $factory->create('with-options-as-value')); + } + + public function testCreateWithOptionsInArray(): void + { + $this->temporalWorkerFactory + ->expects($this->once()) + ->method('newWorker') + ->with('with-options-in-array', $this->equalTo(WorkerOptions::new()->withEnableSessionWorker())) + ->willReturn($worker = $this->createMock(WorkerInterface::class)); + + $factory = $this->createWorkerFactory($this->temporalWorkerFactory); + + $this->assertSame($worker, $factory->create('with-options-in-array')); + } + + /** + * @dataProvider exceptionInterceptorsDataProvider + */ + public function testCreateWithExceptionInterceptor(string $name): void + { + $this->temporalWorkerFactory + ->expects($this->once()) + ->method('newWorker') + ->with($name, null, $this->equalTo(new ExceptionInterceptor([]))) + ->willReturn($worker = $this->createMock(WorkerInterface::class)); + + $factory = $this->createWorkerFactory($this->temporalWorkerFactory); + + $this->assertSame($worker, $factory->create($name)); + } + + public function testCreateWithInterceptors(): void + { + $expectedInterceptors = new SimplePipelineProvider([ + new SomeInterceptor(), + new SomeInterceptor(), + new SomeInterceptor() + ]); + + $this->temporalWorkerFactory + ->expects($this->once()) + ->method('newWorker') + ->with('with-interceptors', null, null, $this->equalTo($expectedInterceptors)) + ->willReturn($worker = $this->createMock(WorkerInterface::class)); + + $factory = $this->createWorkerFactory($this->temporalWorkerFactory); + + $this->assertSame($worker, $factory->create('with-interceptors')); + } + + public function testCreateWithAllOptions(): void + { + $expectedInterceptors = new SimplePipelineProvider([ + new SomeInterceptor(), + new SomeInterceptor(), + new SomeInterceptor() + ]); + + $this->temporalWorkerFactory + ->expects($this->once()) + ->method('newWorker') + ->with( + 'all', + $this->equalTo(WorkerOptions::new()->withEnableSessionWorker()), + $this->equalTo(new ExceptionInterceptor([])), + $this->equalTo($expectedInterceptors) + ) + ->willReturn($worker = $this->createMock(WorkerInterface::class)); + + $factory = $this->createWorkerFactory($this->temporalWorkerFactory); + + $this->assertSame($worker, $factory->create('all')); + } + + public function exceptionInterceptorsDataProvider(): \Traversable + { + yield ['with-exception-interceptor-as-string']; + yield ['with-exception-interceptor-as-autowire']; + yield ['with-exception-interceptor-as-instance']; + } + + private function createWorkerFactory(TemporalWorkerFactory $workerFactory): WorkerFactory + { + $container = new Container(); + $container->bind(PipelineProvider::class, SimplePipelineProvider::class); + $container->bind(ExceptionInterceptor::class, new ExceptionInterceptor([])); + + $interceptors = [ + SomeInterceptor::class, + new SomeInterceptor(), + new Autowire(SomeInterceptor::class) + ]; + + return new WorkerFactory( + $workerFactory, + $this->createMock(FinalizerInterface::class), + $container, + new TemporalConfig([ + 'workers' => [ + 'with-options-as-value' => WorkerOptions::new()->withEnableSessionWorker(), + 'with-options-in-array' => [ + 'options' => WorkerOptions::new()->withEnableSessionWorker() + ], + 'with-interceptors' => [ + 'interceptors' => $interceptors + ], + 'with-exception-interceptor-as-string' => [ + 'exception_interceptor' => ExceptionInterceptor::class + ], + 'with-exception-interceptor-as-autowire' => [ + 'exception_interceptor' => new Autowire(ExceptionInterceptor::class, []) + ], + 'with-exception-interceptor-as-instance' => [ + 'exception_interceptor' => new ExceptionInterceptor([]) + ], + 'all' => [ + 'options' => WorkerOptions::new()->withEnableSessionWorker(), + 'interceptors' => $interceptors, + 'exception_interceptor' => ExceptionInterceptor::class + ] + ] + ]) + ); + } +}