Skip to content

Commit

Permalink
change snapshot store interfaces
Browse files Browse the repository at this point in the history
resolves: #5
  • Loading branch information
prolic committed Jan 25, 2017
1 parent 885f9bf commit 1dd0e3f
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 20 deletions.
64 changes: 44 additions & 20 deletions src/PdoSnapshotStore.php
Expand Up @@ -71,34 +71,58 @@ public function get(string $aggregateType, string $aggregateId): ?Snapshot
);
}

public function save(Snapshot $snapshot): void
public function save(Snapshot ...$snapshots): void
{
$table = $this->getTableName($snapshot->aggregateType());
if (empty($snapshots)) {
return;
}

$this->connection->beginTransaction();
$deletes = [];
$inserts = [];

foreach ($snapshots as $snapshot) {
$deletes[$this->getTableName($snapshot->aggregateType())][] = $snapshot->aggregateId();
$inserts[$this->getTableName($snapshot->aggregateType())][] = $snapshot;
}

$statements = [];

$delete = <<<EOT
DELETE FROM $table WHERE aggregate_id = ?
foreach ($deletes as $table => $aggregateIds) {
$ids = implode(', ', array_fill(0, count($aggregateIds), '?'));
$deleteSql = <<<EOT
DELETE FROM $table where aggregate_id IN ($ids);
EOT;
$statement = $this->connection->prepare($deleteSql);
foreach ($aggregateIds as $position => $aggregateId) {
$statement->bindValue($position + 1, $aggregateId);
}

$statement = $this->connection->prepare($delete);
$statement->execute([
$snapshot->aggregateId(),
]);
$statements[] = $statement;
}

$insert = <<<EOT
foreach ($inserts as $table => $snapshots) {
$allPlaces = implode(', ', array_fill(0, count($snapshots), '(?, ?, ?, ?, ?)'));
$insertSql = <<<EOT
INSERT INTO $table (aggregate_id, aggregate_type, last_version, created_at, aggregate_root)
VALUES (?, ?, ?, ?, ?);
VALUES $allPlaces
EOT;
$statement = $this->connection->prepare($insertSql);
foreach ($snapshots as $index => $snapshot) {
$position = $index * 5;
$statement->bindValue(++$position, $snapshot->aggregateId());
$statement->bindValue(++$position, $snapshot->aggregateType());
$statement->bindValue(++$position, $snapshot->lastVersion(), PDO::PARAM_INT);
$statement->bindValue(++$position, $snapshot->createdAt()->format('Y-m-d\TH:i:s.u'));
$statement->bindValue(++$position, serialize($snapshot->aggregateRoot()));
}
$statements[] = $statement;
}

$statement = $this->connection->prepare($insert);
$statement->execute([
$snapshot->aggregateId(),
$snapshot->aggregateType(),
$snapshot->lastVersion(),
$snapshot->createdAt()->format('Y-m-d\TH:i:s.u'),
serialize($snapshot->aggregateRoot()),
]);
$this->connection->beginTransaction();

foreach ($statements as $statement) {
$statement->execute();
}

$this->connection->commit();
}
Expand All @@ -116,7 +140,7 @@ private function getTableName(string $aggregateType): string

/**
* @param string|resource $serialized
* @return object
* @return object|array
*/
private function unserializeAggregateRoot($serialized)
{
Expand Down
43 changes: 43 additions & 0 deletions tests/PdoSnapshotStoreTest.php
Expand Up @@ -67,6 +67,41 @@ public function it_saves_and_reads()
$this->assertCount(1, $snapshots);
}

/**
* @test
*/
public function it_saves_multiple_snapshots()
{
$aggregateRoot1 = new \stdClass();
$aggregateRoot1->foo = 'bar';

$aggregateRoot2 = ['foo' => 'baz'];

$time = (string) microtime(true);
if (false === strpos($time, '.')) {
$time .= '.0000';
}

$now = \DateTimeImmutable::createFromFormat('U.u', $time);

$snapshot1 = new Snapshot('object', 'id_one', $aggregateRoot1, 1, $now);

$snapshot2 = new Snapshot('array', 'id_two', $aggregateRoot2, 2, $now);

$this->snapshotStore->save($snapshot1, $snapshot2);

$this->assertEquals($snapshot1, $this->snapshotStore->get('object', 'id_one'));
$this->assertEquals($snapshot2, $this->snapshotStore->get('array', 'id_two'));
}

/**
* @test
*/
public function it_returns_early_when_no_snapshots_given()
{
$this->snapshotStore->save();
}

/**
* @test
*/
Expand Down Expand Up @@ -117,6 +152,14 @@ protected function setUp(): void
$this->snapshotStore = new PdoSnapshotStore($this->connection, ['foo' => 'bar'], 'snapshots');
}

protected function tearDown(): void
{
$statement = $this->connection->prepare('TRUNCATE snapshots');
$statement->execute();
$statement = $this->connection->prepare('TRUNCATE bar');
$statement->execute();
}

protected function createTable(string $name)
{
switch (TestUtil::getDatabaseVendor()) {
Expand Down

0 comments on commit 1dd0e3f

Please sign in to comment.