gdx/p-service-bus-laravel-package

PServiceBus

Installs: 2 325

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Forks: 0

Type:laravel-package

2.0.0 2024-09-30 19:12 UTC

This package is auto-updated.

Last update: 2024-10-30 17:22:30 UTC


README

Laravel integration for library https://gitlab.com/GDXbsv/pservicebus

Packagist: https://packagist.org/packages/gdx/p-service-bus-laravel-package

Installation

composer require gdx/p-service-bus-laravel-package

Configuration

Add your transports in configuration (They are just examples you can create as many transports as you want with any names. The example has 2 transports: SNS for exteranl communications and SQS for internal)

    'transports' => [
        'external' => SnsSqsTransport::class,
        'main' => in_array(env('APP_ENV'), ['production', 'staging',]) ? 'app.service_bus.transport.main' : InMemoryTransport::class,
    ],

Define those transports in your application:

<?php declare(strict_types=1);

namespace App\Providers;

use GDXbsv\PServiceBus\Transport\Sns\SnsSqsTransport;
use GDXbsv\PServiceBus\Transport\Sqs\SqsTransport;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Console\ClosureCommand;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\ServiceProvider;

class PServiceBusProvider extends ServiceProvider
{
    public function register()
    {
        $snsDsn = env('SNS_DSN', 'sns+http://key:secret@aws/000000000000?region=eu-central-1&topic=service_bus');
        $sqsDsn = env('SQS_DSN', 'sqs+http://key:secret@aws/000000000000?region=eu-central-1');
        $this->app->singleton(SnsSqsTransport::class,
            fn(Application $app) => SnsSqsTransport::ofDsn(
                $snsDsn,
                SqsTransport::ofDsn($sqsDsn . '&retries=3&queue=editing_ext'),
                $app->make('p-service-bus.build.storage')->messageNameMapIn,
            )
        );
        $this->app->singleton('app.service_bus.transport.main', fn() => SqsTransport::ofDsn($sqsDsn . '&retries=3&queue=editing_main'));
    }
}

Saga Eloquent

create saga:

The main difference you have to extend GDXbsv\PServiceBusLaravel\Saga\SagaEloquent and implement getEloquentModelClass

<?php declare(strict_types=1);

namespace App\Saga;

use Doctrine\ORM\Mapping as ORM;
use GDXbsv\PServiceBus\Bus\Handling\Handle;
use GDXbsv\PServiceBus\Id;
use GDXbsv\PServiceBus\Message\TimeSpan;
use GDXbsv\PServiceBus\Saga\MessageSagaContext;
use GDXbsv\PServiceBus\Saga\SagaContext;
use GDXbsv\PServiceBus\Saga\SagaCreateMapper;
use GDXbsv\PServiceBus\Saga\SagaPropertyMapper;
use GDXbsv\PServiceBusLaravel\Saga\SagaEloquent;


/**
 * @final
 */
final class TestSaga extends SagaEloquent
{
    private Id $id;
    public string $string;
    public ?string $value = null;


    public static function getEloquentModelClass(): string
    {
        return TestSagaModel::class;
    }

    /**
     * @param Id<static> $id
     */
    private function __construct(Id $id, string $string)
    {
        $this->id = $id;
        $this->string = $string;
    }

    public static function configureHowToCreateSaga(SagaCreateMapper $mapper): void
    {
        $mapper
            ->toMessage(
                // do not forget to create handling function in a case if saga exists and to let saga know that we wait this message
                function (TestSagaCreateCommand $command, MessageSagaContext $context) {
                    return new self(new Id($command->id), $command->string);
                }
            );
    }

    public static function configureHowToFindSaga(SagaPropertyMapper $mapper): void
    {
        $mapper
            ->mapSaga(new \ReflectionProperty(TestSaga::class, 'id'))
            ->toMessage(
                function (TestSagaCommand $command, MessageSagaContext $context) {
                    return new Id($command->id);
                }
            );
    }

    /** We have to tell saga we wait this message */
    #[Handle('main', 3)]
    public function testSagaCreateCommand(TestSagaCreateCommand $command, SagaContext $context)
    {
        $this->string = $command->string;
        $context->publish(new TestsSagaOutputEvent('testHandlerFunction'));
    }
}

And create provided EloquentModel:

<?php declare(strict_types=1);

namespace App\Saga;

use Illuminate\Database\Eloquent\Model;

class TestSagaModel extends Model
{
    protected $table = 'saga';
    protected $primaryKey = 'id';
    public $incrementing = false;
    protected $guarded = [];
}

After this use it as usual.

Commands for laravel

p-service-bus:cache:clear clean cache and search attributes again. Needed only for debug=false modes.

p-service-bus:saga:eloquent:outbox:recover-messages run it send messages from outbox if something goes wrong. Do it periodically.

p-service-bus:saga:eloquent:only-once:clean {days=30} cleanup old messages form only once control. Do it once a day.