Skip to content

Commit

Permalink
Merge pull request #550 from patchlevel/fix-some-docs-issues
Browse files Browse the repository at this point in the history
fix some docs issues
  • Loading branch information
DavidBadura authored Mar 22, 2024
2 parents ecf5795 + 0c435b0 commit 8556e0b
Show file tree
Hide file tree
Showing 13 changed files with 345 additions and 92 deletions.
2 changes: 1 addition & 1 deletion bin/docs-extract-php-code
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ foreach ($finder as $file) {

$source = sprintf('%s:%s', $file->getRealPath(), $node->getStartLine());

$code = "<?php\n // " . $source . "\n\n" . $node->getLiteral();
$code = "<?php\n// " . $source . "\n\n" . $node->getLiteral();

$targetPath = $targetDir . '/' . $fileName . '_' . $i . '.php';
file_put_contents($targetPath, $code);
Expand Down
10 changes: 6 additions & 4 deletions docs/pages/aggregate.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ final class Profile extends BasicAggregateRoot
#[Apply]
protected function applyNameChanged(NameChanged $event): void
{
$this->name = $event->name();
$this->name = $event->name;
}
}
```
Expand Down Expand Up @@ -581,7 +581,7 @@ use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot;
use Patchlevel\EventSourcing\Aggregate\Uuid;
use Patchlevel\EventSourcing\Attribute\Aggregate;
use Patchlevel\EventSourcing\Attribute\Id;
use Patchlevel\EventSourcing\Clock\Clock;
use Psr\Clock\ClockInterface;

#[Aggregate('profile')]
final class Profile extends BasicAggregateRoot
Expand All @@ -591,7 +591,7 @@ final class Profile extends BasicAggregateRoot
private Name $name;
private DateTimeImmutable $registeredAt;

public static function register(Uuid $id, string $name, Clock $clock): static
public static function register(Uuid $id, string $name, ClockInterface $clock): static
{
$self = new static();
$self->recordThat(new ProfileRegistered($id, $name, $clock->now()));
Expand Down Expand Up @@ -627,7 +627,9 @@ There, with the help of paths, all classes with the attribute `Aggregate` are se
and the `AggregateRootRegistry` is built up.

```php
$aggregateRegistry = (new AttributeEventRegistryFactory())->create($paths);
use Patchlevel\EventSourcing\Metadata\Event\AttributeEventRegistryFactory;

$aggregateRegistry = (new AttributeEventRegistryFactory())->create([/* paths... */]);
```
## Learn more

Expand Down
71 changes: 36 additions & 35 deletions docs/pages/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,38 +57,40 @@ The inspector is a tool to inspect the event streams.
A cli php file can look like this:

```php
use Doctrine\DBAL\Connection;
use Patchlevel\EventSourcing\Console\Command;
use Patchlevel\EventSourcing\Console\DoctrineHelper;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaManager;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
use Patchlevel\EventSourcing\Store\Store;
use Patchlevel\EventSourcing\Subscription\Engine\SubscriptionEngine;
use Symfony\Component\Console\Application;

/* define your doctrine store */
$store;

/* create projectionist */
$projectionist;

$cli = new Application('Event-Sourcing CLI');
$cli->setCatchExceptions(true);

$doctrineHelper = new DoctrineHelper();
$schemaManager = new DoctrineSchemaManager();

/**
* @var Connection $connection
* @var Store $store
*/
$schemaDirector = new DoctrineSchemaDirector($connection, $store);

/** @var SubscriptionEngine $subscriptionEngine */
$cli->addCommands([
new Command\DatabaseCreateCommand($store, $doctrineHelper),
new Command\DatabaseDropCommand($store, $doctrineHelper),
new Command\SubscriptionBootCommand($projectionist),
new Command\SubscriptionPauseCommand($projectionist),
new Command\SubscriptionRunCommand($projectionist),
new Command\SubscriptionTeardownCommand($projectionist),
new Command\SubscriptionRemoveCommand($projectionist),
new Command\SubscriptionReactivateCommand($projectionist),
new Command\SubscriptionRebuildCommand($projectionist),
new Command\SubscriptionSetupCommand($projectionist),
new Command\SubscriptionStatusCommand($projectionist),
new Command\SchemaCreateCommand($store, $schemaManager),
new Command\SchemaDropCommand($store, $schemaManager),
new Command\SchemaUpdateCommand($store, $schemaManager),
new Command\DatabaseCreateCommand($connection, $doctrineHelper),
new Command\DatabaseDropCommand($connection, $doctrineHelper),
new Command\SubscriptionBootCommand($subscriptionEngine, $store),
new Command\SubscriptionPauseCommand($subscriptionEngine),
new Command\SubscriptionRunCommand($subscriptionEngine, $store),
new Command\SubscriptionTeardownCommand($subscriptionEngine),
new Command\SubscriptionRemoveCommand($subscriptionEngine),
new Command\SubscriptionReactivateCommand($subscriptionEngine),
new Command\SubscriptionSetupCommand($subscriptionEngine),
new Command\SubscriptionStatusCommand($subscriptionEngine),
new Command\SchemaCreateCommand($schemaDirector),
new Command\SchemaDropCommand($schemaDirector),
new Command\SchemaUpdateCommand($schemaDirector),
]);

$cli->run();
Expand All @@ -98,26 +100,24 @@ $cli->run();
If you want to use doctrine migrations, you can register the commands like this:

```php
use Doctrine\DBAL\Connection;
use Doctrine\Migrations\Configuration\Connection\ExistingConnection;
use Doctrine\Migrations\Configuration\Migration\ConfigurationLoader;
use Doctrine\Migrations\DependencyFactory;
use Doctrine\Migrations\Provider\SchemaProvider;
use Doctrine\Migrations\Tools\Console\Command;
use Patchlevel\EventSourcing\Schema\DoctrineMigrationSchemaProvider;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
use Patchlevel\EventSourcing\Store\Store;
use Symfony\Component\Console\Application;

/* create connection */
$connection;
/* define your doctrine store */
$store;

$schemaDirector = new DoctrineSchemaDirector(
$store,
$connection,
);

/* define your migration config */
$migrationConfig;

/**
* @var Connection $connection
* @var Store $store
*/
$schemaDirector = new DoctrineSchemaDirector($connection, $store);

/** @var ConfigurationLoader $migrationConfig */
$dependencyFactory = DependencyFactory::fromConnection(
$migrationConfig,
new ExistingConnection($connection),
Expand All @@ -129,6 +129,7 @@ $dependencyFactory->setService(
new DoctrineMigrationSchemaProvider($schemaDirector),
);

/** @var Application $cli */
$cli->addCommands([
new Command\ExecuteCommand($dependencyFactory, 'event-sourcing:migrations:execute'),
new Command\GenerateCommand($dependencyFactory, 'event-sourcing:migrations:generate'),
Expand Down
5 changes: 3 additions & 2 deletions docs/pages/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ You can do that too. However, you must define a normalizer for this
so that the library knows how to write this data to the database and load it again.

```php
use Patchlevel\EventSourcing\Aggregate\Uuid;
use Patchlevel\EventSourcing\Attribute\Event;
use Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer;
use Patchlevel\Hydrator\Normalizer\DateTimeImmutableNormalizer;
use Patchlevel\Hydrator\Normalizer\IdNormalizer;

#[Event('profile.created')]
final class ProfileCreated
Expand Down Expand Up @@ -107,7 +108,7 @@ and the `EventRegistry` is built up.
```php
use Patchlevel\EventSourcing\Metadata\Event\AttributeEventRegistryFactory;

$eventRegistry = (new AttributeEventRegistryFactory())->create($paths);
$eventRegistry = (new AttributeEventRegistryFactory())->create([/* paths... */]);
```
## Learn more

Expand Down
46 changes: 34 additions & 12 deletions docs/pages/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ A hotel can be created with a `name` and a `id`:

```php
use Patchlevel\EventSourcing\Aggregate\Uuid;
use Patchlevel\EventSourcing\Attribute\Event;
use Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer;

#[Event('hotel.created')]
Expand All @@ -27,6 +28,8 @@ final class HotelCreated
A guest can check in by `name`:

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

#[Event('hotel.guest_checked_in')]
final class GuestIsCheckedIn
{
Expand All @@ -39,6 +42,8 @@ final class GuestIsCheckedIn
And also check out again:

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

#[Event('hotel.guest_checked_out')]
final class GuestIsCheckedOut
{
Expand Down Expand Up @@ -82,7 +87,8 @@ final class Hotel extends BasicAggregateRoot
return $this->name;
}

public function guests(): int
/** @return list<string> */
public function guests(): array
{
return $this->guests;
}
Expand Down Expand Up @@ -151,6 +157,7 @@ Each projector is then responsible for a specific projection.

```php
use Doctrine\DBAL\Connection;
use Patchlevel\EventSourcing\Aggregate\AggregateHeader;
use Patchlevel\EventSourcing\Attribute\Projector;
use Patchlevel\EventSourcing\Attribute\Setup;
use Patchlevel\EventSourcing\Attribute\Subscribe;
Expand Down Expand Up @@ -182,7 +189,7 @@ final class HotelProjector
$this->db->insert(
$this->table(),
[
'id' => $message->aggregateId(),
'id' => $message->header(AggregateHeader::class)->aggregateId,
'name' => $event->hotelName,
'guests' => 0,
],
Expand All @@ -194,7 +201,7 @@ final class HotelProjector
{
$this->db->executeStatement(
"UPDATE {$this->table()} SET guests = guests + 1 WHERE id = ?;",
[$message->aggregateId()],
[$message->header(AggregateHeader::class)->aggregateId],
);
}

Expand All @@ -203,7 +210,7 @@ final class HotelProjector
{
$this->db->executeStatement(
"UPDATE {$this->table()} SET guests = guests - 1 WHERE id = ?;",
[$message->aggregateId()],
[$message->header(AggregateHeader::class)->aggregateId],
);
}

Expand Down Expand Up @@ -267,12 +274,13 @@ After we have defined everything, we still have to plug the whole thing together

```php
use Doctrine\DBAL\DriverManager;
use Patchlevel\EventSourcing\Projection\Engine\DefaultSubscriptionEngine;
use Patchlevel\EventSourcing\Projection\Store\DoctrineSubscriptionStore;
use Patchlevel\EventSourcing\Projection\Subscriber\MetadataSubscriberAccessorRepository;
use Patchlevel\EventSourcing\Metadata\AggregateRoot\AttributeAggregateRootRegistryFactory;
use Patchlevel\EventSourcing\Repository\DefaultRepositoryManager;
use Patchlevel\EventSourcing\Serializer\DefaultEventSerializer;
use Patchlevel\EventSourcing\Store\DoctrineDbalStore;
use Patchlevel\EventSourcing\Subscription\Engine\DefaultSubscriptionEngine;
use Patchlevel\EventSourcing\Subscription\Store\DoctrineSubscriptionStore;
use Patchlevel\EventSourcing\Subscription\Subscriber\MetadataSubscriberAccessorRepository;

$connection = DriverManager::getConnection(['url' => 'mysql://user:secret@localhost/app']);

Expand All @@ -287,7 +295,6 @@ $aggregateRegistry = (new AttributeAggregateRootRegistryFactory())->create(['src
$eventStore = new DoctrineDbalStore(
$connection,
$serializer,
$aggregateRegistry,
);

$hotelProjector = new HotelProjector($projectionConnection);
Expand Down Expand Up @@ -322,19 +329,30 @@ So that we can actually write the data to a database,
we need the associated schema and databases.

```php
use Doctrine\DBAL\Connection;
use Patchlevel\EventSourcing\Schema\ChainDoctrineSchemaConfigurator;
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;

use Patchlevel\EventSourcing\Store\Store;
use Patchlevel\EventSourcing\Subscription\Engine\SubscriptionEngine;
use Patchlevel\EventSourcing\Subscription\Store\SubscriptionStore;

/**
* @var Connection $connection
* @var Store $eventStore
* @var SubscriptionStore $subscriptionStore
*/
$schemaDirector = new DoctrineSchemaDirector(
$connection,
new ChainDoctrineSchemaConfigurator([
$eventStore,
$projectionStore,
$subscriptionStore,
]),
);

$schemaDirector->create();
$projectionist->setup(skipBooting: true);

/** @var SubscriptionEngine $engine */
$engine->setup(skipBooting: true);
```
!!! note

Expand All @@ -346,19 +364,23 @@ We are now ready to use the Event Sourcing System. We can load, change and save

```php
use Patchlevel\EventSourcing\Aggregate\Uuid;
use Patchlevel\EventSourcing\Repository\Repository;
use Patchlevel\EventSourcing\Subscription\Engine\SubscriptionEngine;

$hotel1 = Hotel::create(Uuid::v7(), 'HOTEL');
$hotel1->checkIn('David');
$hotel1->checkIn('Daniel');
$hotel1->checkOut('David');

/** @var Repository $hotelRepository */
$hotelRepository->save($hotel1);

$hotel2 = $hotelRepository->load(Uuid::fromString('d0d0d0d0-d0d0-d0d0-d0d0-d0d0d0d0d0d0'));
$hotel2->checkIn('David');
$hotelRepository->save($hotel2);

$projectionist->run();
/** @var SubscriptionEngine $engine */
$engine->run();

$hotels = $hotelProjection->getHotels();
```
Expand Down
27 changes: 25 additions & 2 deletions docs/pages/message_decorator.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ To use multiple decorators at the same time, you can use the `ChainMessageDecora

```php
use Patchlevel\EventSourcing\Repository\MessageDecorator\ChainMessageDecorator;
use Patchlevel\EventSourcing\Repository\MessageDecorator\MessageDecorator;

/**
* @var MessageDecorator $decorator1
* @var MessageDecorator $decorator2
*/
$decorator = new ChainMessageDecorator([
$decorator1,
$decorator2,
Expand All @@ -37,16 +42,24 @@ To use the message decorator, you have to pass it to the `DefaultRepositoryManag
which will then pass it to all Repositories.

```php
use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry;
use Patchlevel\EventSourcing\Metadata\Event\EventMetadataFactory;
use Patchlevel\EventSourcing\Repository\DefaultRepositoryManager;
use Patchlevel\EventSourcing\Repository\MessageDecorator\ChainMessageDecorator;
use Patchlevel\EventSourcing\Repository\MessageDecorator\SplitStreamDecorator;
use Patchlevel\EventSourcing\Store\Store;

/** @var EventMetadataFactory $eventMetadataFactory */
$decorator = new ChainMessageDecorator([new SplitStreamDecorator($eventMetadataFactory)]);

/**
* @var AggregateRootRegistry $aggregateRootRegistry
* @var Store $store
*/
$repositoryManager = new DefaultRepositoryManager(
$aggregateRootRegistry,
$store,
$eventBus,
null,
null,
$decorator,
);
Expand All @@ -63,14 +76,24 @@ You can also use this feature to add your own metadata to your events. For this
to add data `withHeader` and to read this data later on `header`.

```php
use Patchlevel\EventSourcing\Attribute\Header;
use Patchlevel\EventSourcing\Message\Message;
use Patchlevel\EventSourcing\Repository\MessageDecorator\MessageDecorator;

#[Header('system')]
final class SystemHeader
{
public function __construct(
public string $system,
) {
}
}

final class OnSystemRecordedDecorator implements MessageDecorator
{
public function __invoke(Message $message): Message
{
return $message->withHeader('system', 'accounting_system');
return $message->withHeader(new SystemHeader('system'));
}
}
```
Expand Down
Loading

0 comments on commit 8556e0b

Please sign in to comment.