/** * @param Contract $aggregateRootType * @param EventStream $eventStream * * @throws \Exception */ public function append(Contract $aggregateRootType, EventStream $eventStream) { $statement = $this->insertQuery->prepare(); try { while ($eventStream->hasNext()) { $event = $eventStream->next(); $statement->bindValue(':aggregate_id', $event->aggregateRootIdentifier()->toString()); $statement->bindValue(':aggregate_type', $aggregateRootType->toString()); $statement->bindValue(':aggregate_version', $event->sequenceNumber()); $statement->bindValue(':event_id', $event->identifier()->toString()); $statement->bindValue(':event_payload', $this->eventSerializer->serializePayload($event)); $statement->bindValue(':event_payload_type', $event->payloadType()->toString()); $statement->bindValue(':event_metadata', $this->eventSerializer->serializeMetadata($event)); $statement->bindValue(':event_metadata_type', $event->metadataType()->toString()); $statement->execute(); $statement->closeCursor(); } } catch (\PDOException $exception) { // 23000 being the primary key duplicate entry error code. if ($exception->errorInfo[0] === '23000') { throw new ConcurrencyException('Concurrent modification detected.'); } throw $exception; } }
public function it_can_be_reconstituted_from_an_event_stream_history(EventStream $eventStream, Event $event) { $created = new Created(new UuidAggregateRootIdentifier()); $deleted = new Deleted(new UuidAggregateRootIdentifier()); $eventStream->hasNext()->willReturn(true, true, false); $eventStream->next()->willReturn($event); $event->sequenceNumber()->willReturn(1, 2); $event->payload()->willReturn($created, $deleted); $this->beConstructedThrough('loadFromHistory', [$eventStream]); $this->lastCommittedEventSequenceNumber()->shouldReturn(2); $this->isDeleted()->shouldReturn(true); }
public function it_can_append_events_to_the_store(Contract $aggregateType, EventStream $eventStream, $query, \PDOStatement $statement, Event $event, AggregateRootIdentifier $aggregateRootIdentifier, MessageIdentifier $messageIdentifier) { $query->prepare()->willReturn($statement); $eventStream->hasNext()->willReturn(true, false); $eventStream->next()->willReturn($event); $event->aggregateRootIdentifier()->willReturn($aggregateRootIdentifier); $event->sequenceNumber()->willReturn(Argument::any()); $event->identifier()->willReturn($messageIdentifier); $event->payloadType()->willReturn($aggregateType); $event->metadataType()->willReturn($aggregateType); $statement->bindValue(Argument::any(), Argument::any())->shouldBeCalled(); $statement->execute()->shouldBeCalled(); $statement->closeCursor()->shouldBeCalled(); $this->append($aggregateType, $eventStream); }
/** * @param Contract $aggregateType * @param EventStream $eventStream * * @throws \Exception */ public function append(Contract $aggregateType, EventStream $eventStream) { $statement = $this->insertQuery->prepare(); $commitIdentifier = CommitIdentifier::generate()->toString(); $committedAt = new \DateTime(); while ($eventStream->hasNext()) { $event = $eventStream->next(); $statement->bindValue(':aggregate_id', $event->aggregateRootIdentifier()->toString()); $statement->bindValue(':aggregate_type', $aggregateType->toString()); $statement->bindValue(':aggregate_version', $event->sequenceNumber()); $statement->bindValue(':event_id', $event->identifier()->toString()); $statement->bindValue(':event_payload', $this->eventSerializer->serializePayload($event)); $statement->bindValue(':event_payload_type', $event->payloadType()->toString()); $statement->bindValue(':event_metadata', $this->eventSerializer->serializeMetadata($event)); $statement->bindValue(':event_metadata_type', $event->metadataType()->toString()); $statement->bindValue(':commit_id', $commitIdentifier); $statement->bindValue(':committed_at', $committedAt->format('UTC')); $statement->execute(); $statement->closeCursor(); } }
/** * Roll-out all events to reconstitute the state of the aggregate. * * @param EventStream $eventStream * * @return static */ public static final function loadFromHistory(EventStream $eventStream) { $aggregate = new static(); while ($eventStream->hasNext()) { $aggregate->replayChange($eventStream->next()); } return $aggregate; }