DarkRiDDeR22 мин

Переход как автомат состояний: критерии, трафик, данные и rollback без подмены

АрхитектураСистемное мышление

Ошибка в механике миграции обычно начинается с одного статуса «готово». В него складывают схему, копию данных, candidate traffic и кнопку rollback, хотя это разные состояния с разными отказами. Цена — ложная обратимость: команда может вернуть маршрут, но обнаружить, что изменения данных уже не имеют named recovery path; или увидеть candidate без control и назвать это сравнением. Один зелёный статус прячет несколько не заданных вопросов.

Ниже — не конечный автомат реальной платформы, а строгая модель fixed synthetic record. Она различает четыре условия: инвентарь complete, трафик comparable, data state reversible и rollback decidable. Функция выдаёт только первый нарушенный барьер или synthetic-migration-review-hand-off. Положительный выход не запускает переход. Он говорит, что структура одного учебного доказательства достаточно связна для дальнейшего review.

Почему порядок отказов важнее счастливой ветки

В state machine порядок — это политика диагностики. Если inventory пуст, бессмысленно спорить о триггере rollback: неизвестно, на что он должен воздействовать. Если traffic не имеет control boundary, нельзя читать data state как достаточное основание для перехода. Если data необратимы, trigger уже не делает rollback осмысленным. Модель поэтому проверяет путь слева направо и не пытается собрать список всех возможных дефектов. Первый stop оставляет узкую следующую работу.

Такой порядок не доказывает, что остальные поля верны. Он делает причину отказа стабильной. Это принципиально для review: разные рецензенты на том же literal получают одинаковый status, а не набор зависимых от настроения замечаний. Стабильность полезна и для текста. Автор не пишет «план сырой», а указывает inventory-route-owner-or-dependency-missing или другую named boundary. Это уже можно исправить без угадывания скрытого смысла.

Таблица из четырёх synthetic cases. Только строка с control 90 процентов, candidate 10 процентов, обратимым data state и named trigger заканчивается hand-off; остальные строки останавливаются.
Матрица показывает, что возврат трафика не заменяет восстановление данных, а trigger не может быть неназванным наблюдением.
Состояния механизма
СостояниеИнвариантЗачем он нуженЧего не говорит
inventory completeroute, owner, record и dependency названыесть объект переходаинвентарь реальной системы полон
traffic comparablecontrol/candidate имеют общий routeесть граница сравнениядоли отражают реальный трафик
data reversiblerestore и reconciliation видимыкопия не выдана за откатвосстановление технически выполнено
rollback decidabletrigger, owner, return states именованыстоп можно обсуждатьсреда будет изменена

Inventory — тип входа, а не приложение к документу

Механизм принимает inventory как тип входа. Один route должен иметь id, owner и dependency; один record — id, reader и writer. Эта модель не пытается вывести связи по имени файла или URL. Вывод был бы внешним исследованием и нарушил бы границу package. Фиксированный объект позволяет спросить проще: достаточно ли информации, чтобы связать traffic slice с data transition? Если нет, ошибка называется до того, как появляются проценты и диаграммы.

В accepted case dependency record-ledger-entry соединяет route и record. Это искусственный, но полезный шов. Когда dependency отсутствует, engine не угадывает, что route «вероятно» читает record. Он возвращает stop-missing-inventory. Fail-closed здесь важнее удобства: оптимистичное допущение именно превращает целевую архитектуру в план без текущего состояния. В настоящем расследовании пробел нужно заполнять доказательством, а не значением по умолчанию.

Traffic slice — отношение двух множеств

Контрольная граница — не просто остаток после candidate share. Она должна быть named set routes и совпадать с candidate route set в том вопросе, который обсуждает review. Если candidate читает route A, а control — route B, числа 10 и 90 не образуют сравнение. Если control пуст, candidate становится демонстрацией самого себя. Функция проверяет это как структуру массивов и останавливает состояние до анализа data или trigger.

Observation window содержит id и список metric ids. В реальности окно потребовало бы время, систему наблюдения и определение расчёта. Здесь их нет намеренно. fixed-window-15-samples-v1 — имя синтетической границы, а не пятнадцать реальных измерений. Требование к имени спасает модель от фразы «после перевода посмотрим». Но оно не делает список имён телеметрией и не подтверждает какой-либо пользовательский эффект.

Data state обязан иметь направление назад

Модель не использует bool migrated, потому что тот не говорит ничего о возвращении. У accepted case есть state copy-verified-reversible, source/target record, reconciliation и restore state. Любой пропуск переводит его в stop-irreversible-data-state. В частности, copy-complete не проходит. Это сознательная семантика: наличие target не эквивалентно возможности восстановить прежнее write condition.

Можно возразить, что некоторые переходы не требуют data rollback. Возможно; тогда это должно быть отдельным явно названным вариантом модели с другой задачей, а не дырой в текущем record. Механизм не обязан покрыть все архитектуры. Его обязанность — не позволить несовместимым смысловым случаям спрятаться за одной строкой. Прямое ограничение лучше универсального объекта, который принимает всё и не умеет объяснить, почему rollback оказался недоступен.

Литеральное выполнение state machine

import { createFixedMigrationRecord, evaluateFixedTransitionState } from './upgrade-2026-07.mjs';

const record = createFixedMigrationRecord('traffic-without-control-v1');
const result = evaluateFixedTransitionState(record);
console.log({ status: result.status, reasons: result.reasons, next: result.nextAction });
// { status: 'stop-unbounded-traffic-slice', reasons: ['traffic-slice-requires-named-control-boundary'], next: 'name-control-candidate-same-route-and-observation-window' }

Этот snippet проверяет отрицательную ветку буквально. Он не создаёт traffic slice и не читает load balancer. Результат ценен тем, что имеет один named reason и одно named next action. Для технической речи это полезнее, чем «проверьте маршрутизацию»: reader видит, что следует добавить в record, и одновременно видит, чего функция не делает. Исполняемость здесь относится к детерминированной классификации literal, не к изменению инфраструктуры.

Rollback decidable, когда заданы границы решения

Rollback складывается из условия, владельца и двух return states. Condition отвечает, какое наблюдение в рамках модели вызывает вопрос; owner — кто удерживает выбор как именованный предмет review; traffic/data states — что вообще подразумевается под «назад». Без trigger механизм возвращает stop-unnamed-rollback-trigger. Он не заменяет trigger словом «аномалия», потому что это возвращает нас к зелёному статусу, который зависит от непередаваемого контекста.

Это различие помогает не злоупотреблять аналогией с deployment rollback. Versioned Kubernetes documentation описывает управляемое изменение желаемого state у Deployment и отмечает, что откат ранней revision возвращает Pod template. В модели migration это внешний пример узкого scope, а не шаблон подмены. Мы не переносим Kubernetes semantics на record или traffic. Наоборот, используем источник, чтобы не назвать rollback одного controller отменой всех последствий перехода.

Последовательность построения перехода

  1. Собрать inventory и проверить, что первый route связан с owner, dependency и record read/write boundary.
  2. Построить два traffic sets с одним route boundary и дать observation window отдельное имя.
  3. Описать data transition через source, target, reconciliation и reversible restore, не через флаг completed.
  4. Назвать rollback trigger, condition, decision owner, traffic return и data return как разные поля.
  5. Проверить allowed positive status: он должен быть hand-off и содержать effect no-system-change.

Критерии должны быть сильнее комментария

Фраза «данные синхронизированы» звучит сильнее, чем позволяет current object. Механизм вместо неё разрешает только reconciliation: fixed-count-and-key-set-v1. Это имя требует дальнейшего отдельного определения, но не притворяется его выполнением. Точно так же «candidate стабилен» в package заменяется на ссылку на named observation window. Уменьшение амбиции здесь не потеря качества: это отказ от статуса, который нельзя вывести из входа.

RFC 2119 полезен для самопроверки формулировок: MUST в этой статье относится к структуре record, а не к человеку, процессу или production system. Можно сказать: accepted branch MUST иметь restore state. Нельзя сказать: команда MUST переключить маршрут. В первом случае проверка делает statement наблюдаемым. Во втором текст играет роль оператора над внешним миром, хотя у него нет доступа ни к этому миру, ни к его последствиям.

Ограничения автомата и следующий шаг

State machine не выражает длительность, concurrency, свойства конкретного хранилища, законодательные требования или стоимость простоя. Она не может различить хороший и плохой trigger, если оба именованы. Она также не оценивает, правильно ли выбран owner. Это намеренная цена формальности: machine защищает связность модели, но не заменяет инженерное суждение, discovery и отдельные evidence о среде.

Следующий безопасный шаг — добавить fixed case с несовпадающими control/candidate routes либо с конфликтом source/target record и проверить, что status остаётся точным. Такой рост тестирует границы, а не делает successful branch громче. Если новый случай требует иной семантики данных, его стоит выделить в отдельную карточку. Нельзя расширить существующий positive hand-off до «разрешено мигрировать»: это была бы другая функция с отсутствующими входами.

Проверяемые источники

  • Kubernetes Documentation: Deployments — версия: Kubernetes v1.33 versioned documentation snapshot, 23 April 2025. Использована граница rollback Deployment: он относится к Pod template; это контрпример попытке назвать rollback controller откатом данных. Граница: Не выводит Kubernetes API, состояние кластера или стратегию перехода.
  • Google SRE Book: Addressing Cascading Failures — версия: Wayback immutable capture, 23 January 2025 16:42:19 UTC. Использована только формулировка положительной обратной связи для объяснения ценности раннего, именованного stop. Граница: Не подтверждает конкретный failure mode или trigger synthetic record.
  • RFC 2119: Key words for use in RFCs to Indicate Requirement Levels — версия: RFC 2119, March 1997, immutable RFC text. Использована терминология MUST/MAY для отделения инварианта JS model от приказа внешней среде. Граница: Не создаёт нормативных требований к реальной миграции.