502просмотров
15 октября 2025 г.
📷 ФотоScore: 552
Паттерн: Сага Интересный архитектурный шаблон, особенно актуальный в условиях распределённых систем, когда некое бизнес-осмысленное действие будет успешным, только если будет успешным каждый небольшой шаг, а функционал реализован в разных сервисах; если любой шажок закончится неудачей, то надо откатить все предыдущие (успешные) шаги. Сага — это последовательность локальных транзакций. Каждая локальная транзакция обновляет базу данных и публикует сообщение или событие, чтобы запустить следующую локальную транзакцию в саге. Если локальная транзакция завершается неудачей из-за нарушения бизнес-правила, сага выполняет серию компенсирующих транзакций, которые отменяют изменения, внесённые предыдущими локальными транзакциями.
— Pattern: Saga Пример — создание заказа на одном из текущих проектов. Задача: создать сущность заказа в OMS в статусе «Создан», затем зарезервировать остатки под заказ в системе оперативных остатков товаров, потом сменить статус заказа на «Оформлен» и в конце отправить уведомления клиенту и менеджеру (ещё нужно будет бонусы списывать в программе лояльности, но это на следующих этапах проекта). Формально сагу рекомендуют делать на событиях, которые либо оркестрируются либо обрабатываются хореографически. Мы сделали упрощённый оркестратор, который хранит состояние саги в реляционной СУБД. В случае неудачи оркестратор пытается выполнить шаг с таймаутом с нелинейным возрастанием задержки. Если попытки исчерпаны — вся сага отменяется с компенсирующими действиями. Наша сага имеет следующие шаги:
APPLY_STOCK — создать временный резерв остатков
APPLY_LOYALTY — списать бонусы в системе лояльности
CONFIRM — подтвердить заказ, отправить уведомления Финальные шаги:
FINISHED — сага успешно завершена
FAILED — сага завершилась с ошибками Шаг отката:
ROLLBACK_STOCK — убрать временный резерв остатков в случае ошибок Я решил не усложнять архитектуру асинхронными очередями, потому что: (1) тестировать сагу стало бы в разы сложнее; (2) проектная нагрузка на систему далека от „High load“; (3) узнать в моменте состояние саги стало бы сложнее. Подобная реализация уже была сделана нашим тимлидом на другом проекте и по моим наблюдениям вполне неплохо себя зарекомендовала. Проблемы, которые там были, появились из-за некачественного логгирования шагов и плохо настроенных таймаутов (финальные таймауты достигали дней между повторами). Я с самого начала спроектировал логгирование правильно, ну а для таймаутов, для разнообразия взял ряд Фибоначчи с ценой деления 1 минута. А есть ли у вас в практике интересные шаблоны проектирования, которые вы использовали осознанно? (ну или случайно, главное чтобы вам понравилось :) )