-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEventSourcingRoot.php
More file actions
98 lines (89 loc) · 4.39 KB
/
Copy pathEventSourcingRoot.php
File metadata and controls
98 lines (89 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?php
declare(strict_types=1);
namespace TinyBlocks\BuildingBlocks\Aggregate;
use TinyBlocks\BuildingBlocks\Entity\Identity;
use TinyBlocks\BuildingBlocks\Event\DomainEvent;
use TinyBlocks\BuildingBlocks\Event\EventRecord;
use TinyBlocks\BuildingBlocks\Event\EventRecords;
use TinyBlocks\BuildingBlocks\Internal\Exceptions\MissingIdentityProperty;
use TinyBlocks\BuildingBlocks\Snapshot\Snapshot;
/**
* Aggregate root variant whose state is derived entirely from its ordered stream of events.
*
* <p>The event store is the source of truth; aggregate state is a projection. Instances are created
* through {@see blank()} and populated by replaying events via {@see reconstitute()}, optionally starting
* from a {@see Snapshot} to skip earlier events.</p>
*
* <p>Sibling of {@see EventualAggregateRoot}, not a parent. The default implementation instantiates
* aggregates via reflection without invoking the constructor, so implementations must derive all state
* from events or from a snapshot, never from constructor logic.</p>
*
* @see Greg Young, <em>CQRS Documents</em> (2010), "Event Sourcing".
* @see Vaughn Vernon, <em>Implementing Domain-Driven Design</em> (Addison-Wesley, 2013), Chapter 8,
* "Event Sourcing" section.
*/
interface EventSourcingRoot extends AggregateRoot
{
/**
* Returns the explicit map of event class names to handler callables.
*
* <p>When the returned array is empty, the trait falls back to the implicit
* convention <code>when<EventShortName></code>. When the array is
* non-empty, it is the authoritative source: only events whose class names
* appear as keys can be applied; absence triggers an exception.</p>
*
* @return array<class-string<DomainEvent>, callable>
*/
public function eventHandlers(): array;
/**
* Returns the events recorded during the current unit of work.
*
* @return EventRecords The events awaiting append to the event store.
*/
public function recordedEvents(): EventRecords;
/**
* Creates a blank aggregate with the given identity and no recorded events.
*
* <p>The constructor is not invoked. All state must come from events or from a snapshot.</p>
*
* @param Identity $identity The identity to assign to the new aggregate.
* @return static A new aggregate in its initial state.
* @throws MissingIdentityProperty When the property referenced by <code>identityProperty()</code> does not exist.
*/
public static function blank(Identity $identity): static;
/**
* Reconstitutes an aggregate by replaying an ordered stream of event records.
*
* <p>When a snapshot is provided, the aggregate state is first restored from it and the snapshot's
* sequence number is taken as authoritative. Only events recorded after the snapshot need to be
* replayed.</p>
*
* @param Identity $identity The identity of the aggregate.
* @param iterable<EventRecord> $records The event stream to replay, ordered by sequence number.
* @param Snapshot|null $snapshot Optional snapshot to restore from before replay.
* @return static The reconstituted aggregate.
* @throws MissingIdentityProperty When the property referenced by <code>identityProperty()</code> does not exist.
*/
public static function reconstitute(Identity $identity, iterable $records, ?Snapshot $snapshot = null): static;
/**
* Returns the aggregate state to persist in a snapshot.
*
* <p>The default implementation provided by {@see EventSourcingRootBehavior} returns all object
* properties except <code>recordedEvents</code> (transient buffer) and <code>sequenceNumber</code>
* (already a first-class field on the snapshot). Override to exclude infrastructure properties
* (loggers, caches, etc.) or to include only a curated subset of state.</p>
*
* @return array<string, mixed> Keyed by property name.
*/
public function snapshotState(): array;
/**
* Restores aggregate state from the given snapshot.
*
* <p>Implementations read {@see Snapshot::aggregateState()} and copy the relevant fields into
* their own properties. The sequence number is applied automatically by
* <code>reconstitute()</code>; implementations should not touch it.</p>
*
* @param Snapshot $snapshot The snapshot to restore from.
*/
public function applySnapshot(Snapshot $snapshot): void;
}