Skip to content

Commit

Permalink
Split event message from builder (#34)
Browse files Browse the repository at this point in the history
Split event message from builder
  • Loading branch information
Serginyu authored Oct 5, 2023
1 parent 04d08f4 commit fdb3ca4
Show file tree
Hide file tree
Showing 25 changed files with 219 additions and 209 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ debug:

.PHONY: update-dependencies
update-dependencies:
docker-compose run composer update
docker-compose run composer update --ignore-platform-req=ext-sockets

.PHONY: checkstyle
checkstyle:
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,14 @@ class EventServiceProvider extends ServiceProvider

### Custom middlewares

The middlewares should implement the `Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract` interface.
The middlewares should implement the `Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface` interface.
Its purpose is to store the domain event provided, so you can implement any storage for domain events.

### Custom messages

The `transactional-event.message` class must implement `EventMessageContract` and `transactional-event.middleware` class must implement `EventStoreMiddlewareContract`.
The `transactional-event.messageBuilder` class must implement `EventMessageBuilderInterface` and `transactional-event.middleware` class must implement `EventStoreMiddlewareInterface`.

The builder should return a `EventMessageInterface` value object. It just needs to implement the `toArray` and `jsonSerialize` methods with all the attributes that you need.

Considerations
==============
Expand Down
7 changes: 4 additions & 3 deletions config/transactional-event-publisher.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?php

use Softonic\TransactionalEventPublisher\Builders\EventMessageBuilder;
use Softonic\TransactionalEventPublisher\ValueObjects\EventMessage;
use Softonic\TransactionalEventPublisher\EventStoreMiddlewares\AmqpMiddleware;
use Softonic\TransactionalEventPublisher\EventStoreMiddlewares\DatabaseMiddleware;
use Softonic\TransactionalEventPublisher\ValueObjects\EventMessage;

return [
/*
Expand All @@ -28,10 +29,10 @@

/*
|--------------------------------------------------------------------------
| Event Message class.
| Event Message Builder class.
|--------------------------------------------------------------------------
*/
'message' => EventMessage::class,
'messageBuilder' => EventMessageBuilder::class,

/*
|--------------------------------------------------------------------------
Expand Down
5 changes: 1 addition & 4 deletions database/factories/DomainEventFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Factories\Factory;
use Softonic\TransactionalEventPublisher\CustomEventMessage;
use Softonic\TransactionalEventPublisher\Models\DomainEvent;
use Softonic\TransactionalEventPublisher\TestModel;

class DomainEventFactory extends Factory
{
Expand All @@ -18,13 +17,11 @@ class DomainEventFactory extends Factory

/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'message' => new CustomEventMessage(new TestModel(), 'testEvent')
'message' => new CustomEventMessage()
];
}
}
27 changes: 27 additions & 0 deletions src/Builders/EventMessageBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Softonic\TransactionalEventPublisher\Builders;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Softonic\TransactionalEventPublisher\Interfaces\EventMessageBuilderInterface;
use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface;
use Softonic\TransactionalEventPublisher\ValueObjects\EventMessage;

class EventMessageBuilder implements EventMessageBuilderInterface
{

public function build(Model $model, string $eventType): EventMessageInterface
{
$modelName = class_basename($model);

return new EventMessage(
service: config('transactional-event-publisher.service'),
eventType: $eventType,
modelName: $modelName,
eventName: $modelName . ucfirst($eventType),
payload: $model->toArray(),
createdAt: Carbon::now()->toDateTimeString(),
);
}
}
6 changes: 3 additions & 3 deletions src/Console/Commands/EmitEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use Illuminate\Support\LazyCollection;
use InvalidArgumentException;
use RuntimeException;
use Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract;
use Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface;
use Softonic\TransactionalEventPublisher\Models\DomainEvent;

class EmitEvents extends Command
Expand All @@ -38,7 +38,7 @@ class EmitEvents extends Command

protected $description = 'Continuously emits domain events in batches';

public EventStoreMiddlewareContract $eventPublisherMiddleware;
public EventStoreMiddlewareInterface $eventPublisherMiddleware;

public string $dbConnection;

Expand All @@ -52,7 +52,7 @@ class EmitEvents extends Command

private bool $eventsProcessed;

public function handle(EventStoreMiddlewareContract $eventPublisherMiddleware): void
public function handle(EventStoreMiddlewareInterface $eventPublisherMiddleware): void
{
$this->eventPublisherMiddleware = $eventPublisherMiddleware;

Expand Down
16 changes: 0 additions & 16 deletions src/Contracts/EventMessageContract.php

This file was deleted.

11 changes: 0 additions & 11 deletions src/Contracts/EventStoreMiddlewareContract.php

This file was deleted.

10 changes: 5 additions & 5 deletions src/EventStoreMiddlewares/AmqpMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
use Exception;
use Illuminate\Support\Facades\Log;
use Softonic\Amqp\Amqp;
use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract;
use Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract;
use Softonic\TransactionalEventPublisher\Factories\AmqpMessageFactory;
use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface;
use Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface;

class AmqpMiddleware implements EventStoreMiddlewareContract
class AmqpMiddleware implements EventStoreMiddlewareInterface
{
public function __construct(
private readonly AmqpMessageFactory $messageFactory,
Expand All @@ -21,7 +21,7 @@ public function __construct(
/**
* Publishes the messages to the AMQP Message broker.
*/
public function store(EventMessageContract ...$messages): bool
public function store(EventMessageInterface ...$messages): bool
{
try {
if (count($messages) === 1) {
Expand Down Expand Up @@ -55,7 +55,7 @@ public function store(EventMessageContract ...$messages): bool
* Returns the message routing key based in the configured parameters
* or a default value based in service, eventType and modelName.
*/
private function getRoutingKey(EventMessageContract $message): string
private function getRoutingKey(EventMessageInterface $message): string
{
$routingKey = $message->service . '.' . $message->eventType . '.' . $message->modelName;
if (isset($this->properties['routing_key_fields'])) {
Expand Down
8 changes: 4 additions & 4 deletions src/EventStoreMiddlewares/DatabaseMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

use Exception;
use Illuminate\Support\Facades\DB;
use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract;
use Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract;
use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface;
use Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface;
use Softonic\TransactionalEventPublisher\Models\DomainEvent;

class DatabaseMiddleware implements EventStoreMiddlewareContract
class DatabaseMiddleware implements EventStoreMiddlewareInterface
{
/**
* Stores the messages in database.
*/
public function store(EventMessageContract ...$messages): bool
public function store(EventMessageInterface ...$messages): bool
{
try {
$inserts = [];
Expand Down
4 changes: 2 additions & 2 deletions src/Factories/AmqpMessageFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

use LogicException;
use PhpAmqpLib\Message\AMQPMessage;
use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract;
use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface;

class AmqpMessageFactory
{
/**
* Makes a AMQPMessage object.
*/
public function make(EventMessageContract $eventMessage, array $properties = []): AMQPMessage
public function make(EventMessageInterface $eventMessage, array $properties = []): AMQPMessage
{
$this->checkMessage($eventMessage->toArray());

Expand Down
10 changes: 10 additions & 0 deletions src/Interfaces/EventMessageBuilderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Softonic\TransactionalEventPublisher\Interfaces;

use Illuminate\Database\Eloquent\Model;

interface EventMessageBuilderInterface
{
public function build(Model $model, string $eventType): EventMessageInterface;
}
13 changes: 13 additions & 0 deletions src/Interfaces/EventMessageInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Softonic\TransactionalEventPublisher\Interfaces;

use JsonSerializable;

interface EventMessageInterface extends JsonSerializable
{
/**
* Returns the message in an array format.
*/
public function toArray(): array;
}
11 changes: 11 additions & 0 deletions src/Interfaces/EventStoreMiddlewareInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Softonic\TransactionalEventPublisher\Interfaces;

interface EventStoreMiddlewareInterface
{
/**
* Stores in the message-oriented middleware.
*/
public function store(EventMessageInterface ...$messages): bool;
}
4 changes: 2 additions & 2 deletions src/Models/DomainEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract;
use Softonic\TransactionalEventPublisher\Database\Factories\DomainEventFactory;
use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface;

class DomainEvent extends Model
{
Expand All @@ -26,7 +26,7 @@ class DomainEvent extends Model
*/
public $timestamps = false;

public function setMessageAttribute(EventMessageContract $message)
public function setMessageAttribute(EventMessageInterface $message)
{
$this->attributes['message'] = serialize(clone $message);
}
Expand Down
16 changes: 10 additions & 6 deletions src/Observers/ModelObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@
namespace Softonic\TransactionalEventPublisher\Observers;

use Illuminate\Database\Eloquent\Model;
use Softonic\TransactionalEventPublisher\Contracts\EventStoreMiddlewareContract;
use Softonic\TransactionalEventPublisher\Exceptions\EventStoreFailedException;
use Softonic\TransactionalEventPublisher\Interfaces\EventMessageBuilderInterface;
use Softonic\TransactionalEventPublisher\Interfaces\EventStoreMiddlewareInterface;

class ModelObserver
{
private $eventStoreMiddleware;
/**
* @var EventStoreMiddlewareInterface[]
*/
private array $eventStoreMiddleware;

/**
* @param EventStoreMiddlewareContract | EventStoreMiddlewareContract[] $eventStoreMiddleware
* @param EventStoreMiddlewareInterface | EventStoreMiddlewareInterface[] $eventStoreMiddleware
*/
public function __construct(
$eventStoreMiddleware,
private readonly string $messageClass
array|EventStoreMiddlewareInterface $eventStoreMiddleware,
protected readonly EventMessageBuilderInterface $builder
) {
$this->eventStoreMiddleware = is_array($eventStoreMiddleware) ? $eventStoreMiddleware : [$eventStoreMiddleware];
}
Expand Down Expand Up @@ -77,7 +81,7 @@ public function deleted(Model $model): bool
private function performStoreEventMessage(Model $model, $modelEvent): void
{
$connection = $model->getConnection();
$message = new $this->messageClass($model, $modelEvent);
$message = $this->builder->build($model, $modelEvent);

if (true === $this->executeMiddlewares($message)) {
$connection->commit();
Expand Down
2 changes: 1 addition & 1 deletion src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function register()

return new ModelObserver(
$middlewares,
config('transactional-event-publisher.message')
new (config('transactional-event-publisher.messageBuilder'))
);
});

Expand Down
49 changes: 14 additions & 35 deletions src/ValueObjects/EventMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,33 @@

namespace Softonic\TransactionalEventPublisher\ValueObjects;

use Illuminate\Database\Eloquent\Model;
use Softonic\TransactionalEventPublisher\Contracts\EventMessageContract;
use Softonic\TransactionalEventPublisher\Interfaces\EventMessageInterface;

class EventMessage implements EventMessageContract
class EventMessage implements EventMessageInterface
{
public $service;

public $eventType;

public $modelName;

public $eventName;

public $createdAt;

public $payload;

public function __construct(Model $model, $eventType)
{
$this->service = config('transactional-event-publisher.service');
$this->eventType = $eventType;
$this->modelName = class_basename($model);
$this->eventName = $this->buildEventName($this->modelName, $eventType);
$this->payload = $model->toArray();
$this->createdAt = date('Y-m-d H:i:s');
public function __construct(
public readonly string $service,
public readonly string $eventType,
public readonly string $modelName,
public readonly string $eventName,
public readonly array $payload,
public readonly string $createdAt,
) {
}

public function toArray(): array
{
return [
'service' => $this->service,
'eventType' => $this->eventType,
'modelName' => $this->modelName,
'eventName' => $this->eventName,
'createdAt' => $this->createdAt,
'payload' => $this->payload,
'createdAt' => $this->createdAt,
];
}

private function buildEventName($modelName, $event)
{
return $modelName . ucfirst($event);
}

public function __toString(): string
{
return serialize($this->toArray());
}

public function jsonSerialize()
public function jsonSerialize(): array
{
return $this->toArray();
}
Expand Down
Loading

0 comments on commit fdb3ca4

Please sign in to comment.