Registration-service.md


Назначение

Получать запрос на регистрацию ЮР лица, формирование набора sag, их отправка на выполнение и ожидания их выполнения, осуществление ответа на gateway по факту выполнения или ошибки выполнения запроса.

Структура БД, в которой буду хранится данные о saga-х

Таблица описания sag

saga_uuid status type name saga_data
uuid numeric(3) numeric(3) varchar(64) json

Статус имеет следующие значения:

  • 0 (undefined)
  • 10 (created)
  • 20 (in progress)
  • 30 (completed)
  • 40 (fallback in process)
  • 50 (fallback completed)
  • 250 (fallback error)
  • 255 (error)

Поле type - указывает на тип операции, в которой задействована sag-а:

  • 0 (неизвестное)
  • 1 (регистрация ЮР лица)
  • 2 (создание счёта для ЮР лица)
  • 255 (ошибка)

При получении удачно выполненного event-а убираем его из списка. В случае, когда все event-ы выполнились, то меняем состояние саги с 20 на 30. В случае, если пришёл неудачный event, то меняем статус саги на с 20 на 255.

Поле saga_data хранит все данные, необходимые для его event-ов, а также данные, которые могут быть получены в результате выполнения event-а. Формат json поля следующий

{
  "name_1": ...,
  ...
  "name_n": ...
}

Таблица зависимостей sag

current_saga_uuid next_saga_uuid acc_connection_status
uuid uuid numeric(3)

Значения поля status:

  • 0 - неизвестный
  • 10 - ожидает выполнения текущей саги
  • 20 - выполнена удачно
  • 30 - откат
  • 255 - ошибка

Данная таблица отвечает за то, что отвечает за последовательность саг в запросе. Т.е. следующая сага не может быть запущена, пока в данное таблице не будет записей с uuid саги next_saga_uuid.

Таблица событий

event_uuid saga_uuid event_status event_name event_is_roll_back event_required_data event_result event_rollback_uuid
uuid uuid numeric(3) varchar(64) bool json json uuid

Содержит события саг. Статус имеет следующие значения:

  • 0 (undefined)
  • 10 (created)
  • 20 (in progress)
  • 30 (completed)
  • 40 (fallback in process)
  • 50 (fallback completed)
  • 250 (fallback error)
  • 255 (error)

В event_required_data лежит список необходимых полей для данного event-а. Формат следующий:

{
  [
    "name_1",
    ...
    "name_n"
  ]
}

Данные берутся из поля saga_data из данных sag-и.

В event_result лежит результат, полученный в ответ от другого сервиса.

event_rollback_uuid - поле, в котором лежит uuid того event-а, которое откатывает текущее.

Список запросов, необходимых для репозитория:

  • создание sag-и
  • удаление sag-и
  • обновление sag-и
  • создание event-a
  • удаление event-а
  • обновление event-а
  • создание связи между sag-ми
  • удаление связи между Sag-ми
  • обновление статуса связи между sag-ми
  • получение списка uuid всех event-ов sag-и
  • получение списка связей текущей Sag-и, где текущая sag-а зависит от других
  • получение списка связей текущей sag-и, где от текущей Sag-и зависят другие

Механизм sag

Список названий event-ов

  • Сервис счетов
    • Reserve account
    • Create acccount
    • Open account
  • Сервис пользователей
    • Create user
    • Add account to user

Список выполняемых операция и sag в них с event-ми

  • Create user (простая)
    • Зависимость sag: create_user
    • Saga №1: create_user
      • Event-ы: Create user
  • Add account to user (составная)
    • Зависимость sag: reserve_acc -> create_acc -> open_acc_and_add_to_user
    • Saga №1: reserve_acc
      • Event-ы: Reserve acc
    • Saga №2: create_acc
      • Event-ы: Create acc
    • Saga №3: open_acc_and_add_to_user
      • Event-ы: Open acc + Add account to user

Формирование sag дерева sag операции

Структура одноименных с операцией Sag внутри сервиса будет представляться в виде уровней дерева:

1)Выбрать следующую sag-у текущего уровня дерева.
2)Создать выбранную пустую sag-у со статусом 0.
3)Добавить uuid созданной sag-и в map с номером sag-и в дереве.
4)У текущей sag-и есть зависимость от других sag? Если да, то идем в пункт 5, иначе, идём в пункт 8.
5)Выбрать следующую sag-у, от которой зависит текущая.
6)Связать текущую sag-у с зависимой по номеру sag-и в map-е.
7)Зависимая sag-а была последней? Если нет, то идём в пункт 5, иначе идём в пункт 8.
8)Создать события со статусом созданных (10), которые должны быть в sag-e.
9)Sag-а является последней в уровне дерева? Если нет, то идём в пункт 1, иначе идём в пункт 10.
10)Уровень дерева является последним? Если нет, то идём в пункт 11, иначе в пункт 12.
11)Переходим на следующий уровень дерева. Идём в пункт 1.
12)Проходимся по map-е и изменяем статус sag на созданный (10)

Работа механизма sag

Обработка событий и sag происходят в go-рутинах. Так что алгоритм рассчитан на много поточное выполнение.

1)Текущая Sag-а зависит от других саг? Если да, то идём в 2, иначе идём в 5.
2)Все sag-и, от которых зависим выполнились? Если да, то идём в 5, иначе идём в 3.
3)Ожидание. Идём в пункт 2.
4)Изменяем статус текущей sag-и на исполняемую (20).
5)Проход по всем событиям sag-и, изменение их статуса на исполняемую (20) и отправка соответствующих им запросов на соответствующие сервисы.
6)Ожидание получения ответов на event-ы.
7)Полученный ответ на event удачный? Если да, то идём в пункт 8, иначе идём в 17.
8)Изменяем статус event-а на выполненный (30).
9)Event откатывает другой (флаг event_is_roll_back)? Если да, то идём в пункт 27, иначе идём в пункт 10.
10)На все event-ы sag-и получен ответ? Если да, то идём в пункт 11, иначе идём в пункт 6.
11)Все события sag-и выполнились удачно, т.е. имеют статус выполненной (30)? Если да, то идём в пункт 12, иначе идём в пункт 28.
12)Изменение статуса sag-и на выполненное удачно (30).
13)От текущей sag-и зависят другие sag-и? Если да, то идём в пункт 14, иначе идём в пункт 15.
14)Изменение статуса связи между текущей sag-ой и зависящих на выполненную удачно (20).
15)Все sag-и выполнились? Если да, то идём в пункт конец, иначе идём в пункт 16.
16)Переключаемся на следующую невыполненную sag-у (речь идёт про многопточность). Идём в пункт 1.
17)Изменение статуса event-а на ошибку (255).
18)Event откатывает другой (флаг event_is_roll_back)? Если да, то идём в пункт 19, иначе идём в пункт 20.
19)У откатываемого event-а меняем статус на ошибка в откатывании (250).
20)Sag-а уже откатывается? Если да, то идём в пункт 22, иначе идём в пункт 21.
21)Изменение статуса sag-и на откат (40).
22)В sag-е есть удачно выполненные (30) event-ы, не являющихся обратными (флаг event_is_roll_back)? Если да, то идём в пункт 23, иначе идём в пункт 10.
23)Выбрать следующий удачно выполненный (30) event, поменять статус на откатываемый (40).
24)Создать откатывающий event к текущему в статусе созданного (10) и с поднятым флагом откатывания другого (event_is_roll_back).
25)Привязать созданный event к откатываемому.
26)Изменить статус созданного event-а на в процессе (20) и отправка соответствующего запроса на соответствующий сервис. Идём в пункт 22.
27)Изменение статуса откатываемого event-а текущим на удачный откат (50). Идём в пункт 10.
28)Текущая сага имеет ошибки в событиях (255)? Если да, то идём в пункт 29, иначе идём в пункт 30.
29)Изменение статуса sag-и на ошибочную (255).
30)Текущая сага имеет ошибки откатывания в событиях (250)? Если да, то идём в пункт 31, иначе идём в пункт 32.
31)Изменение статуса sag-и на ошибочную в откатах (250).
32)Текущая sag-а зависит от других sag? Если да, то идём в пункт 33, иначе идём в пункт 35.
33)Изменение статуса связи между текущей sag-ой и теми, от которых зависит текущая на откат (30).
34)Переход во все sag-и, от которых зависит текущая sag-а.
35)Есть sag-и, которые завися от текущей и связь между текущей и зависимой в статусе выполнено удачно (20)? Если да, то идём в пункт 36, иначе в пункт 21.
36)Переход во все sag-и, которые зависят от текущей со статусом связи выполнено удачно (20). Идём в пункт 35.

конец)Завершилась обработка всех sag операции

Визуальный алгоритм

Пример

Пример работы механизма Sag

Уровень бизнес логики

Уровень sag

  • создать sag-у
  • откатить sag-у
  • удалить sag-у
  • создать event
  • откатить event
  • удалить event
  • отправить запрос, реализующий event
  • обработать ответ на event

Уровень операция бизнеса

  • создать пользователя
  • открыть счёт для пользователя (будет реализовываться после первой операции)
Ссылка на вики репозиторий