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, форма сошлась.