Author: Alexander Miertsch (contact@prooph.de)
Example #1
0
 /**
  * @param EventStore $eventStore
  * @param AggregateType $aggregateType
  * @param AggregateTranslator $aggregateTranslator
  * @param StreamStrategy|null $streamStrategy
  */
 public function __construct(EventStore $eventStore, AggregateType $aggregateType, AggregateTranslator $aggregateTranslator, StreamStrategy $streamStrategy = null)
 {
     $this->eventStore = $eventStore;
     $this->eventStore->getActionEventEmitter()->attachListener('commit.pre', $this);
     $this->aggregateType = $aggregateType;
     $this->aggregateTranslator = $aggregateTranslator;
     if (null === $streamStrategy) {
         $streamStrategy = new SingleStreamStrategy($this->eventStore);
     }
     $this->streamStrategy = $streamStrategy;
 }
 /**
  * @param array $data
  * @return array
  */
 public function run(array $data)
 {
     switch ($data['adapter']) {
         case 'mysql':
             $connection = DriverManager::getConnection($data['options']);
             $connection->executeQuery('DROP TABLE IF EXISTS user_stream');
             $adapter = new DoctrineEventStoreAdapter($connection, new FQCNMessageFactory(), new NoOpMessageConverter(), new JsonPayloadSerializer());
             break;
         case 'postgres':
             $connection = DriverManager::getConnection($data['options']);
             $connection->executeQuery('DROP TABLE IF EXISTS user_stream');
             $adapter = new DoctrineEventStoreAdapter($connection, new FQCNMessageFactory(), new NoOpMessageConverter(), new JsonPayloadSerializer());
             break;
         case 'mongodb':
             $connection = new \MongoClient($data['options']['server']);
             $connection->selectDB('event_store_adapter_benchmarks')->selectCollection('user_stream')->drop();
             $adapter = new MongoDbEventStoreAdapter(new FQCNMessageFactory(), new NoOpMessageConverter(), $connection, $data['options']['db_name']);
             break;
         default:
             throw new \InvalidArgumentException('invalid adapter given');
             break;
     }
     $eventStore = new EventStore($adapter, new ProophActionEventEmitter());
     $result = [];
     foreach ($data['batchSizes'] as $batchSize) {
         for ($i = 0; $i < $this->repeats; $i++) {
             $events = [];
             $start = microtime(true);
             for ($b = 1; $b <= $batchSize * 2; $b++) {
                 $v1 = $b;
                 $b++;
                 $v2 = $b;
                 $events[] = UserCreated::with(['name' => 'Max Mustermann ' . $i . '-' . $b, 'email' => 'contact' . $i . '-' . $b . '@prooph.de'], $v1);
                 $events[] = UsernameChanged::with(['name' => 'John Doe ' . $i . '-' . $b], $v2);
             }
             $eventStore->beginTransaction();
             $eventStore->create(new Stream(new StreamName('user_stream'), new \ArrayIterator($events)));
             $eventStore->commit();
             $end = microtime(true);
             if ($connection instanceof Connection) {
                 $connection->executeQuery('DROP TABLE IF EXISTS user_stream');
             } else {
                 $connection->selectDB('event_store_adapter_benchmarks')->selectCollection('user_stream')->drop();
             }
             $diff = $end - $start;
             $result[$data['adapter'] . ' with batch size ' . $batchSize] = $diff;
         }
     }
     return $result;
 }
 /**
  * @test
  */
 public function it_translates_aggregate_back_and_forth()
 {
     $this->eventStore->beginTransaction();
     $user = User::nameNew('John Doe');
     $this->repository->addAggregateRoot($user);
     $this->eventStore->commit();
     $this->eventStore->beginTransaction();
     //Simulate a normal program flow by fetching the AR before modifying it
     $user = $this->repository->getAggregateRoot($user->id());
     $user->changeName('Max Mustermann');
     $this->eventStore->commit();
     $this->resetRepository();
     $loadedUser = $this->repository->getAggregateRoot($user->id());
     $this->assertEquals('Max Mustermann', $loadedUser->name());
     return $loadedUser;
 }
Example #4
0
 /**
  * Save a Chapter event to the chapter history.
  *
  * @param Message $domainMessage
  * @throws \Prooph\Done\Shared\Exception\StoryName
  * @throws \Exception
  */
 public function logChapterEvent(Message $domainMessage)
 {
     $storyName = Metadata::getStoryNameFromMessage($domainMessage);
     if (!isset($this->storyTellers[$storyName->toString()])) {
         throw Exception\StoryName::isNotLinkedWithStoryTeller($storyName);
     }
     $storyTeller = $this->storyTellers[$storyName->toString()];
     try {
         $this->eventStore->beginTransaction();
         $storyTeller($domainMessage);
         $this->eventStore->commit();
     } catch (\Exception $ex) {
         $this->eventStore->rollback();
         throw $ex;
     }
 }
Example #5
0
 private function rollbackTransaction()
 {
     if ($this->inTransaction) {
         $this->eventStore->rollback();
     }
     $this->inTransaction = false;
     $this->checkMessageQueue();
 }
 /**
  * Check if exception an exception was thrown. If so rollback event store transaction
  * otherwise commit it.
  *
  * @param ActionEvent $actionEvent
  */
 public function onFinalize(ActionEvent $actionEvent)
 {
     if ($this->eventStore->isInTransaction()) {
         if ($actionEvent->getParam(CommandBus::EVENT_PARAM_EXCEPTION)) {
             $this->eventStore->rollback();
         } else {
             $this->eventStore->commit();
         }
     }
     $this->currentCommand = null;
 }
 /**
  * @param string $aggregateId
  * @return null|object
  */
 protected function loadFromSnapshotStore($aggregateId)
 {
     $snapshot = $this->snapshotStore->get($this->aggregateType, $aggregateId);
     if (!$snapshot) {
         return;
     }
     $aggregateRoot = $snapshot->aggregateRoot();
     $streamName = $this->determineStreamName($aggregateId);
     $streamEvents = $this->eventStore->loadEventsByMetadataFrom($streamName, ['aggregate_type' => $this->aggregateType->toString(), 'aggregate_id' => $aggregateId], $snapshot->lastVersion() + 1);
     if (!$streamEvents->valid()) {
         return $aggregateRoot;
     }
     $this->aggregateTranslator->replayStreamEvents($aggregateRoot, $streamEvents);
     return $aggregateRoot;
 }
 /**
  * @test
  */
 public function it_publishes_take_snapshot_commands_by_event_name()
 {
     $this->eventStore->beginTransaction();
     $user = User::create('Alex', '*****@*****.**');
     $this->repository->addAggregateRoot($user);
     $this->eventStore->commit();
     $this->eventStore->beginTransaction();
     $user = $this->repository->getAggregateRoot($user->getId()->toString());
     $user->changeName('Jim');
     $this->eventStore->commit();
     $this->eventStore->beginTransaction();
     $eventWithoutMetadata1 = UsernameChanged::with(['new_name' => 'John Doe'], 5);
     $this->eventStore->appendTo(new StreamName('event_stream'), new \ArrayIterator([$eventWithoutMetadata1]));
     $this->eventStore->commit();
     $this->assertCount(1, $this->result);
     $this->assertArrayHasKey('aggregate_type', $this->result[0]);
     $this->assertArrayHasKey('aggregate_id', $this->result[0]);
     $this->assertEquals(User::class, $this->result[0]['aggregate_type']);
 }
Example #9
0
 /**
  * @test
  * @expectedException Prooph\EventStore\Exception\StreamNotFoundException
  */
 public function it_throws_stream_not_found_exception_if_adapter_loads_nothing()
 {
     $stream = $this->getTestStream();
     $adapter = $this->prophesize(Adapter::class);
     $eventStore = new EventStore($adapter->reveal(), new ProophActionEventEmitter());
     $eventStore->beginTransaction();
     $eventStore->create($stream);
     $eventStore->commit();
     $eventStore->load($stream->streamName());
 }
Example #10
0
         */
        public function get(Uuid $uuid)
        {
            return $this->getAggregateRoot($uuid->toString());
        }
    }
}
namespace {
    //Set up an EventStore with an InMemoryAdapter (Only useful for testing, persistent adapters for ProophEventStore are available)
    use My\Infrastructure\UserRepositoryImpl;
    use My\Model\User;
    use Prooph\Common\Event\ActionEvent;
    use Prooph\Common\Event\ProophActionEventEmitter;
    use Prooph\EventStore\Adapter\InMemoryAdapter;
    use Prooph\EventStore\EventStore;
    $eventStore = new EventStore(new InMemoryAdapter(), new ProophActionEventEmitter());
    //Now we set up our user repository and inject the EventStore
    //Normally this should be done in an IoC-Container and the receiver of the repository should require My\Model\UserRepository
    $userRepository = new UserRepositoryImpl($eventStore);
    //Ok lets start a new transaction and create a user
    $eventStore->beginTransaction();
    $user = User::nameNew('John Doe');
    $userRepository->add($user);
    //Before we commit the transaction let's attach a listener to check that the UserWasCreated event is published after commit
    $eventStore->getActionEventEmitter()->attachListener('commit.post', function (ActionEvent $event) {
        foreach ($event->getParam('recordedEvents', new \ArrayIterator()) as $streamEvent) {
            echo sprintf("Event with name %s was recorded. It occurred on %s UTC /// ", $streamEvent->messageName(), $streamEvent->createdAt()->format('Y-m-d H:i:s'));
        }
    });
    $eventStore->commit();
    $userId = $user->userId();
 * file that was distributed with this source code.
 */
require __DIR__ . '/../vendor/autoload.php';
use Prooph\Common\Event\ProophActionEventEmitter;
use Prooph\Common\Messaging\FQCNMessageFactory;
use Prooph\Common\Messaging\NoOpMessageConverter;
use Prooph\EventStore\Adapter\Flywheel\FlywheelEventStoreAdapter;
use Prooph\EventStore\EventStore;
use Prooph\EventStore\Stream\Stream;
use Prooph\EventStore\Stream\StreamName;
use ProophTest\EventStore\Mock\UserCreated;
use ProophTest\EventStore\Mock\UsernameChanged;
$rootDir = __DIR__ . '/event_store';
$adapter = new FlywheelEventStoreAdapter($rootDir, new FQCNMessageFactory(), new NoOpMessageConverter());
$actionEmitter = new ProophActionEventEmitter();
$eventStore = new EventStore($adapter, $actionEmitter);
$streamName = new StreamName('event_stream');
$stream = new Stream($streamName, new \ArrayIterator([]));
//
// Persist some events in the event store
//
$eventStore->beginTransaction();
$eventStore->create($stream);
$eventStore->appendTo($streamName, new \ArrayIterator([UserCreated::with(['name' => 'Max Mustermann'], 1)->withAddedMetadata('tag', 'person'), UsernameChanged::with(['name' => 'John Doe'], 2)->withAddedMetadata('tag', 'person')]));
$eventStore->commit();
//
// Load all the stored events
//
$persistedEventStream = $eventStore->load($streamName);
foreach ($persistedEventStream->streamEvents() as $event) {
    echo $event->payload()['name'] . PHP_EOL;
 /**
  * @param string $processId
  * @param int $minVersion
  * @return DomainEvent[]
  */
 public function getStreamOfProcess($processId, $minVersion = 0)
 {
     Assertion::uuid($processId);
     return $this->eventStore->loadEventsByMetadataFrom(new StreamName('prooph_processing_stream'), ['aggregate_id' => $processId], $minVersion);
 }
Example #13
0
 /**
  * @return EventStore
  */
 protected function getOtherMachineEventStore()
 {
     if (is_null($this->otherMachineEventStore)) {
         $inMemoryAdapter = new InMemoryAdapter();
         $config = new Configuration();
         $config->setAdapter($inMemoryAdapter);
         $this->otherMachineEventStore = new EventStore($config);
         $this->otherMachineEventStore->getActionEventDispatcher()->attachListener("commit.post", function (PostCommitEvent $postCommitEvent) {
             $this->otherMachineLastPostCommitEvent = $postCommitEvent;
             foreach ($postCommitEvent->getRecordedEvents() as $event) {
                 $this->otherMachineEventNameLog[] = $event->messageName();
             }
         });
         $this->otherMachineEventStore->beginTransaction();
         $this->otherMachineEventStore->create(new Stream(new StreamName('prooph_processing_stream'), []));
         $this->otherMachineEventStore->commit();
     }
     return $this->otherMachineEventStore;
 }
 /**
  * @param AggregateType $aggregateType
  * @param string $aggregateId
  * @param null|int $minVersion
  * @return Message[]
  */
 public function read(AggregateType $aggregateType, $aggregateId, $minVersion = null)
 {
     $stream = $this->eventStore->load($this->buildStreamName($aggregateType, $aggregateId), $minVersion);
     return $stream->streamEvents();
 }
 /**
  * @param EventStore $eventStore
  * @return void
  */
 public function setUp(EventStore $eventStore)
 {
     $eventStore->getActionEventEmitter()->attachListener('commit.post', [$this, "onPostCommit"]);
 }
Example #16
0
 /**
  * @param EventStore $eventStore
  * @return void
  */
 public function setUp(EventStore $eventStore)
 {
     $eventStore->getActionEventEmitter()->attachListener('commit.post', [$this, 'onEventStoreCommitPost'], -1000);
 }
 /**
  * @param EventStore $eventStore
  */
 public function setUp(EventStore $eventStore)
 {
     $eventEmitter = $eventStore->getActionEventEmitter();
     $eventEmitter->attachListener('create.pre', [$this, 'onEventStoreCreateStream'], -1000);
     $eventEmitter->attachListener('appendTo.pre', [$this, 'onEventStoreAppendToStream'], -1000);
 }
Example #18
0
 /**
  * @param AggregateType $repositoryAggregateType
  * @param string $aggregateId
  * @param null|int $minVersion
  * @return Message[]
  */
 public function read(AggregateType $repositoryAggregateType, $aggregateId, $minVersion = null)
 {
     Assertion::string($aggregateId, 'AggregateId needs to be string');
     return $this->eventStore->loadEventsByMetadataFrom($this->streamName, ['aggregate_id' => $aggregateId], $minVersion);
 }
 /**
  * @param ProcessId $processId
  * @param int $minVersion
  * @return DomainEvent[]
  */
 public function getStreamOfProcess(ProcessId $processId, $minVersion = 0)
 {
     return $this->eventStore->loadEventsByMetadataFrom(new StreamName('prooph_processing_stream'), ['aggregate_id' => $processId->toString()], $minVersion);
 }