Services/Service-Registration.md


Назначение

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

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

Таблица операций

operation_uuid operation_name create_time last_time_update
uuid varchar(128) timestamptz timestamptz
  • operation_uuid - уникальный id операции. Уникальное
  • operation_name - имя операции.
  • create_time - время создания операции.
  • last_time_update - последние обновления, связанные с операцией.

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

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

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

  • 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": ...
}
  • operation_uuid - уникальный id операции, в рамках которой выполняется SAGA

Таблица зависимостей 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
    • closse account
    • get_account_data
  • Сервис пользователей
    • Create user
    • Add account to user
    • get_user_data
    • check_user_password
    • update_user_password
    • get_user_data_by_login

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

  • Create user (простая)
    • Зависимость sag: create_user
    • Saga №1: create_user
      • Event-ы: Create user
  • Add account to user (составная)
    • Зависимость sag: check_user -> reserve_acc -> create_acc -> open_acc_and_add_to_user
    • Saga №1: check_user
      • Event-ы: check_user
    • Saga №2: reserve_acc
      • Event-ы: Reserve acc
    • Saga №3: create_acc
      • Event-ы: Create acc
    • Saga №4: open_acc_and_add_to_user
      • Event-ы: Open acc + Add account to user
  • Add accoun cache (составная)
    • Зависимость sag: check_user->get_account_data->add_account_cache
    • Saga №1: check_user
      • Event-ы: get_user_data
    • Saga №2: get_account_data
      • Event-ы: get_account_data
    • Saga №3: add_account_cache
      • Event-ы: add_account_cache
  • Width accoun cache (составная)
    • Зависимость sag: check_user->get_account_data->width_account_cache
    • Saga №1: check_user
      • Event-ы: get_user_data
    • Saga №2: get_account_data
      • Event-ы: get_account_data
    • Saga №3: width_account_cache
      • Event-ы: width_account_cache
  • Close account (составная)
    • Зависимость sag: check_user->get_account_data->close_account
    • Saga №1: check_user
      • Event-ы: get_user_data
    • Saga №2: get_account_data
      • Event-ы: get_account_data
    • Saga №3: close_account
      • Event-ы: close_account
  • Get user data (простая)
    • Зависимости sag: check_user
    • Saga №1: check_user
      • Event-ы: get_user_data
  • Get account data (составная)
    • Зависимость sag: check_user->get_account_data
    • Saga №1: check_user
      • Event-ы: get_user_data
    • Saga №2: get_account_data
      • Event-ы: get_account_data
  • Update_user_password
    • Зависимость sag: update_user_password
    • Saga №1: update_user_password
      • Event-ы: update_user_password
  • Get_user_data_by_login
    • Зависимость sag: get_user_data_by_login
    • Saga №1: get_user_data_by_login
      • Event-ы: get_user_data_by_login
  • Check_user_password
    • Зависимость sag: check_user_password
    • Saga №1: check_user_password
      • Event-ы: check_user_password

Формирование 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). Добавление новых данных в sag-у, к которой относится event.
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). Прокидывание в зависимые sag-и данные из текущей sag-и.
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

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

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

Уровень REST API

Операции

  • Регистрация пользователя
  • Регистрация счёта пользователя
  • Закрытие счёта
  • Снятие со счёта
  • Пополнение счёта
  • получить данные пользователя
  • получить данные счёта
  • обновить пароль пользователя
  • получить данные пользователя по логину
  • проверить пароль пользователя
  • Узнать состояние операции
  • Получить данные об операции, для построения дерева
  • Получить список операций за указанный промежуток времени

Регистрация пользователя

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/create_user

    Входные данные запроса

{
	"user_inn": "01234567890123456789",
	"passport": {
		"series": "0123",
		"number": "012345",
		"name": "...",
		"surname": "...",
		"patronymic": "...",
		"birth_date": "01-01-2001 01:01:01",
		"birth_location": "...",
		"pick_up_point": "...",
		"authority": "012-345",
		"authority_date": "01-01-2001 01:01:01",
		"registration_address": "...",
	}, 
	"user_data": {
		"login": "...",
		"password": "..."
	}
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ начала операции - 202
  • ошибка в данных пользователя - 400
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 202,
  "info": "operation_id(uuid)",
  "additional_info": { # не является обязательным
    "...": "...",
    ...
    "...": ...
  },
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Регистрация счёта пользователя

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/open_account

    Входные данные запроса

{
	"user_id": "uuid",
	"acc_name": "...",
	"culc_number": "...",
	"corr_number": "...",
	"bic": "...",
	"cio": "...",
	"reserve_reason": "..."
}

Возможные ответы на запрос и их статусы

Статусы

  • Счёт создан - 201
  • ошибка в данных пользователя - 400
  • пользователь на найден - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 201,
  "info": "account_id(uuid)"
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Закрытие счёта

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/close_acc

    Входные данные запроса

{
  "user_id": "uuid",
  "account_id": "uuid"
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 202
  • ошибка в данных пользователя - 400
  • нет указанного пользователя или счёта - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 202,
  "info": "operation uuid"
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Пополнение счёта

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/add_account_cache

    Входные данные запроса

{
  "user_id": "uuid",
  "account_id": "uuid",
  "cache_diff": 1234567 # Может быть как целым, так и дробным.
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 202
  • ошибка в данных пользователя - 400
  • нет указанного пользователя или счёта - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 202,
  "info": "operation uuid"
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Снятие со счёта

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/width_account_cache

    Входные данные запроса

{
  "user_id": "uuid",
  "account_id": "uuid",
  "cache_diff": 1234567 # Может быть как целым, так и дробным.
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 202
  • ошибка в данных пользователя - 400
  • нет указанного пользователя или счёта - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 202,
  "info": "operation uuid"
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Получение данных пользователя

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/get_user_data

    Входные данные запроса

{
  "user_id": "uuid"
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 202
  • ошибка в данных пользователя - 400
  • нет указанного пользователя или счёта - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 202,
  "info": "operation uuid"
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Получение данных счёта

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/get_account_data

    Входные данные запроса

{
  "user_id": "uuid",
  "account_id": "uuid"
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 202
  • ошибка в данных пользователя - 400
  • нет указанного пользователя или счёта - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 202,
  "info": "operation uuid"
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Обновить пароль пользователя

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/update_password

    Входные данные запроса

{
  "user_id": "uuid",
  "new_password": "..."
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 202
  • ошибка в данных пользователя - 400
  • нет указанного пользователя - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 202,
  "info": "operation uuid"
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Получить данные пользователя по логину

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/user_data_by_login

    Входные данные запроса

{
  "user_login": "..."
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 202
  • ошибка в данных пользователя - 400
  • нет указанного пользователя - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 202,
  "info": "operation uuid"
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Проверить пароль пользователя

Информация о запросе

  • тип запроса - POST
  • url - http://localhost:8080/api/v1/registration/check_password

    Входные данные запроса

{
  "user_id": "uuid",
  "password": "..."
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 202
  • ошибка в данных пользователя - 400
  • нет указанного пользователя - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 202,
  "info": "operation uuid"
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

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

Информация о запросе

  • тип запроса - GET
  • url - http://localhost:8080/api/v1/registration/get_operation_status

    Входные данные запроса

{
  "operation_id": "uuid",
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ - 200
  • ошибка в данных пользователя - 400
  • операция не найдена - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 200,
  "info": "in process",
  "additional_info": { # может и отсутствовать
    ...
  }
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Получить данные об операции, для построения дерева

Информация о запросе

  • тип запроса - GET
  • url - http://localhost:8080/api/v1/registration/get_operation_tree_data

    Входные данные запроса

{
  "operation_id": "uuid"
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 200
  • ошибка в данных пользователя - 400
  • нет указанного пользователя - 404
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 200,
  "info": {
    "operation_name": "...",
    "saga": [
      {
        "id": "...",
        "status": 999,
        "name": "...",
        "events": [
          "event_id",
          ...
          "event_id_n"
        ]
      },
      ...
      {
        ...
      }
    ],
    "events": [
      {
        "id": "...",
        "name": "...",
        "status": 999,
        "roll_back_id": "..."
      },
      ...
      {
        ...
      }
    ],
    "saga_depend": [
      {
        "parent_id": "...",
        "child_id": "..."
      }
    ]
  }
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}

Получить список операций за указанный промежуток времени

Информация о запросе

  • тип запроса - GET
  • url - http://localhost:8080/api/v1/registration/get_operations_range

    Входные данные запроса

{
  "time_begin": "time",
  "time_end": "time_end"
}

Возможные ответы на запрос и их статусы

Статусы

  • удачный ответ (операция выполняется) - 200
  • ошибка в данных пользователя - 400
  • внутренняя ошибка сервера - 500

Ответы

  • Удачный:
{
  "status": 200,
  "info": {
    "operations": [
      "operation_id",
        ...
      "operation_id_n"
    ]
  }
}
  • Ошибочный:
{
  "status": 400,
  "info": "Input data validation error"
}
Ссылка на вики репозиторий