Revision: Sat, 02 Jul 2022 10:45:30 GMT

Temporal integration package for Spiral Framework

PHP Latest Version on Packagist GitHub Tests Action Status Total Downloads

Temporal is the simple, scalable open source way to write and run reliable cloud applications.

Requirements

Make sure that your server is configured with following PHP version and extensions:

  • PHP 8.0+
  • Spiral framework 2.9+

Installation

You can install the package via composer:

composer require spiral/temporal-bridge

After package install you need to register bootloader from the package.

protected const LOAD = [
    // ...
    \Spiral\TemporalBridge\Bootloader\TemporalBridgeBootloader::class,
];

Note: if you are using spiral-packages/discoverer, you don't need to register bootloader by yourself.

RoadRunner configuration

Add temporal plugin section in your RoadRunner rr.yaml config:

temporal:
  address: localhost:7233
  activities:
    num_workers: 10

Temporal

You can run temporal server via docker by using the example below:

You can find official docker compose files here https://github.com/temporalio/docker-compose

version: '3.5'

services:
  postgresql:
    container_name: temporal-postgresql
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: temporal
      POSTGRES_USER: temporal
    ports:
      - 5432:5432

  temporal:
    container_name: temporal
    image: temporalio/auto-setup:1.14.2
    depends_on:
      - postgresql
    environment:
      - DB=postgresql
      - DB_PORT=5432
      - POSTGRES_USER=temporal
      - POSTGRES_PWD=temporal
      - POSTGRES_SEEDS=postgresql
      - DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development.yaml
    ports:
      - 7233:7233
    volumes:
      - ./temporal:/etc/temporal/config/dynamicconfig

  temporal-web:
    container_name: temporal-web
    image: temporalio/web:1.13.0
    depends_on:
      - temporal
    environment:
      - TEMPORAL_GRPC_ENDPOINT=temporal:7233
      - TEMPORAL_PERMIT_WRITE_API=true
    ports:
      - 8088:8088

Please make sure that a configuration file for temporal server exists. mkdir temporal && touch temporal/development.yaml

Creating workflow

You are able to create a new workflow via console command:

php app.php temporal:make-workflow MySuperWorkflow

The command will generate the following files with default namespace App\Workflow:

project/
  src/
    Workflow/
      MySuperWorkflow/
        MySuperWorkflowInterface
        MySuperWorkflow

You can redefine default namespace via app/config/temporal.php config file.

Workflow with activity classes

php app.php temporal:make-workflow MySuperWorkflow --with-activity
project/
  src/
    Workflow/
      MySuperWorkflow/
        ...
        MySuperWorkflowHandlerInterface
        MySuperWorkflowHandler

Workflow with handler classes

php app.php temporal:make-workflow MySuperWorkflow --with-handler
project/
  src/
    Workflow/
      MySuperWorkflow/
        ...
        MySuperWorkflowActivityInterface
        MySuperWorkflowActivity

You can mixin options --with-activity --with-handler

Workflow method name definition

temporal:make-workflow PingSite -m ping
#[WorkflowInterface]
interface PingSiteWorkflowInterface
{
    #[WorkflowMethod]
    public function ping(string $name): \Generator;
}

Workflow method parameters definition

temporal:make-workflow PingSite ... -p url:string -p name:string
#[WorkflowInterface]
interface PingSiteWorkflowInterface
{
    #[WorkflowMethod]
    public function ping(string $url, string $name): \Generator;
}

Workflow query methods definition

temporal:make-workflow PingSite ... -r getStatusCode -r getHeaders:array
#[WorkflowInterface]
interface PingSiteWorkflowInterface
{
    #[WorkflowMethod]
    public function ping(...): \Generator;

    #[QueryMethod]
    function getStatusCode(): string;

    #[QueryMethod]
    function getHeaders(): array;
}

Workflow with namespace definition

temporal:make-workflow Domain\\MyPackage\\MoneyTransfer ... -s withdraw -s deposit

Creating workflow from presets

The package provides the ability to create predefined Workflows. Presets for the package can be provided via third-party packages.

Example of usage

php app.php temporal:make-preset subscribtion-trial CustomerTrialSubscription 

A preset will create all necessary classes.

You can show list of available presets using the console command php app.php temporal:presets

Creating a preset

A preset class should implement Spiral\TemporalBridge\Preset\PresetInterface and should have an attribute Spiral\TemporalBridge\Preset\WorkflowPreset

use Spiral\TemporalBridge\Generator\WorkflowInterfaceGenerator;
use Spiral\TemporalBridge\Generator\SignalWorkflowGenerator;
use Spiral\TemporalBridge\Generator\ActivityInterfaceGenerator;
use Spiral\TemporalBridge\Generator\ActivityGenerator;
use Spiral\TemporalBridge\Generator\HandlerInterfaceGenerator;
use Spiral\TemporalBridge\Generator\HandlerGenerator;
use Spiral\TemporalBridge\Preset\PresetInterface;
use Spiral\TemporalBridge\Preset\WorkflowPreset;

#[WorkflowPreset('signal')]
final class SignalWorkflow implements PresetInterface
{
    public function getDescription(): ?string
    {
        return 'Workflow with signals';
    }

    public function generators(Context $context): array
    {
        $generators = [
            'WorkflowInterface' => new WorkflowInterfaceGenerator(),
            'Workflow' => new SignalWorkflowGenerator(),
        ];

        if ($context->hasActivity()) {
            $generators = \array_merge($generators, [
                'ActivityInterface' => new ActivityInterfaceGenerator(),
                'Activity' => new ActivityGenerator(),
            ]);
        }

        if ($context->hasHandler()) {
            $generators = \array_merge($generators, [
                'HandlerInterface' => new HandlerInterfaceGenerator(),
                'Handler' => new HandlerGenerator(),
            ]);
        }

        return $generators;
    }
}

Please note: If you are using WorkflowPreset you have to add a directory with presets to tokenizer.

use Spiral\Tokenizer\Bootloader\TokenizerBootloader;

class MyBootloader extends \Spiral\Boot\Bootloader\Bootloader
{
    protected const DEPENDENCIES = [
        TokenizerBootloader::class
    ];

    public function start(TokenizerBootloader $tokenizer)
    {
        $tokenizer->addDirectory(__DIR__..'/presets');
    }
}

You can omit WorkflowPreset attribute and register your preset via Bootloader

use Spiral\TemporalBridge\Preset\PresetRegistryInterface;

class MyBootloader extends \Spiral\Boot\Bootloader\Bootloader
{
    public function start(PresetRegistryInterface $registry)
    {
        $registry->register('signal', new SignalWorkflow());
    }
}

Workflow signal methods definition

temporal:make-workflow MoneyTransfer ... -s withdraw -s deposit
#[WorkflowInterface]
interface MoneyTransferWorkflowInterface
{
    #[WorkflowMethod]
    public function ping(...): \Generator;

    #[SignalMethod]
    function withdraw(): void;

    #[SignalMethod]
    function deposit(): void;
}

You may discover available workflow samples here

Usage

Configure temporal address via env variables .env

TEMPORAL_ADDRESS=127.0.0.1:7233

Running workflow

class PingController 
{
    public function ping(StoreRequest $request, PingSiteHandler $handler): void
    {
        $this->hanlder->handle(
            $request->url, 
            $request->name
        );
    }
}

Running workers with different task queue

RoadRunner doesn't support running several task queues out of the box, but you may run several RoadRunner instances with passing task queue name through the env variable TEMPORAL_TASK_QUEUE

Example

.rr.temporal.yaml config

version: '2.7'

rpc:
  listen: tcp://127.0.0.1:6001

server:
  command: "php app.php"
  relay: pipes

temporal:
  address: localhost:7233
  activities:
    num_workers: 10

Running RoadRunenr instance

TEMPORAL_TASK_QUEUE=orders ./rr serve -c ./.rr.temporal.yaml

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.

Edit this page