Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename Attributes for Projector #452

Merged
merged 2 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/pages/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,15 @@ Each projector is then responsible for a specific projection and version.

```php
use Doctrine\DBAL\Connection;
use Patchlevel\EventSourcing\Attribute\Create;
use Patchlevel\EventSourcing\Attribute\Drop;
use Patchlevel\EventSourcing\Attribute\Setup;
use Patchlevel\EventSourcing\Attribute\Teardown;
use Patchlevel\EventSourcing\Attribute\Subscribe;
use Patchlevel\EventSourcing\Attribute\Projection;
use Patchlevel\EventSourcing\Attribute\Projector;
use Patchlevel\EventSourcing\EventBus\Message;
use Patchlevel\EventSourcing\Projection\Projection\ProjectionId;
use Patchlevel\EventSourcing\Projection\Projector\ProjectorUtil;

#[Projection('hotel')]
#[Projector('hotel')]
final class HotelProjector
{
use ProjectorUtil;
Expand Down Expand Up @@ -215,13 +215,13 @@ final class HotelProjector
);
}

#[Create]
#[Setup]
public function create(): void
{
$this->db->executeStatement("CREATE TABLE IF NOT EXISTS ${this->table()} (id VARCHAR PRIMARY KEY, name VARCHAR, guests INTEGER);");
}

#[Drop]
#[Teardown]
public function drop(): void
{
$this->db->executeStatement("DROP TABLE IF EXISTS ${this->table()};");
Expand Down
34 changes: 17 additions & 17 deletions docs/pages/projection.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ In this example we always create a new data set in a relational database when a

```php
use Doctrine\DBAL\Connection;
use Patchlevel\EventSourcing\Attribute\Create;
use Patchlevel\EventSourcing\Attribute\Drop;
use Patchlevel\EventSourcing\Attribute\Setup;
use Patchlevel\EventSourcing\Attribute\Teardown;
use Patchlevel\EventSourcing\Attribute\Subscribe;
use Patchlevel\EventSourcing\Attribute\Projection;
use Patchlevel\EventSourcing\Attribute\Projector;
use Patchlevel\EventSourcing\EventBus\Message;
use Patchlevel\EventSourcing\Projection\Projector\ProjectorUtil;

#[Projection('profile')]
#[Projector('profile')]
final class ProfileProjector
{
use ProjectorUtil;
Expand All @@ -40,15 +40,15 @@ final class ProfileProjector
return $this->connection->fetchAllAssociative("SELECT id, name FROM ${this->table()};");
}

#[Create]
#[Setup]
public function create(): void
{
$this->connection->executeStatement(
"CREATE TABLE IF NOT EXISTS ${this->table()} (id VARCHAR PRIMARY KEY, name VARCHAR NOT NULL);"
);
}

#[Drop]
#[Teardown]
public function drop(): void
{
$this->connection->executeStatement("DROP TABLE IF EXISTS ${this->table()};");
Expand Down Expand Up @@ -81,14 +81,14 @@ final class ProfileProjector

Each projector is responsible for a specific projection and version.
This combination of information results in the so-called `project ID`.
In order for us to be able to define this, we have to use the `Projection` attribute.
In order for us to be able to define this, we have to use the `Projector` attribute.
In our example, the projection is called "profile" and has the version "0" because we did not specify it.
So that there is no problems with existing projection,
both the name of the projection and the version should be part of the table/collection name.
In our example, we build a `table` helper method, what creates the following string: "projection_profile_0".

Projectors can have one `create` and `drop` method that is executed when the projection is created or deleted.
For this there are the attributes `Create` and `Drop`. The method name itself doesn't matter.
Projectors can have one `setup` and `teardown` method that is executed when the projection is created or deleted.
For this there are the attributes `Setup` and `Teardown`. The method name itself doesn't matter.
In some cases it may be that no schema has to be created for the projection,
as the target does it automatically, so you can skip this.

Expand All @@ -114,17 +114,17 @@ Several projectors can also listen to the same event.

As soon as the structure of a projection changes, the version must be change or increment.
Otherwise the projectionist will not recognize that the projection has changed and will not rebuild it.
To do this, you have to change the version in the `Projection` attribute.
To do this, you have to change the version in the `Projector` attribute.

```php
use Doctrine\DBAL\Connection;
use Patchlevel\EventSourcing\Attribute\Create;
use Patchlevel\EventSourcing\Attribute\Drop;
use Patchlevel\EventSourcing\Attribute\Setup;
use Patchlevel\EventSourcing\Attribute\Teardown;
use Patchlevel\EventSourcing\Attribute\Handle;
use Patchlevel\EventSourcing\Attribute\Projection;
use Patchlevel\EventSourcing\Attribute\Projector;
use Patchlevel\EventSourcing\EventBus\Message;

#[Projection('profile', version: 1)]
#[Projector('profile', version: 1)]
final class ProfileProjector
{
// ...
Expand Down Expand Up @@ -169,12 +169,12 @@ If something breaks, the projectionist marks the individual projections as fault
## Projection Id

A projection id consists of a unique name and a version.
It can be defined using the `Projection` attribute.
It can be defined using the `Projector` attribute.

```php
use Patchlevel\EventSourcing\Attribute\Projection;
use Patchlevel\EventSourcing\Attribute\Projector;

#[Projection('profile', version: 1)]
#[Projector('profile', version: 1)]
final class ProfileProjector
{
// ...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
use Attribute;

#[Attribute(Attribute::TARGET_CLASS)]
final class Projection
final class Projector
{
public function __construct(
private string $name,
private int $version = 0,

Check warning on line 14 in src/Attribute/Projector.php

View workflow job for this annotation

GitHub Actions / Mutation tests (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "DecrementInteger": --- Original +++ New @@ @@ #[Attribute(Attribute::TARGET_CLASS)] final class Projector { - public function __construct(private string $name, private int $version = 0) + public function __construct(private string $name, private int $version = -1) { } public function name() : string

Check warning on line 14 in src/Attribute/Projector.php

View workflow job for this annotation

GitHub Actions / Mutation tests (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "IncrementInteger": --- Original +++ New @@ @@ #[Attribute(Attribute::TARGET_CLASS)] final class Projector { - public function __construct(private string $name, private int $version = 0) + public function __construct(private string $name, private int $version = 1) { } public function name() : string
) {
}

Expand Down
2 changes: 1 addition & 1 deletion src/Attribute/Drop.php → src/Attribute/Setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
use Attribute;

#[Attribute(Attribute::TARGET_METHOD)]
final class Drop
final class Setup
{
}
2 changes: 1 addition & 1 deletion src/Attribute/Create.php → src/Attribute/Teardown.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
use Attribute;

#[Attribute(Attribute::TARGET_METHOD)]
final class Create
final class Teardown
{
}
16 changes: 8 additions & 8 deletions src/Metadata/Projector/AttributeProjectorMetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

namespace Patchlevel\EventSourcing\Metadata\Projector;

use Patchlevel\EventSourcing\Attribute\Create;
use Patchlevel\EventSourcing\Attribute\Drop;
use Patchlevel\EventSourcing\Attribute\Projection;
use Patchlevel\EventSourcing\Attribute\Projector;
use Patchlevel\EventSourcing\Attribute\Setup;
use Patchlevel\EventSourcing\Attribute\Subscribe;
use Patchlevel\EventSourcing\Attribute\Teardown;
use ReflectionClass;

use function array_key_exists;
Expand All @@ -26,7 +26,7 @@ public function metadata(string $projector): ProjectorMetadata

$reflector = new ReflectionClass($projector);

$attributes = $reflector->getAttributes(Projection::class);
$attributes = $reflector->getAttributes(Projector::class);

if ($attributes === []) {
throw new ClassIsNotAProjector($projector);
Expand Down Expand Up @@ -59,9 +59,9 @@ public function metadata(string $projector): ProjectorMetadata
$subscribeMethods[$eventClass] = $method->getName();
}

if ($method->getAttributes(Create::class)) {
if ($method->getAttributes(Setup::class)) {
if ($createMethod) {
throw new DuplicateCreateMethod(
throw new DuplicateSetupMethod(
$projector,
$createMethod,
$method->getName(),
Expand All @@ -71,12 +71,12 @@ public function metadata(string $projector): ProjectorMetadata
$createMethod = $method->getName();
}

if (!$method->getAttributes(Drop::class)) {
if (!$method->getAttributes(Teardown::class)) {
continue;
}

if ($dropMethod) {
throw new DuplicateDropMethod(
throw new DuplicateTeardownMethod(
$projector,
$dropMethod,
$method->getName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

use function sprintf;

final class DuplicateDropMethod extends MetadataException
final class DuplicateSetupMethod extends MetadataException
{
/** @param class-string $projector */
public function __construct(string $projector, string $fistMethod, string $secondMethod)
{
parent::__construct(
sprintf(
'Two methods "%s" and "%s" on the projector "%s" have been marked as "create" methods. Only one method can be defined like this.',
'Two methods "%s" and "%s" on the projector "%s" have been marked as "setup" methods. Only one method can be defined like this.',
$fistMethod,
$secondMethod,
$projector,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

use function sprintf;

final class DuplicateCreateMethod extends MetadataException
final class DuplicateTeardownMethod extends MetadataException
{
/** @param class-string $projector */
public function __construct(string $projector, string $fistMethod, string $secondMethod)
{
parent::__construct(
sprintf(
'Two methods "%s" and "%s" on the projector "%s" have been marked as "create" methods. Only one method can be defined like this.',
'Two methods "%s" and "%s" on the projector "%s" have been marked as "teardown" methods. Only one method can be defined like this.',
$fistMethod,
$secondMethod,
$projector,
Expand Down
4 changes: 2 additions & 2 deletions src/Metadata/Projector/ProjectorMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public function __construct(
public readonly int $version,
/** @var array<class-string, string> */
public readonly array $subscribeMethods = [],
public readonly string|null $createMethod = null,
public readonly string|null $dropMethod = null,
public readonly string|null $setupMethod = null,
public readonly string|null $teardownMethod = null,
) {
}
}
22 changes: 11 additions & 11 deletions src/Projection/Projectionist/DefaultProjectionist.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ public function boot(
$projection->id()->toString(),
));

$createMethod = $this->projectorResolver->resolveCreateMethod($projector);
$setupMethod = $this->projectorResolver->resolveSetupMethod($projector);

if (!$createMethod) {
if (!$setupMethod) {
$this->logger?->info(sprintf(
'projector "%s" for "%s" has no create method',
'projector "%s" for "%s" has no "setup" method',
$projector::class,
$projection->id()->toString(),
));
Expand All @@ -76,7 +76,7 @@ public function boot(
}

try {
$createMethod();
$setupMethod();
$this->logger?->info(sprintf(
'projector "%s" for "%s" prepared',
$projector::class,
Expand Down Expand Up @@ -242,11 +242,11 @@ public function teardown(ProjectionCriteria $criteria = new ProjectionCriteria()
continue;
}

$dropMethod = $this->projectorResolver->resolveDropMethod($projector);
$teardownMethod = $this->projectorResolver->resolveTeardownMethod($projector);

if ($dropMethod) {
if ($teardownMethod) {
try {
$dropMethod();
$teardownMethod();
} catch (Throwable $e) {
$this->logger?->error(
sprintf('projection for "%s" could not be removed, skipped', $projection->id()->toString()),
Expand Down Expand Up @@ -281,9 +281,9 @@ public function remove(ProjectionCriteria $criteria = new ProjectionCriteria()):
continue;
}

$dropMethod = $this->projectorResolver->resolveDropMethod($projector);
$teardownMethod = $this->projectorResolver->resolveTeardownMethod($projector);

if (!$dropMethod) {
if (!$teardownMethod) {
$this->projectionStore->remove($projection->id());

$this->logger?->info(
Expand All @@ -294,11 +294,11 @@ public function remove(ProjectionCriteria $criteria = new ProjectionCriteria()):
}

try {
$dropMethod();
$teardownMethod();
} catch (Throwable $e) {
$this->logger?->error(
sprintf(
'projector "%s" drop method could not be executed:',
'projector "%s" teardown method could not be executed:',
$projector::class,
),
);
Expand Down
8 changes: 4 additions & 4 deletions src/Projection/Projector/MetadataProjectorResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@

use function array_key_exists;

final class MetadataProjectorResolver implements ProjectorResolver

Check failure on line 15 in src/Projection/Projector/MetadataProjectorResolver.php

View workflow job for this annotation

GitHub Actions / Backward Compatibility Check (locked, 8.2, ubuntu-latest)

Method Patchlevel\EventSourcing\Projection\Projector\MetadataProjectorResolver#resolveCreateMethod() was removed
{
public function __construct(
private readonly ProjectorMetadataFactory $metadataFactory = new AttributeProjectorMetadataFactory(),
) {
}

public function resolveCreateMethod(object $projector): Closure|null
public function resolveSetupMethod(object $projector): Closure|null
{
$metadata = $this->metadataFactory->metadata($projector::class);
$method = $metadata->createMethod;
$method = $metadata->setupMethod;

if (!$method) {
return null;
Expand All @@ -31,10 +31,10 @@
return $projector->$method(...);
}

public function resolveDropMethod(object $projector): Closure|null
public function resolveTeardownMethod(object $projector): Closure|null
{
$metadata = $this->metadataFactory->metadata($projector::class);
$method = $metadata->dropMethod;
$method = $metadata->teardownMethod;

if (!$method) {
return null;
Expand Down
4 changes: 2 additions & 2 deletions src/Projection/Projector/ProjectorResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

interface ProjectorResolver
{
public function resolveCreateMethod(object $projector): Closure|null;
public function resolveSetupMethod(object $projector): Closure|null;

public function resolveDropMethod(object $projector): Closure|null;
public function resolveTeardownMethod(object $projector): Closure|null;

public function resolveSubscribeMethod(object $projector, Message $message): Closure|null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,30 @@
namespace Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Projection;

use Doctrine\DBAL\Connection;
use Patchlevel\EventSourcing\Attribute\Create;
use Patchlevel\EventSourcing\Attribute\Drop;
use Patchlevel\EventSourcing\Attribute\Projection;
use Patchlevel\EventSourcing\Attribute\Projector;
use Patchlevel\EventSourcing\Attribute\Setup;
use Patchlevel\EventSourcing\Attribute\Subscribe;
use Patchlevel\EventSourcing\Attribute\Teardown;
use Patchlevel\EventSourcing\EventBus\Message;
use Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation\Events\ProfileCreated;

use function assert;

#[Projection('dummy', 1)]
#[Projector('dummy', 1)]
final class ProfileProjector
{
public function __construct(
private Connection $connection,
) {
}

#[Create]
#[Setup]
public function create(): void
{
$this->connection->executeStatement('CREATE TABLE IF NOT EXISTS projection_profile (id VARCHAR PRIMARY KEY, name VARCHAR);');
}

#[Drop]
#[Teardown]
public function drop(): void
{
$this->connection->executeStatement('DROP TABLE IF EXISTS projection_profile;');
Expand Down
Loading
Loading