Skip to content

Commit

Permalink
Merge pull request #625 from patchlevel/in-memory-store
Browse files Browse the repository at this point in the history
add in memory event store
  • Loading branch information
DavidBadura authored Jul 30, 2024
2 parents fe23cbc + 664ea5e commit def0b67
Show file tree
Hide file tree
Showing 7 changed files with 649 additions and 44 deletions.
5 changes: 5 additions & 0 deletions baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@
<code><![CDATA[$dateTimeType->convertToPHPValue($data['recorded_on'], $platform)]]></code>
</MixedArgument>
</file>
<file src="src/Store/InMemoryStore.php">
<MixedPropertyTypeCoercion>
<code><![CDATA[$this->messages]]></code>
</MixedPropertyTypeCoercion>
</file>
<file src="src/Store/StreamDoctrineDbalStoreStream.php">
<ArgumentTypeCoercion>
<code><![CDATA[$data['playhead'] === null ? null : (int)$data['playhead']]]></code>
Expand Down
87 changes: 51 additions & 36 deletions docs/pages/store.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,11 @@ Each message contains an event and the associated headers.

The store is optimized to efficiently store and load events for aggregates.

## Create DBAL connection

The first thing we need for our store is a DBAL connection:

```php
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Tools\DsnParser;

$connection = DriverManager::getConnection(
(new DsnParser())->parse('pdo-pgsql://user:secret@localhost/app'),
);
```
!!! note

You can find out more about how to create a connection
[here](https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html)

## Configure Store

We currently offer two stores, both based on the [doctrine dbal](https://www.doctrine-project.org/projects/dbal.html) library.
The default store is the `DoctrineDbalStore` and the new experimental store is the `StreamDoctrineDbalStore`.
We offer different stores to store the messages.
Two stores based on [doctrine dbal](https://www.doctrine-project.org/projects/dbal.html)
and one in-memory store for testing purposes.

### DoctrineDbalStore

Expand All @@ -38,16 +22,25 @@ You can create a store with the `DoctrineDbalStore` class.
The store needs a dbal connection, an event serializer and has some optional parameters like options.

```php
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Tools\DsnParser;
use Patchlevel\EventSourcing\Serializer\DefaultEventSerializer;
use Patchlevel\EventSourcing\Store\DoctrineDbalStore;

/** @var Connection $connection */
$connection = DriverManager::getConnection(
(new DsnParser())->parse('pdo-pgsql://user:secret@localhost/app'),
);

$store = new DoctrineDbalStore(
$connection,
DefaultEventSerializer::createFromPaths(['src/Event']),
);
```
!!! note

You can find out more about how to create a connection
[here](https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html)

Following options are available in `DoctrineDbalStore`:

| Option | Type | Default | Description |
Expand Down Expand Up @@ -89,16 +82,25 @@ This store introduces two new methods `streams` and `remove`.
The store needs a dbal connection, an event serializer and has some optional parameters like options.

```php
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Tools\DsnParser;
use Patchlevel\EventSourcing\Serializer\DefaultEventSerializer;
use Patchlevel\EventSourcing\Store\StreamDoctrineDbalStore;

/** @var Connection $connection */
$connection = DriverManager::getConnection(
(new DsnParser())->parse('pdo-pgsql://user:secret@localhost/app'),
);

$store = new StreamDoctrineDbalStore(
$connection,
DefaultEventSerializer::createFromPaths(['src/Event']),
);
```
!!! note

You can find out more about how to create a connection
[here](https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html)

Following options are available in `StreamDoctrineDbalStore`:

| Option | Type | Default | Description |
Expand All @@ -122,6 +124,19 @@ The table structure of the `StreamDoctrineDbalStore` looks like this:
| archived | bool | If the event is archived |
| custom_headers | json | Custom headers for the event |

### InMemoryStore

We also offer an in-memory store for testing purposes.

```php
use Patchlevel\EventSourcing\Store\InMemoryStore;

$store = new InMemoryStore();
```
!!! tip

You can pass messages to the constructor to initialize the store with some events.

## Schema

With the help of the `SchemaDirector`, the database structure can be created, updated and deleted.
Expand All @@ -130,7 +145,7 @@ With the help of the `SchemaDirector`, the database structure can be created, up

You can also use doctrine migration to create and keep your schema in sync.

### Schema Director
### Doctrine Schema Director

The `SchemaDirector` is responsible for creating, updating and deleting the database schema.
The `DoctrineSchemaDirector` is a concrete implementation of the `SchemaDirector` for doctrine dbal.
Expand Down Expand Up @@ -159,18 +174,18 @@ $schemaDirector = new DoctrineSchemaDirector(
You can create the table from scratch using the `create` method.

```php
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
use Patchlevel\EventSourcing\Schema\SchemaDirector;

/** @var DoctrineSchemaDirector $schemaDirector */
/** @var SchemaDirector $schemaDirector */
$schemaDirector->create();
```
Or can give you back which SQL statements would be necessary for this.
Either for a dry run, or to define your own migrations.

```php
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
use Patchlevel\EventSourcing\Schema\DryRunSchemaDirector;

/** @var DoctrineSchemaDirector $schemaDirector */
/** @var DryRunSchemaDirector $schemaDirector */
$sql = $schemaDirector->dryRunCreate();
```
#### Update schema
Expand All @@ -179,35 +194,35 @@ The update method compares the current state in the database and how the table s
As a result, the diff is executed to bring the table to the desired state.

```php
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
use Patchlevel\EventSourcing\Schema\SchemaDirector;

/** @var DoctrineSchemaDirector $schemaDirector */
/** @var SchemaDirector $schemaDirector */
$schemaDirector->update();
```
Or can give you back which SQL statements would be necessary for this.

```php
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
use Patchlevel\EventSourcing\Schema\DryRunSchemaDirector;

/** @var DoctrineSchemaDirector $schemaDirector */
/** @var DryRunSchemaDirector $schemaDirector */
$sql = $schemaDirector->dryRunUpdate();
```
#### Drop schema

You can also delete the table with the `drop` method.

```php
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
use Patchlevel\EventSourcing\Schema\SchemaDirector;

/** @var DoctrineSchemaDirector $schemaDirector */
/** @var SchemaDirector $schemaDirector */
$schemaDirector->drop();
```
Or can give you back which SQL statements would be necessary for this.

```php
use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector;
use Patchlevel\EventSourcing\Schema\DryRunSchemaDirector;

/** @var DoctrineSchemaDirector $schemaDirector */
/** @var DryRunSchemaDirector $schemaDirector */
$sql = $schemaDirector->dryRunDrop();
```
### Doctrine Migrations
Expand Down
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ parameters:
count: 1
path: src/Store/DoctrineDbalStoreStream.php

-
message: "#^Property Patchlevel\\\\EventSourcing\\\\Store\\\\InMemoryStore\\:\\:\\$messages \\(array\\<int\\<0, max\\>, Patchlevel\\\\EventSourcing\\\\Message\\\\Message\\>\\) does not accept array\\<int, Patchlevel\\\\EventSourcing\\\\Message\\\\Message\\>\\.$#"
count: 1
path: src/Store/InMemoryStore.php

-
message: "#^Parameter \\#2 \\$playhead of class Patchlevel\\\\EventSourcing\\\\Store\\\\StreamHeader constructor expects int\\<1, max\\>\\|null, int\\|null given\\.$#"
count: 1
Expand Down
7 changes: 7 additions & 0 deletions src/Store/Criteria/StreamCriterion.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@

namespace Patchlevel\EventSourcing\Store\Criteria;

use Patchlevel\EventSourcing\Store\InvalidStreamName;

use function preg_match;

/** @experimental */
final class StreamCriterion
{
public function __construct(
public readonly string $streamName,
) {
if (!preg_match('/^[^*]*\*?$/', $this->streamName)) {
throw new InvalidStreamName($this->streamName);
}
}

public static function startWith(string $streamName): self
Expand Down
Loading

0 comments on commit def0b67

Please sign in to comment.