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

E-03 · Учёт товара в сети пунктов выдачи — вход#

Этап прогона: прогон завершён · вход зафиксирован 2026-09-18 Кейс: карточки под него нет — ближайшие CASE-10 и CASE-12 не о том Шаги: W0 · Рамки и требования и W1 · Оценки на салфетке

Зачем третий прогон. Первые два проверяли покрытие: хватает ли документов. Оба раза находились дыры, и после каждого почти всем документам требовался MAJOR. Известные дыры закрыты. Этот прогон проверяет форму: сходится ли она, или каждый новый кейс продолжает перестраивать набор. Предсказания записаны заранее — до того, как выбрана тема.

Тему выбирал не автор предсказаний. Шесть кандидатов предложили два независимых агента, работавших с урезанной копией руководства без исследования, бэклога, плана правок и мастер-шаблона — как именно и что проверено. Этот — их первый по одному из двух списков.

Система вымышлена, но внутренне непротиворечива. Числа не взяты у реальной компании; они выбраны так, чтобы арифметика сходилась и решения принимались на них по-настоящему. Пометки: [замер] — измерено на работающей системе, [расчёт] — выведено арифметически, [продукт] — задано бизнесом, [орг] — из состава команд и инфраструктуры, [допущение] — принято нами, требует проверки.

Чем E-03 противоположен обоим предшественникам#

Ось E-01 · Бронирование E-02 · Лента E-03 · Учёт товара
Стадия проекта Гринфилд: фактов нет, предсказываем Работает два года: факты измеряются Работает одиннадцать лет: факты есть и недоступны. Авторов нет, трекер подрядчика закрыт вместе с подрядчиком, репозиторий полон с 2019
Источник истины В базе В базе Вне системы — физическая полка. База не истина, а утверждение о ней
Дефицитный ресурс Место: продать дважды нельзя Нет вовсе Конкуренции за предмет нет. Дефицитно обращение к арбитру: инвентаризация стоит часов чужой работы
Согласованность Атомарность обязательна, местами недостижима Итоговая по построению, отставание 10 с Ни та, ни другая. Система неправа на 0,4 % постоянно; вопрос не «сойдётся ли», а «за сколько узнаем»
Объём 130 ГБ за пять лет — ничтожен Сотни гигабайт в памяти — решает ≈ 0,55 ТБ на диске — скучен и ни на что не влияет. Совпадает с E-01 по итогу, расходится по причине: там предсказан, здесь измерен
Нагрузка Пик ×1000 полчаса в неделю Ровная, пик ×10, круглосуточно 9 операций в секунду. Пик ×12 по графику смен, ×4 в сезон. Инженерной задачи нагрузки нет вовсе — и это третье значение оси, а не её отсутствие
Команда Четыре разработчика, платформенной нет Три команды, платформенная есть Трое сопровождения, ни одного автора. Знание системы — у кладовщиков и диспетчеров, а не у разработчиков
Наблюдаемость Нет — система не запущена Есть: метрики, трассировка, автовыкат Асимметричная: логи есть, метрики частичные, трассировки нет, предметного сигнала нет вовсе. Совпадает с E-01 по итогу, расходится по причине: там нечего было наблюдать
Что решает исход Конкуренция за строку Соотношение чтений к записям и хвост подписок Величина расхождения с физическим миром и время до его обнаружения

Главное отличие — источник истины. E-01 и E-02 могли проверить себя изнутри: строка либо занята, либо нет; пост либо в ленте, либо нет. Здесь единственный арбитр — полка, обращение к нему стоит чужого рабочего времени, и «как часто мы имеем право спрашивать» становится проектным параметром наравне с размером индекса.

План прогона#

Этап Что делаем Документ Статус
1 Вход: рамки, числа, инварианты W0, W1 ✅ этот файл
2 Границы работающей системы D-02 v5.0 → ADR-0001 ✅ модульный монолит, три модуля; шесть дисквалификаторов
3 Декомпозиция данных и реестр копий D-07 v1.0 → ADR-0002 ✅ владение внутри одной базы; шесть копий, три неудаляемы
4 Хранилище под журнал операций D-01 v2.0 → ADR-0003 ✅ расширить имеющееся; матрица не заполнялась — дисквалификаторы сделали всю работу
5 Поведение терминала без связи D-06 v1.0 → ADR-0004 ✅ норма, а не деградация; документ отвёл себя и остался полезен
6 Цель по расхождению и её измеритель D-10 v1.0 → ADR-0005 ✅ ни одна цель не обещана; три измерителя, цель «сутки» отменена расчётом
7 Ревизия: что подтвердилось, что сломалось 99-findings.md ✅ 20 находок · один MAJOR · два предсказания из шести проверены

Список неприменимых фиксируется здесь, до первого ADR — по совету обоих предлагавших агентов: кейс, который по ходу «дотягивают» до полного охвата, ничего не проверяет.

Не планируем применять Почему
D-05 Не гринфилд
D-04 Процесс «приёмка → размещение → выдача» идёт внутри одного контура, участников поперёк границ нет
D-08 Переезда данных нет, и конструировать его ради документа нельзя
D-09 Выкат обычный
D-11 Задевает краем — приложение терминала; одна строка, а не применение
D-03 Вероятно применится и честно кончится умолчанием: кэш здесь не узкое место

Если какой-то из них всё же понадобится — это находка, а не корректировка плана, и она записывается в ревизию отдельно.

Нумерация ADR начинается заново.

1. Что имеем#

Сеть из 900 пунктов выдачи и трёх сортировочных складов. Система учёта работает одиннадцать лет: коробочный продукт, поверх которого внешний подрядчик десять лет делал доработки. Договор с подрядчиком закрыт в 2021 году вместе с его трекером; собственный репозиторий полон с 2019-го, раньше — только релизные архивы. Схема — 340 таблиц [замер].

Симптом, из-за которого всё началось: квартальная инвентаризация стабильно показывает 0,4 % расхождений — посылок, которых по системе нет там, где они есть, или наоборот [замер]. При 1,08 млн посылок в сети это 4 320 штук, при средней объявленной ценности 3 500 ₽ — 15,1 млн ₽ в подвешенном состоянии в любой момент времени [расчёт]. Время до обнаружения — до 90 суток: ровно до следующей инвентаризации. Цель бизнеса — сутки [продукт].

Вне рамок: маршрутизация и перевозка между складами, тарификация и оплата, кассовые операции, колл-центр, приложение получателя. Мы считаем, где чья посылка и кто за неё отвечает.

2. Инварианты#

Их четыре, и главная особенность в том, что первый не держится системой вовсе.

№ Инвариант Чем грозит нарушение Кто держит
И1 У каждой посылки в любой момент ровно одно место и один ответственный Это и есть те самые 0,4 %: посылка «числится» не там, где лежит Никто внутри системы. Арбитр — полка
И2 Выдача происходит один раз Отдали чужое; товар и деньги теряются вместе с доверием Система, если операция дошла
И3 Операция, выполненная без связи, доходит до ядра и не теряется Система расходится с полкой по собственной вине, а не из-за людей Терминал плюс ядро
И4 Порядок операций над одной посылкой сохраняется Выдача, пришедшая раньше приёмки, создаёт мусор, который потом ищут руками Никем не обеспечен сегодня

И1 — центр кейса и его отличие от обоих предшественников. В E-01 инвариант «нельзя продать одно место дважды» держала транзакция; в E-02 «пост не появляется дважды» держала структура хранения. Здесь инвариант держит физический мир, а система только утверждает о нём, и утверждение бывает ложным без всякой ошибки в коде: коробку переставили на соседний стеллаж и не отсканировали.

Отсюда уступка, открывающая класс решений: расхождение допустимо, недопустимо позднее обнаружение [продукт]. Это третье значение той оси, где у E-01 стояла атомарность, а у E-02 — отставание в 10 секунд.

3. Профиль нагрузки#

Показатель Значение Откуда
Пунктов выдачи 900, плюс 3 сортировочных склада [замер]
Посылок в сети единовременно ≈ 1,08 млн [расчёт]: 900 × 1 200
Приёмок в сутки 225 тыс. [замер]
Выдач в сутки 225 тыс. [замер]
Возвратов в сутки 20 тыс. [замер]
Операций в сутки ≈ 470 тыс. [расчёт]
Средняя нагрузка 9 операций/с [расчёт]: 470 тыс. ÷ (14 ч × 3 600)
Первый час смены ≈ 28/с [замер]
Ноябрьский пик ≈ 110/с [замер]
Терминалов в парке ≈ 1 900 [расчёт]: 900 × 2 плюс 3 × 20 плюс резерв

Нагрузки здесь нет, и это надо сказать прямо. Одна нода реляционной базы держит 110 операций в секунду с запасом в десятки раз. Оценка на салфетке нужна ровно затем, чтобы это показать и не строить того, что не требуется. Пик ×12 приходит от графика людей, а не от поведения системы: смены 08:00–22:00, ночью нагрузки нет, всплеск в первый час — разбор утреннего привоза.

Настоящий дефицит в другом месте. Инвентаризация одного пункта — два человека на четыре часа [замер], то есть 7 200 человеко-часов на полную сверку сети [расчёт]. Это и есть цена обращения к арбитру, и она не уменьшается от того, что мы что-то улучшим в коде.

4. Объём данных#

Что Размер Откуда
Запись о посылке ≈ 1 КБ [замер]
Запись об операции ≈ 200 Б [замер]
Журнал операций 94 МБ/сут сырьём; с индексами и метаданными ≈ 100 ГБ/год [расчёт] + [допущение] о тройном множителе на индексы
Журнал за регламентные 3 года 300 ГБ [расчёт]
Посылки за 3 года 225 тыс./сут × 1 095 × 1 КБ ≈ 246 ГБ [расчёт]
Активные посылки 1,08 млн × 1 КБ ≈ 1 ГБ [расчёт]
База целиком ≈ 0,55 ТБ, из них журнал 55 % [расчёт]

Объём скучен, и это его свойство, а не недоработка кейса. Полтерабайта на диске не создают ни одной развилки: не давят на память, не требуют шардирования, не делают миграцию невозможной. Ось «объём» в этом прогоне будет заполняться словом «неважно» — и проверить, умеет ли набор принимать такой ответ, не менее полезно, чем проверить его на 320 гигабайтах E-02.

5. Бюджет — не по задержке, а по времени обнаружения#

Задержка ответа терминала имеет границу, но она мягкая: сканирование → ответ не дольше 300 мс [продукт], иначе растёт очередь у стойки. Сейчас 180 мс [замер], запас есть.

Настоящий бюджет — время до обнаружения расхождения, и он единственный, где есть разрыв:

Участок Сейчас [замер] Целевой [продукт]
Расхождение возникло → операция дошла до ядра до 2 ч (офлайн) до 2 ч
Операция в ядре → расхождение замечено до 90 суток до 24 ч
Замечено → объяснено и исправлено 3–10 суток 3–10 суток

Разрыв в одном участке, как и в E-02. Разница в том, что там его измерила трассировка, а здесь измерять нечем: сигнала «система разошлась с полкой» не существует ни в каком виде, и 90 суток — это не замер задержки, а период инвентаризации, поставленный на её место.

6. Доступность#

Что Цель Обоснование
Приём и выдача на пункте Работают без связи 108 пунктов (12 %) теряют связь суммарно до 40 мин в сутки, в сезон до 2 ч [замер]. Офлайн — штатный режим, а не деградация
Ядро учёта 99,5 % Пункт переживает недоступность ядра; склад — нет
Сортировочный склад 99,9 % Остановка склада останавливает сеть на следующий день

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

7. Ограничения, не относящиеся к технике#

  • Команда: трое сопровождающих [орг]. Ни один не автор. Половина изменений исторически делалась внешним исполнителем, которого больше нет.
  • История недоступна наполовину: репозиторий с 2019 года, до того релизные архивы без истории; трекер подрядчика закрыт в 2021 вместе с договором; своя постановка задач ведётся нерегулярно [орг].
  • Знание системы — не у разработчиков. Как она себя ведёт, знают кладовщики и диспетчеры, и знают в форме обходных приёмов, а не правил [орг].
  • Наблюдаемость: логи приложения 14 суток, метрики только инфраструктурные, трассировки нет, предметных метрик нет ни одной [орг].
  • В эксплуатации: PostgreSQL от коробочного продукта, один ЦОД плюс холодный резерв, выкат раз в две недели ночью [орг].
  • Терминалы — приложение на складских сканерах, обновление централизованное, но парк обновляется неделями [орг].
  • Регламент хранения: журнал операций — три года [продукт].

8. Что осталось неизвестным#

Этого раздела в E-03 больше, чем в обоих предшественниках вместе, и это свойство кейса, а не небрежность подготовки.

Неизвестно Чем закроется
Какие из 340 таблиц живые Учёт обращений к таблицам за месяц — включается настройкой
Полный список писателей в базу Известны приложение и ночная выгрузка; права доступа надо разбирать вручную
Связность изменений по задачам — вход D-02 Своя история 6 лет, но задачи заводились не всегда: порог 80 % может оказаться не на чем считать
Откуда берутся 0,4 % Инвентаризация даёт итог, а не причину. Разбор расхождений сегодня не ведётся
Сколько операций теряется при потере связи Не меряли; терминал не отличает «не отправил» от «отправил и не получил ответ»
Сколько стоит одна внеочередная инвентаризация пункта Считали только полную сверку сети

Что пришло извне, а что дописано#

Различение записано, чтобы вопрос о подгонке был проверяем, а не оставался на слове.

Из внешнего предложения (41-case-candidates.md): предметная область и масштаб сети; 11 лет и отсутствие авторов; 340 таблиц; закрытый трекер подрядчика; все числа нагрузки и объёма; 0,4 % и 90 суток против цели в сутки; 12 % пунктов с потерей связи.

Дописано при записи входа — то, без чего W0 и W1 не заполняются: четыре инварианта и распределение «кто их держит»; бюджет по времени обнаружения; цифры доступности; стоимость инвентаризации (7 200 человеко-часов); состав раздела «что осталось неизвестным».

Два дописанных факта соседствуют с областями, по которым записаны предсказания, и потому названы отдельно: офлайн как штатный режим (следует из внешних 12 % и вынуждает вопрос о поведении без связи) и три роли работающих с системой — кладовщик, диспетчер, поддержка — названные как состав, без единого утверждения о том, как устроены права. Ни то, ни другое не добавлено ради проверки: первое приходит из внешних данных, второе необходимо любому W0.


Итог прогона — 99-findings.md. Коротко: ни одного нового документа решения не потребовалось, один MAJOR, форма сошлась.