2

I am implementing PHP application with CQRS.

Let's say I have CreateOrderCommand and when I do

$command = new CreateOrderCommand(/** some data**/);
$this->commandBus->handle($command);

CommandBus now just pass command to proper CreateOrderCommandHandler class as easily as:

abstract class SimpleCommandBus implements CommandBus
{
    /** @var ICommandHandlerLocator */
    protected $locator;

    /**
     * Executes command
     *
     * @param Command $command
     */
    public function handle(Command $command)
    {
        $handler = $this->locator->getCommandHandler($command);
        $handler->handle($command);
    }
}

Everything ok.

But handling is void method, so I do not know anything about progress or result. What can I do to be able to for example fire CreateOrderCommand and then in same process acquire newly created entity id (probably with some passive waiting for its creation)?

public function createNewOrder(/** some data**/){
  $command = new CreateOrderCommand(/** some data**/);
  $this->commandBus->handle($command);
  // something that will wait until command is done
  $createdOrder = // some magic that retrieves some adress to result data
  return $createdOrder;
}

And to get closer of what CQRS can provide, command bus should be able to have RabbitMqCommandBus implementation that just serializes command and sends it to rabbit queue.

So, then the process that finally handles command might be some running consumer and some kind of communication between processes is needed here - to be able to somehow inform original user process from consumer, that it is done (with some information, for example id of new entity).

I know that there is solution with GUID - I could mark command with GUID. But then what:

public function createNewOrder(/** some data**/){
  $command = new CreateOrderCommand(/** some data**/);
  $this->commandBus->handle($command);
  $guid = $command->getGuid();
  // SOME IMPLEMENTATION
  return $createdOrder;
}

SOME IMPLEMENTATION should do some checking of events (so I need to implement some event system too) on command with specific GUID, to be able to for example echo progress or on OrderCreatedEvent just return it's ID that I would get from that event. Consumer process that asynchronously handles command might for example feed events to rabbit and user client would taking them and do proper response (echo progress, return newly created entity for example).

But how to do that? And is solution with GUID the only one? What are acceptable implementations of solutions? Or, what point am I missing? :)

Tom
  • 189
  • 1
  • 12

1 Answers1

1

The easiest solution to get information about id of created aggregate/entity is to add it to the command. So the frontend generates the id and pass it with the data. But to make this solution works, you need to make use of uuid instead of normal database integers, otherwise you may find yourself duplicating identifiers on the db side.
If the command is async and perform so time consuming actions, you can for sure publish events from the consumer. So the client via.e.g. websockets receives the informations in real time. Or ask the backend about existance of the order with the id from the command, from time to time and when the resource exists, redirect him to the right page.

Dariss
  • 1,258
  • 1
  • 12
  • 27
  • I somehow do not like the idea, that service that do something and needs to use command to create new entity (just by the way), should be taking care of generating id of that entity. As I showed in my example, i would rather like that every command is created with it's GUID and I can get it then from it. Then i have id of command and I know what to listen for. But how _exactly_ can be listening implemented in my example? It should be blocking, so no active asking about existence. – Tom Feb 19 '17 at 15:19
  • Websocket sounds good, I found React PHP http://reactphp.org/, but I still don't get how to apply to my example. There is so little about that when I search on google. It will take some time. Would be fine if somebody could elaborate that in answer. :) – Tom Feb 19 '17 at 15:24
  • Why do you think that service should be responsible for generating id? You expose it to user anyways, it's not an hidden value that user should not be aware of. – Dariss Feb 20 '17 at 04:54
  • About the websockets. Take a look on publish subscribe pattern implementations. – Dariss Feb 20 '17 at 04:55