Цель: научиться локально имплементировать паттерн Saga в рамках известной предметной области.
Смысл: для распределенных систем с микросервисной архитектурой (в частности реализацией подхода Database per Service) характерны проблемы атомарности и изолированности транзакций, состоящих из операций, выполняемых различными микросервисами. Паттерн Saga является классическим подходом к проектированию распределенных транзакций.
Предполагается, что команды в рассматриваемой предметной области выполняются различными микросервисами. В этом случае макрокоманды можно считать распределенными транзакциями.
Задачи:
в качестве предметной области использовать “игру” SpaceBattle
спроектировать макрокоманду SagaCommand для представления транзакций
прямое и компенсирующее действие представляются в виде команд (реализаций ICommand)
в конструкторе данная макрокоманда принимает упорядоченную коллекцию пар (объектов Tuple<ICommand, ICommand>)
идея: в ходе выполнения макрокоманды (SagaCommand) при возникновении исключения в команде, реализующей прямое действие, начинают выполняться в обратном порядке предыдущие команды, реализующие компенсирующее действие
реализовать стратегию IoC для создания макрокоманды SagaCommand, которая строит макрокоманду, получая на вход списки имен команд, характеризующих прямые действия, а также объект (IUObject), для которого макрокоманда будет выполняться (стратегия возвращает ссылку на объект макрокоманды SagaCommand, который проинициализирован через конструктор)
подсказка: пример входа стратегии (“MoveCommand“, “WasteFuelCommand“, uobject); внутри самой стратегии происходит получение команд из контейнера IoC по имени; при этом договоримся, что зная имя прямой команды, реализующей прямое действие, мы всегда можем также получить из контейнера IoC команду для реализации компенсирующего действия
стратегия должна уметь создавать любые саги (SagaCommand) для любых универсальных объектов (IUObject)
используя разработанную стратегию реализовать транзакцию из двух операций: движение + уменьшение топлива (напоминание: операции представляются в виде команд)
В ходе выполнения ЛР может потребоваться создание новых команд (изменение топлива у объекта должно реализовываться в виде отдельной команды), а также проектирование соответствующих абстракций (интерфейсов, например интерфейс, позволяющий изменять топливо у объекта).
Должен обязательно быть предусмотрен тест, в котором выполнение второй операции завершается с ошибкой. Необходимо проверить, чтобы в этом случае выполнялась компенсирующее действие для первой операции.
Критерии приема работы:
Для упрощения приема и сдачи работ рекомендуется предоставлять преподавателям репозиторий с настроенным CI.