Skip to content

Commit

Permalink
Merge pull request #497 from patchlevel/remove-explicit-projector-ver…
Browse files Browse the repository at this point in the history
…sion

remove the explicit defined version
  • Loading branch information
DavidBadura authored Feb 17, 2024
2 parents a8a901a + 13a268c commit a469f0d
Show file tree
Hide file tree
Showing 45 changed files with 219 additions and 636 deletions.
6 changes: 1 addition & 5 deletions docs/pages/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,7 @@ final class HotelProjector

private function table(): string
{
return sprintf(
'projection_%s_%s',
$this->projectionName(),
$this->projectionVersion()
);
return 'projection_' . $this->projectorId();
}
}
```
Expand Down
40 changes: 20 additions & 20 deletions docs/pages/projection.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use Patchlevel\EventSourcing\Attribute\Projector;
use Patchlevel\EventSourcing\EventBus\Message;
use Patchlevel\EventSourcing\Projection\Projector\ProjectorUtil;

#[Projector('profile')]
#[Projector('profile_1')]
final class ProfileProjector
{
use ProjectorUtil;
Expand Down Expand Up @@ -70,22 +70,21 @@ final class ProfileProjector

private function table(): string
{
return sprintf(
'projection_%s_%s',
$this->projectionName(),
$this->projectionVersion()
);
return 'projection_' . $this->projectionId();
}
}
```

Each projector is responsible for a specific projection and version.
This combination of information results in the so-called `project ID`.
!!! tip

Add a version as suffix to the `projectorId`, so you can increment it when the projection changes.

Each projector has an unique ID and is responsible for a specific projection.
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.
In our example, the projection is called "profile".
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".
the name of the projection should be part of the table/collection name.
In our example, we build a `table` helper method, what creates the following string: "projection_profile".

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.
Expand All @@ -112,9 +111,11 @@ Several projectors can also listen to the same event.

## Versioning

As soon as the structure of a projection changes, the version must be change or increment.
As soon as the structure of a projection changes or the or you need other events from the past,
the `projectorId` 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 `Projector` attribute.
To do this, you can add a version to the `projectorId`:

```php
use Doctrine\DBAL\Connection;
Expand All @@ -124,7 +125,7 @@ use Patchlevel\EventSourcing\Attribute\Handle;
use Patchlevel\EventSourcing\Attribute\Projector;
use Patchlevel\EventSourcing\EventBus\Message;

#[Projector('profile', version: 1)]
#[Projector('profile_1')]
final class ProfileProjector
{
// ...
Expand All @@ -133,7 +134,7 @@ final class ProfileProjector

!!! warning

If you change the version, you must also change the table/collection name.
If you change the ID, you must also change the table/collection name.

!!! tip

Expand Down Expand Up @@ -168,20 +169,19 @@ 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 `Projector` attribute.
A projection id is unique and can be defined using the `Projector` attribute.

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

#[Projector('profile', version: 1)]
#[Projector('profile_1')]
final class ProfileProjector
{
// ...
}
```

As soon as the projection changes, such as the structure or the data, the version of the projection must be incremented.
As soon as the projection changes, such as the structure or the data, the id of the projection must be changed.
This tells the projectionist to build an another projection with this projector.

!!! note
Expand Down Expand Up @@ -217,7 +217,7 @@ stateDiagram-v2
### New

A projection gets the status new if there is a projector with an unknown `projection id`.
This can happen when either a new projector has been added, the version has changed
This can happen when either a new projector has been added, the `projector id` has changed
or the projection has been manually deleted from the projection store.

### Booting
Expand Down
3 changes: 1 addition & 2 deletions src/Attribute/Projector.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
final class Projector
{
public function __construct(
public readonly string $name,
public readonly int $version = 0,
public readonly string $id,
) {
}
}
7 changes: 3 additions & 4 deletions src/Console/Command/ProjectionCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Patchlevel\EventSourcing\Console\InvalidArgumentGiven;
use Patchlevel\EventSourcing\Projection\Projection\ProjectionCriteria;
use Patchlevel\EventSourcing\Projection\Projection\ProjectionId;
use Patchlevel\EventSourcing\Projection\Projectionist\Projectionist;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -44,7 +43,7 @@ protected function projectionCriteria(InputInterface $input): ProjectionCriteria
);
}

/** @return list<ProjectionId>|null */
/** @return list<string>|null */
private function projectionIds(InputInterface $input): array|null
{
$ids = $input->getOption('id');
Expand All @@ -59,12 +58,12 @@ private function projectionIds(InputInterface $input): array|null

return array_values(
array_map(
static function (mixed $id) use ($ids): ProjectionId {
static function (mixed $id) use ($ids): string {
if (!is_string($id)) {
throw new InvalidArgumentGiven($ids, 'list<string>');
}

return ProjectionId::fromString($id);
return $id;
},
$ids,
),
Expand Down
15 changes: 3 additions & 12 deletions src/Console/Command/ProjectionStatusCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Patchlevel\EventSourcing\Console\InputHelper;
use Patchlevel\EventSourcing\Console\OutputStyle;
use Patchlevel\EventSourcing\Projection\Projection\Projection;
use Patchlevel\EventSourcing\Projection\Projection\ProjectionId;
use Patchlevel\EventSourcing\Projection\Projection\Store\ErrorContext;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
Expand Down Expand Up @@ -47,17 +46,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$io->table(
[
'id',
'name',
'version',
'position',
'status',
'error message',
],
array_map(
static fn (Projection $projection) => [
$projection->id()->toString(),
$projection->id()->name(),
$projection->id()->version(),
$projection->id(),
$projection->position(),
$projection->status()->value,
$projection->projectionError()?->errorMessage,
Expand All @@ -69,22 +64,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return 0;
}

$projection = $projections->get(ProjectionId::fromString($id));
$projection = $projections->get($id);

$io->horizontalTable(
[
'id',
'name',
'version',
'position',
'status',
'error message',
],
[
[
$projection->id()->toString(),
$projection->id()->name(),
$projection->id()->version(),
$projection->id(),
$projection->position(),
$projection->status()->value,
$projection->projectionError()?->errorMessage,
Expand Down
3 changes: 1 addition & 2 deletions src/Metadata/Projector/AttributeProjectorMetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ public function metadata(string $projector): ProjectorMetadata
}

$metadata = new ProjectorMetadata(
$projectorInfo->name,
$projectorInfo->version,
$projectorInfo->id,
$subscribeMethods,
$createMethod,
$dropMethod,
Expand Down
3 changes: 1 addition & 2 deletions src/Metadata/Projector/ProjectorMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
final class ProjectorMetadata
{
public function __construct(
public readonly string $name,
public readonly int $version,
public readonly string $id,
/** @var array<class-string|"*", list<string>> */
public readonly array $subscribeMethods = [],
public readonly string|null $setupMethod = null,
Expand Down
4 changes: 2 additions & 2 deletions src/Projection/Projection/DuplicateProjectionId.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

final class DuplicateProjectionId extends RuntimeException
{
public function __construct(ProjectionId $projectionId)
public function __construct(string $projectionId)
{
parent::__construct(sprintf('projection with the id "%s" exist already', $projectionId->toString()));
parent::__construct(sprintf('projection with the id "%s" exist already', $projectionId));
}
}
4 changes: 2 additions & 2 deletions src/Projection/Projection/Projection.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
final class Projection
{
public function __construct(
private readonly ProjectionId $id,
private readonly string $id,
private ProjectionStatus $status = ProjectionStatus::New,
private int $position = 0,
private ProjectionError|null $error = null,
private int $retry = 0,
) {
}

public function id(): ProjectionId
public function id(): string
{
return $this->id;
}
Expand Down
14 changes: 7 additions & 7 deletions src/Projection/Projection/ProjectionCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,28 @@ public function __construct(array $projections = [])
$result = [];

foreach ($projections as $projection) {
if (array_key_exists($projection->id()->toString(), $result)) {
if (array_key_exists($projection->id(), $result)) {
throw new DuplicateProjectionId($projection->id());
}

$result[$projection->id()->toString()] = $projection;
$result[$projection->id()] = $projection;
}

$this->projections = $result;
}

public function get(ProjectionId $projectorId): Projection
public function get(string $projectorId): Projection
{
if (!$this->has($projectorId)) {
throw new ProjectionNotFound($projectorId);
}

return $this->projections[$projectorId->toString()];
return $this->projections[$projectorId];
}

public function has(ProjectionId $projectorId): bool
public function has(string $projectorId): bool
{
return array_key_exists($projectorId->toString(), $this->projections);
return array_key_exists($projectorId, $this->projections);
}

public function add(Projection $projection): self
Expand Down Expand Up @@ -104,7 +104,7 @@ public function filterByCriteria(ProjectionCriteria $criteria): self
static function (Projection $projection) use ($criteria): bool {
if ($criteria->ids !== null) {
foreach ($criteria->ids as $id) {
if ($projection->id()->equals($id)) {
if ($projection->id() === $id) {
return true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Projection/Projection/ProjectionCriteria.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/** @psalm-immutable */
final class ProjectionCriteria
{
/** @param list<ProjectionId>|null $ids */
/** @param list<string>|null $ids */
public function __construct(
public readonly array|null $ids = null,
) {
Expand Down
63 changes: 0 additions & 63 deletions src/Projection/Projection/ProjectionId.php

This file was deleted.

4 changes: 2 additions & 2 deletions src/Projection/Projection/ProjectionNotFound.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

final class ProjectionNotFound extends RuntimeException
{
public function __construct(ProjectionId $projectionId)
public function __construct(string $projectionId)
{
parent::__construct(sprintf('projection with the id "%s" not found', $projectionId->toString()));
parent::__construct(sprintf('projection with the id "%s" not found', $projectionId));
}
}
Loading

0 comments on commit a469f0d

Please sign in to comment.