-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5ce6710
commit 5e1b140
Showing
4 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Patchlevel\EventSourcing\Debug; | ||
|
||
use Patchlevel\EventSourcing\Aggregate\AggregateRoot; | ||
|
||
use function microtime; | ||
|
||
final class ProfileData | ||
{ | ||
private float|null $start = null; | ||
private float|null $duration = null; | ||
|
||
private function __construct( | ||
private readonly string $type, | ||
/** @var class-string<AggregateRoot> */ | ||
private readonly string $aggregateClass, | ||
private readonly string $aggregateId, | ||
) { | ||
} | ||
|
||
public function start(): void | ||
{ | ||
$this->start = microtime(true); | ||
} | ||
|
||
public function stop(): void | ||
{ | ||
if ($this->start === null) { | ||
return; | ||
} | ||
|
||
$this->duration = microtime(true) - $this->start; | ||
} | ||
|
||
public function type(): string | ||
{ | ||
return $this->type; | ||
} | ||
|
||
/** @return class-string<AggregateRoot> */ | ||
public function aggregateClass(): string | ||
{ | ||
return $this->aggregateClass; | ||
} | ||
|
||
public function aggregateId(): string | ||
{ | ||
return $this->aggregateId; | ||
} | ||
|
||
public function duration(): float|null | ||
{ | ||
return $this->duration; | ||
} | ||
|
||
/** @param class-string<AggregateRoot> $aggregateClass */ | ||
public static function load(string $aggregateClass, string $aggregateId): self | ||
{ | ||
return new ProfileData('load', $aggregateClass, $aggregateId); | ||
} | ||
|
||
/** @param class-string<AggregateRoot> $aggregateClass */ | ||
public static function save(string $aggregateClass, string $aggregateId): self | ||
{ | ||
return new ProfileData('save', $aggregateClass, $aggregateId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Patchlevel\EventSourcing\Debug; | ||
|
||
final class ProfileDataHolder | ||
{ | ||
/** @var ProfileData[] */ | ||
private array $data = []; | ||
|
||
public function addData(ProfileData $data): void | ||
{ | ||
$this->data[] = $data; | ||
} | ||
|
||
/** @return ProfileData[] */ | ||
public function getData(): array | ||
{ | ||
return $this->data; | ||
} | ||
|
||
public function reset(): void | ||
{ | ||
$this->data = []; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Patchlevel\EventSourcing\Debug; | ||
|
||
use Patchlevel\EventSourcing\Aggregate\AggregateRoot; | ||
use Patchlevel\EventSourcing\Repository\Repository; | ||
use Symfony\Component\Stopwatch\Stopwatch; | ||
|
||
/** | ||
* @template T of AggregateRoot | ||
* @implements Repository<T> | ||
*/ | ||
final class TraceableRepository implements Repository | ||
{ | ||
public function __construct( | ||
/** @var Repository<T> */ | ||
private readonly Repository $repository, | ||
/** @var class-string<T> */ | ||
private readonly string $aggregateClass, | ||
private readonly ProfileDataHolder $dataHolder, | ||
private readonly Stopwatch|null $stopwatch = null, | ||
) { | ||
} | ||
|
||
/** @return T */ | ||
public function load(string $id): AggregateRoot | ||
{ | ||
$data = ProfileData::load($this->aggregateClass, $id); | ||
|
||
$this->dataHolder->addData($data); | ||
$event = $this->stopwatch?->start('event_sourcing', 'event_sourcing'); | ||
$data->start(); | ||
|
||
try { | ||
$aggregate = $this->repository->load($id); | ||
} finally { | ||
$data->stop(); | ||
$event?->stop(); | ||
} | ||
|
||
return $aggregate; | ||
} | ||
|
||
public function has(string $id): bool | ||
{ | ||
return $this->repository->has($id); | ||
} | ||
|
||
/** @param T $aggregate */ | ||
public function save(AggregateRoot $aggregate): void | ||
{ | ||
$event = $this->stopwatch?->start('event_sourcing', 'event_sourcing'); | ||
|
||
$this->repository->save($aggregate); | ||
|
||
$event?->stop(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Patchlevel\EventSourcing\Debug; | ||
|
||
use Patchlevel\EventSourcing\Aggregate\AggregateRoot; | ||
use Patchlevel\EventSourcing\Repository\Repository; | ||
use Patchlevel\EventSourcing\Repository\RepositoryManager; | ||
use Symfony\Component\Stopwatch\Stopwatch; | ||
|
||
final class TraceableRepositoryManager implements RepositoryManager | ||
{ | ||
public function __construct( | ||
private RepositoryManager $repositoryManager, | ||
private readonly ProfileDataHolder $dataHolder, | ||
private readonly Stopwatch|null $stopwatch = null, | ||
) { | ||
} | ||
|
||
/** | ||
* @param class-string<T> $aggregateClass | ||
* | ||
* @return Repository<T> | ||
* | ||
* @template T of AggregateRoot | ||
*/ | ||
public function get(string $aggregateClass): Repository | ||
{ | ||
return new TraceableRepository( | ||
$this->repositoryManager->get($aggregateClass), | ||
$aggregateClass, | ||
$this->dataHolder, | ||
$this->stopwatch, | ||
); | ||
} | ||
} |