2017-02-19 27 views
1

Я реализую приложение PHP с CQRS.Как получить вновь созданный объект с помощью асинхронной команды (CQRS) в том же процессе php?

Скажем, у меня есть CreateOrderCommand и когда я

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

CommandBus теперь просто передать команду к правильному CreateOrderCommandHandler классу так же легко, как:

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); 
    } 
} 

Все ок.

Но обработка недействительна, поэтому я ничего не знаю о прогрессе или результате. Что я могу сделать, чтобы иметь возможность, например, пожар CreateOrderCommand, а затем в том же процессе получить вновь созданный идентификатор объекта (возможно, с некоторым пассивным ожиданием его создания)?

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; 
} 

И сблизиться, что CQRS может обеспечить, команды шина должна быть в состоянии иметь RabbitMqCommandBus реализацию, только сериализующую команды и отправляет его в очередь кролика.

Таким образом, процесс, который, наконец, обрабатывает команду, может быть некоторым бегущим потребителем, и здесь требуется какая-то связь между процессами - чтобы как-то сообщить об этом пользовательскому процессу от потребителя, что это делается (с некоторой информацией, например id нового объекта).

Я знаю, что есть решение с GUID - я могу отметить команду с GUID. Но тогда что:

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

НЕКОТОРАЯ РЕАЛИЗАЦИЯ должен сделать некоторые проверки событий (так мне нужно реализовать некоторую систему событий тоже) по команде с конкретным GUID, чтобы иметь возможность, например, эхо прогресса или OrderCreatedEvent просто вернуть его ID, который я получаю от этого события. Потребительский процесс, который асинхронно обрабатывает команду, может, например, передавать события кролику, а пользовательский клиент будет брать их и делать правильный ответ (эхо-прогресс, возвращать вновь созданный объект, например).

Но как это сделать? И решение с GUID является единственным? Каковы приемлемые варианты решений? Или, какой момент мне не хватает? :)

+1

CQRS лучше всего работает с DDD и Event Sourcing. Вы пробовали их? –

ответ

1

Самое легкое решение для получения информации об идентификаторе созданного агрегата/объекта - это добавить его в команду. Таким образом, интерфейс генерирует идентификатор и передает его с данными. Но чтобы это решение работало, вам нужно использовать uuid вместо обычных целых чисел базы данных, иначе вы можете найти дубликаты идентификаторов на стороне db.
Если команда является асинхронной и выполняет такие трудоемкие действия, вы можете точно публиковать события у потребителя. Таким образом, клиент через. websockets получает информацию в режиме реального времени. Или спросите бэкэнд о существовании заказа с идентификатором из команды, время от времени и когда ресурс существует, перенаправьте его на нужную страницу.

+0

Мне как-то не нравится идея, что служба, которая что-то делает и должна использовать команду для создания новой сущности (как раз кстати), должна заботиться о генерации идентификатора этого объекта. Как я показал в своем примере, мне бы хотелось, чтобы каждая команда была создана с помощью GUID, и я могу получить ее оттуда. Тогда у меня есть команда id, и я знаю, что слушать. Но как _exactly_ можно прослушивать в моем примере? Это должно быть блокирование, поэтому нет активных вопросов о существовании. – Tom

+0

Websocket звучит хорошо, я нашел React PHP http: // reactphp.org /, но я до сих пор не понимаю, как применить к моему примеру. Об этом мало что касается поиска в Google. Это займет некоторое время. Было бы хорошо, если бы кто-нибудь мог это объяснить в ответ. :) – Tom

+0

Почему вы думаете, что служба должна отвечать за генерирование id? Вы все равно предоставляете его пользователю, это не скрытое значение, о котором пользователь не должен знать. – Dariss