neos / contentrepository-development-collection

Work in Progress on the Event Sourced Content Repository as installable set of packages
4 stars 9 forks source link

Move initiating user identifier and recorded date to event metadata #196

Open bwaidelich opened 3 years ago

bwaidelich commented 3 years ago

Two problems:

  1. The initiating user field that was added with #188 has to be implemented and specified in all commands and events* thus makes it quite tedious and error prone to work with
  2. The recorded_at timestamp of the RawEvent is currently the only option to determine the last updated time of a node. But it is change whenever a content stream is rebased

Suggestion:

Move initiatingUserIdentifier to the event metadata and add another metadata for the timestamp (e.g. initiatingTimestamp) and add those when publishing new events (and copy them when rebasing).

Implementation

Maybe we can extend the command handlers such that they can be created in a certain context, e.g.:

$this->nodeAggregateCommandHandler->forUser($currentUserId)->handleSomeCommand($command);

and in the command handler s.th. along the lines of:

class SomeCommandHandler {
  private UserIdentifier $userId;
  private Now $now;
  public function __construct(Now $now) {
    $this->userId = UserIdentifier::forSystemUser();
    $this->now = $now;
  }

  public function forUser(UserIdentifier $userId): self
  {
    if ($userId->equals($this->userId)) {
      return $this;
    }
    $newInstance = clone $this;
    $newInstance->userId = $userId;
    return $newInstance;
  }

  // ...

   private function addMetadataBeforePublishing(DomainEvents $events): DomainEvents
   {
      $metadata = [
          'initiatingUserIdentifier' => $this->userId->toString(),
          'initiatingTimestamp' => $this->now->format(\DateTimeInterface::ATOM),
      ];
      return $events->map(fn(DomainEventInterface $event) => DecoratedEvent::addMetadata($event, $metadata));
   }
}

* We forgot to implement it in NodeAggregateTypeWasChanged