Перейти к содержанию

Stateful backend-компоненты

Требования применяются к разработке, тестированию и сборке backend-компонента, корректность которого зависит от устойчивого состояния. Выбор, эксплуатация и резервное копирование хранилища находятся вне области документа. Уровни обязательности определены в корневом README.md.

BE-STATE-001. Явная модель состояния

Уровень: MUST

Применяется к: каждому устойчиво хранимому состоянию компонента

Проект должен определить владельца, источник истины, ключ идентичности, инварианты и транзакционную границу состояния. Cache, производное представление и источник истины должны различаться в коде и контракте. Владение по умолчанию совпадает с владением компонентом; отдельный владелец состояния требуется только при отличии.

Обоснование

Неявная роль хранилища приводит к конфликтующим изменениям и невозможности восстановить производные данные.

Проверка

  • review модели и repository boundaries;
  • тест инвариантов транзакции;
  • тест пересоздания производного состояния.

Исключения

Эфемерное состояние одного запроса не относится к этому профилю.

BE-STATE-002. Отсутствие локальной исключительности

Уровень: MUST

Применяется к: изменяемому состоянию в памяти или локальной файловой системе

Корректность не должна зависеть от того, что последующий запрос попадёт в тот же экземпляр. Локальное состояние должно быть одноразовым cache либо иметь проверяемый протокол владения и восстановления. In-process lock не должен считаться защитой от конкурентного экземпляра.

Обоснование

Сборка и тест одного процесса скрывают ошибки при параллельных экземплярах.

Проверка

  • integration-тест двух экземпляров;
  • restart между связанными операциями;
  • тест конкурентного изменения без общего process lock.

Исключения

Однопроцессный компонент допускается только как явно зафиксированный профиль с тестом отказа запуска второго writer.

BE-STATE-003. Конкурентное изменение

Уровень: MUST

Применяется к: двум операциям, изменяющим один логический объект

Код должен применять optimistic concurrency, сериализацию по ключу или иной проверяемый механизм и определять результат конфликта. Потерянное обновление и last-write-wins не должны возникать неявно.

Обоснование

Успешные независимые операции могут взаимно уничтожить изменения.

Проверка

  • конкурентный тест одного объекта;
  • тест stale version;
  • contract-тест результата конфликта.

Исключения

Last-write-wins допустим, если это явно определённая семантика поля и проверяется тестом.

BE-STATE-004. Совместимость формата состояния

Уровень: MUST

Применяется к: изменению persisted schema или сериализованного формата

Изменение должно соблюдать BE-MIG-001BE-MIG-004. Код новой версии должен иметь тест чтения данных предыдущей поддерживаемой версии; rollback не должен требовать чтения формата, который старая версия не понимает, без отдельной совместимой миграции.

Обоснование

Совместимость кода не доказывает совместимость уже сохранённых данных.

Проверка

  • fixture предыдущей версии;
  • тест mixed-version и rollback;
  • schema compatibility check.

Исключения

Полностью воспроизводимый cache может быть удалён и создан заново.

BE-STATE-005. Идемпотентное восстановление операции

Уровень: MUST

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

Операция должна фиксироваться атомарно либо хранить явное состояние, позволяющее безопасно продолжить, компенсировать или повторить её. Признак успеха не должен записываться до выполнения всех обязательных эффектов.

Обоснование

Restart между записями является штатной границей отказа stateful-компонента.

Проверка

  • fault-injection после каждого шага записи;
  • тест повторного запуска;
  • проверка отсутствия ложного успешного состояния.

Исключения

Необратимая внешняя операция требует отдельного идемпотентного контракта с её provider.

BE-STATE-006. Fencing владельца lease

Уровень: MUST

Применяется к: writer, считающему себя единственным владельцем по distributed lock, lease или leader election

Каждая выдача владения должна иметь монотонный fencing token или эквивалентный признак поколения. Хранилище либо защищаемая операция должны атомарно отклонять запись с token старше уже принятого.

Потерявший lease экземпляр должен прекратить новые защищённые операции. Продление lease должно иметь конечный timeout и не должно считать локальные часы или отсутствие ответа доказательством сохранённого владения.

Обоснование

Истёкший writer может продолжить работу после pause или network partition и повредить данные одновременно с новым владельцем; обычный distributed lock этого не предотвращает.

Проверка

  • fault-injection pause, partition и задержанного продления;
  • конкурентная запись старого и нового владельца;
  • проверка отклонения устаревшего fencing token.

Исключения

Fencing token не требуется, если защищаемое хранилище само гарантирует эквивалентное отклонение прежнего владельца и это подтверждено integration- тестом.

BE-STATE-007. Согласованность независимых фиксаций

Уровень: MUST

Применяется к: бизнес-операции, обязательные эффекты которой фиксируются в двух или более системах без общей атомарной транзакции

Контракт операции должен определять источник истины, стабильный идентификатор, порядок фиксаций, допустимые промежуточные состояния и способ восстановления после каждой границы отказа. После частичной фиксации компонент должен идемпотентно продолжить операцию, компенсировать подтверждённый эффект либо сверить системы и перевести операцию в определённое терминальное состояние.

Компонент не должен сообщать успех до подтверждения всех обязательных эффектов. Если внешний необратимый эффект мог завершиться, отсутствие ответа не должно сообщаться как подтверждённый окончательный отказ до восстановления фактического результата.

Обоснование

Локальная транзакция не обеспечивает атомарность с независимо фиксируемой системой, а неоднозначный исход создаёт потерю либо дублирование эффекта.

Проверка

  • fault-injection после каждой независимой фиксации;
  • тест restart из каждого промежуточного состояния;
  • тест продолжения, компенсации или reconciliation;
  • проверка результата при недоступном подтверждении внешнего эффекта.

Исключения

Необязательный best-effort эффект находится вне области требования, если бизнес-контракт явно допускает его потерю и он не влияет на сообщаемый результат обязательной операции.