Ejemplo n.º 1
0
 /**
  * @return MigrationsService
  */
 protected function createServiceWithMigrations()
 {
     $this->migrationsDirectory = __DIR__ . '/../../../Fixtures/Migrations';
     require_once __DIR__ . '/../../../Fixtures/BlogEventSourced.php';
     // simulate an application and aggregate version state
     $currentApplicationVersion = Version::fromString('0.1.0');
     VersionManager::setCurrentApplicationVersion($currentApplicationVersion);
     VersionManager::persistVersionOfClass(PostEventSourced::class, $currentApplicationVersion);
     VersionManager::persistVersionOfClass(\BlogEventSourced::class, $currentApplicationVersion);
     // creating migration store
     $aggregates = [PostEventSourced::class, \BlogEventSourced::class];
     $migratorStore = new InMemoryMigrationStore();
     $migratorStore->persist(new Migration($aggregates, $currentApplicationVersion, new \DateTime()));
     // creating event store
     $eventStore = new InMemoryEventStore();
     // add the event store flow
     $postId1 = PostId::fromNative(md5(rand()));
     $postEventStream1 = new EventStream($this->streamName(PostEventSourced::class), $postId1, [new PostWasCreated($postId1, 'Best restaurants in barcelona', 'empty'), new PostTitleWasChanged($postId1, 'Best cuban restaurants in barcelona')]);
     $postId2 = PostId::fromNative(md5(rand()));
     $postEventStream2 = new EventStream($this->streamName(PostEventSourced::class), $postId2, [new PostWasCreated($postId2, 'Best things to do with children in barcelona', 'empty'), new PostTitleWasChanged($postId2, 'Things to do with children in barcelona this weekend')]);
     $eventStore->persist($postEventStream1, $currentApplicationVersion, $currentApplicationVersion);
     $eventStore->persist($postEventStream2, $currentApplicationVersion, $currentApplicationVersion);
     // fake BlogEventSourced event stream
     $postId2 = PostId::fromNative(md5(rand()));
     $postEventStream2 = new EventStream($this->streamName(\BlogEventSourced::class), $postId2, [new PostWasCreated($postId2, 'Blog', 'empty'), new PostTitleWasChanged($postId2, 'new title')]);
     $eventStore->persist($postEventStream2, $currentApplicationVersion, $currentApplicationVersion);
     return new MigrationsService(new Migrator($this->getClassMetadataFactory(), $migratorStore, $eventStore, $this->migrationsDirectory));
 }
Ejemplo n.º 2
0
 /**
  * Test Generate method.
  */
 public function testGenerate()
 {
     require_once __DIR__ . '/../../../Fixtures/BlogEventSourced.php';
     $this->given($generator = $this->createGenerator())->and($aggregateClass = PostEventSourced::class)->and($version = VersionManager::versionOfClass($aggregateClass))->when($generator->generate($aggregateClass, $version))->then()->boolean(file_exists($this->getMigratorFileName($aggregateClass, $version)))->isTrue()->and()->exception(function () use($generator, $aggregateClass, $version) {
         $generator->generate($aggregateClass, $version);
     })->isInstanceOf(\RuntimeException::class);
     $this->given($generator = $this->createGenerator())->and($aggregateClass = \BlogEventSourced::class)->and($version = VersionManager::versionOfClass($aggregateClass))->when($generator->generate($aggregateClass, $version))->then()->boolean(file_exists($this->getMigratorFileName($aggregateClass, $version)))->isTrue()->boolean($generator->existsDirectory($version))->isTrue();
 }
Ejemplo n.º 3
0
 /**
  * Test migrate method.
  */
 public function testMigrate()
 {
     $this->migrationsDirectory = __DIR__ . '/../../Fixtures/Migrations';
     require_once __DIR__ . '/../../Fixtures/BlogEventSourced.php';
     // simulate an application and aggregate version state
     $currentApplicationVersion = Version::fromString('0.1.0');
     $aggregateVersion = Version::fromString('0.1.0');
     VersionManager::setCurrentApplicationVersion($currentApplicationVersion);
     VersionManager::persistVersionOfClass(PostEventSourced::class, $aggregateVersion);
     VersionManager::persistVersionOfClass(\BlogEventSourced::class, $aggregateVersion);
     // creating migration store
     $aggregates = [PostEventSourced::class, \BlogEventSourced::class];
     $migratorStore = new InMemoryMigrationStore();
     $migratorStore->persist(new Migration($aggregates, $aggregateVersion, new \DateTime()));
     // creating event store
     $eventStore = new InMemoryEventStore();
     // add the event store flow
     $postId1 = PostId::fromNative(md5(rand()));
     $postEventStream1 = new EventStream($this->streamName(PostEventSourced::class), $postId1, [new PostWasCreated($postId1, 'Best restaurants in barcelona', 'empty'), new PostTitleWasChanged($postId1, 'Best cuban restaurants in barcelona')]);
     $postId2 = PostId::fromNative(md5(rand()));
     $postEventStream2 = new EventStream($this->streamName(PostEventSourced::class), $postId2, [new PostWasCreated($postId2, 'Best things to do with children in barcelona', 'empty'), new PostTitleWasChanged($postId2, 'Things to do with children in barcelona this weekend')]);
     $eventStore->persist($postEventStream1, $aggregateVersion, $currentApplicationVersion);
     $eventStore->persist($postEventStream2, $aggregateVersion, $currentApplicationVersion);
     // fake BlogEventSourced event stream
     $postId3 = PostId::fromNative(md5(rand()));
     $postEventStream2 = new EventStream($this->streamName(\BlogEventSourced::class), $postId3, []);
     $eventStore->persist($postEventStream2, $aggregateVersion, $currentApplicationVersion);
     // creating snapshot store
     $snapshotStore = new InMemorySnapshotStore();
     // creating the migrator
     $migrator = new MigratorWithSnapshot($this->getClassMetadataFactory(), $migratorStore, $eventStore, $snapshotStore, $this->migrationsDirectory);
     $emptyMigrator = new MigratorWithSnapshot($this->getClassMetadataFactory(), $migratorStore, $eventStore, $snapshotStore, __DIR__ . '/../../Fixtures/EmptyMigrations');
     $this->given($result = $emptyMigrator->migrate())->then()->boolean($result)->isFalse();
     $this->given($status = $migrator->status())->and($nextVersion = $status->nextAvailableVersion())->then()->boolean($migratorStore->hasMigration($nextVersion))->isFalse()->variable($snapshotStore->load('post_event_sourced', $postId1, $aggregateVersion, $currentApplicationVersion))->isNull()->and()->when($result = $migrator->migrate())->and(VersionManager::setCurrentApplicationVersion($migratorStore->getLast()->version()))->then()->boolean($migratorStore->hasMigration($nextVersion))->isTrue()->boolean($result)->isTrue()->variable($snapshotStore->load('post_event_sourced', $postId1, $aggregateVersion, $nextVersion))->isNotNull()->variable($snapshotStore->load('post_event_sourced', $postId2, $aggregateVersion, $nextVersion))->isNotNull()->and()->exception(function () use($migrator) {
         // because the V1_0_0\BlogEventSourcedMigration class return an invalid stream
         $migrator->migrate();
     })->isInstanceOf(\RuntimeException::class);
 }
 /**
  * Save the aggregate history.
  *
  * @param EventSourcedAggregateRootInterface $aggregateRoot
  */
 protected function saveHistory(EventSourcedAggregateRootInterface $aggregateRoot)
 {
     $recordedEvents = $aggregateRoot->recordedEvents();
     if (count($recordedEvents) > 0) {
         DomainEventPublisher::publish(new PrePersistEvent($aggregateRoot));
         // clear events
         $aggregateRoot->clearEvents();
         // create the eventStream and persist it
         $applicationVersion = VersionManager::currentApplicationVersion();
         $eventStream = new EventStream($this->streamName(), $aggregateRoot->id(), $recordedEvents);
         $this->eventStore->persist($eventStream, $aggregateRoot->version(), $applicationVersion);
         DomainEventPublisher::publish(new PostPersistEvent($aggregateRoot));
     }
 }
 /**
  * Load a aggregate snapshot from the storage.
  *
  * @param IdInterface $id
  *
  * @return Snapshot
  */
 protected function loadSnapshot(IdInterface $id)
 {
     $applicationVersion = VersionManager::currentApplicationVersion();
     $aggregateVersion = VersionManager::versionOfClass($this->aggregateClassName, $applicationVersion);
     return $this->snapshotStore->load($this->streamName(), $id, $aggregateVersion, $applicationVersion);
 }
Ejemplo n.º 6
0
 /**
  * @return bool
  */
 public function migrate()
 {
     $nextMigration = $this->migrationManager()->nextMigrationToExecute();
     $currentApplicationVersion = VersionManager::currentApplicationVersion();
     if ($nextMigration !== null) {
         foreach ($nextMigration->aggregates() as $aggregateMigrationClass) {
             // -- start current application context --
             /** @var MigrationInterface $migrationClass */
             $migrationClass = new $aggregateMigrationClass();
             $aggregateClassName = $migrationClass->aggregateClassName();
             $currentAggregateVersion = VersionManager::versionOfClass($aggregateClassName, $currentApplicationVersion);
             // get all event streams for this aggregate class name
             $eventStreams = $this->eventStore->loadAll($this->streamName($aggregateClassName), $currentAggregateVersion, $currentApplicationVersion);
             // -- end current application context --
             // -- start new version context --
             $nextApplicationVersion = $nextMigration->version();
             // iterate for every aggregateRoot event stream
             foreach ($eventStreams as $aggregateRootEventStream) {
                 // migrate the current aggregate event stream
                 $newAggregateRootEventStream = $migrationClass->migrate($aggregateRootEventStream);
                 if ($newAggregateRootEventStream === null || $newAggregateRootEventStream !== null && !$newAggregateRootEventStream instanceof EventStream) {
                     throw new \RuntimeException(sprintf('Invalid migration class %s. The migration method should return the new EventStream', $aggregateMigrationClass));
                 }
                 // calculate the new version for every event
                 $pathVersion = 0;
                 foreach ($newAggregateRootEventStream->events() as $event) {
                     $event->setVersion(++$pathVersion);
                 }
                 // and the new version for this aggregateRoot
                 $newAggregateRootVersion = Version::fromString($nextMigration->version()->__toString());
                 $newAggregateRootVersion->setPatch($pathVersion);
                 // persist the new event stream for this aggregateRoot.
                 $this->migrateAggregateRoot($aggregateClassName, $newAggregateRootEventStream, $newAggregateRootVersion, $nextApplicationVersion);
             }
             // persist the new version of this aggregate class in the VersionManager
             VersionManager::persistVersionOfClass($aggregateClassName, $nextMigration->version(), $nextApplicationVersion);
             // -- end new version context --
         }
         // persist the new migration in the store
         $this->migrationManager->persistMigration($nextMigration);
         return true;
     }
     return false;
 }
 /**
  * @param Snapshot $snapshot
  *
  * @return EventSourcedAggregateRootInterface
  */
 protected function snapshotToAggregateRoot(Snapshot $snapshot)
 {
     $applicationVersion = VersionManager::currentApplicationVersion();
     $history = $this->eventStore->load($this->streamName(), $snapshot->aggregateId(), $snapshot->version(), $applicationVersion);
     $aggregateRoot = $snapshot->aggregate();
     $aggregateRoot->setVersion($snapshot->version());
     $aggregateRoot->replay($history);
     return $aggregateRoot;
 }
Ejemplo n.º 8
0
 /**
  * Test setCurrentApplicationVersion method.
  */
 public function testSetCurrentApplicationVersion()
 {
     $this->given($applicationVersion = Version::fromString('3.2.0'))->and(VersionManager::setCurrentApplicationVersion($applicationVersion))->then()->object(VersionManager::currentApplicationVersion())->isEqualTo($applicationVersion);
 }
Ejemplo n.º 9
0
 /**
  * {@inheritdoc}
  */
 public function version()
 {
     if ($this->version === null) {
         $this->version = VersionManager::versionOf($this);
     }
     return $this->version;
 }