gdx / p-service-bus-laravel-package
PServiceBus
Requires
- php: >=8
- friendsofphp/proxy-manager-lts: ^1.0
- gdx/p-service-bus: ^2.0.0
- haydenpierce/class-finder: ^0.5.3
- illuminate/support: ^9.0|^10.13|^v11.25.0
- ocramius/generated-hydrator: ^4.5
Requires (Dev)
- doctrine/doctrine-bundle: ^2.4
- doctrine/orm: ^2.10
- laravel/framework: ^9.0|^10.0|^v11.25.0
- phpunit/phpunit: ^10.2
- roave/security-advisories: dev-latest
- vimeo/psalm: ^5.12.0
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.