SLA и критичность этапов¶
Целевые сроки — из SPEC §6. Колонка «Как обеспечивается» описывает, что для этого есть в коде прототипа, а «Чего нет» — что понадобилось бы в банке. Этапы — в PROCESS.md.
| Этап | Критичность | Цель | Как обеспечивается в прототипе | Чего нет |
|---|---|---|---|---|
| Подача заявки | Высокая: клиент ждёт ответа на экране | Мгновенно | Заявка пишется в базу сразу в submitted; ключ идемпотентности не даёт создать дубль при повторной отправке |
— |
| Обогащение | Высокая: без обязательных источников решения нет | p95 до 30 с | Источники опрашиваются параллельно; на попытку 10 с, всего 3 попытки, пауза 0,5 с × номер попытки (RetryPolicy, apps/sources/enrichment.py; переменные SOURCE_*). Обязательный источник (счета, карточка клиента, ЕГРЮЛ/ЕГРИП, БКИ, 115-ФЗ) недоступен → заявка у андеррайтера, а не сбой; необязательный (ФНС, ФССП, арбитраж) → флаг. Худший случай: 3 × 10 с + 1,5 с паузы ≈ 32 с. Медианы задержек моков 0,06–2,4 с (apps/sources/service.py) |
Circuit breaker на источник, экспоненциальная пауза с разбросом, мониторинг p95 по каждой интеграции |
| Стоп-факторы, скоринг, лимит, предложения, маршрут | Высокая | До 1 с каждый | Чистые функции в памяти без внешних вызовов: на заявку уходят миллисекунды | Замер времени по этапам |
| Весь автоматический путь | Высокая | До 2 мин | Worker проверяет очередь каждые 0,5 с. Аренда заявки 120 с: если worker упал, заявка возвращается в очередь (recover_stale). Сбой расчёта — повтор через 5 с × номер попытки, после третьей попытки заявка уходит к сотруднику без решения (workflow.py). В демо решение приходит за несколько секунд |
Брокер очереди с очередью ошибок, несколько worker, алерт на застрявшие заявки |
| Ручное рассмотрение | Средняя: клиент предупреждён о сроке | 4 рабочих часа (микро), 1 день (малый), 2 дня (комитет) | Клиент видит, кто рассматривает заявку и сколько это займёт. Очередь сотрудника — заявки in_review; журнал хранит время поступления и решения, поэтому срок можно посчитать |
Контроль срока: таймер, эскалация, распределение очереди. Сегмент (микро / малый) в маршруте не определяется |
| Запрос данных у клиента | Низкая: ждёт клиента | — | Заявка в needs_data ждёт выписку или «продолжить без неё» |
Срок ожидания: заявка ждёт бесконечно (docs/v2/NOTES.md, Unassigned) |
| Срок предложения | Средняя: условия считаются на день решения | 10 дней | offered → expired при проходе worker после Offer.valid_until или при попытке выбрать просроченное предложение |
— |
| Подписание | Высокая: клиент ждёт на экране | Мгновенно | Код из 6 цифр, действует 5 минут, 3 попытки, не больше 5 кодов на заявку (disbursement.py) |
Срок на подписание после выбора предложения (docs/v2/NOTES.md, Unassigned) |
| Отлагательные условия и выдача | Высокая | До 15 мин | Worker проверяет условия и выдаёт сразу после подписи, на следующем проходе (0,5 с) | Повторная проверка непрошедшего условия: заявка остаётся в conditions (docs/v2/NOTES.md, Unassigned) |
| Предодобрение | Низкая: фоновый расчёт | Раз в сутки, результат действует 30 дней | Worker запускает пакет, когда последний расчёт старше суток; хранится последний результат по ИНН (preapproval.py) |
Планировщик заданий на ночь, история расчётов |
| ИИ-ассистент | Низкая: необязательная надстройка | — | Тайм-аут 30 с, ответ до 500 токенов; при любой ошибке — ответ по шаблону (assistant.py) |
— |
Что делает конвейер устойчивым¶
- Один источник не роняет заявку. У каждого источника своя политика отказа (SPEC §5): недоступный обязательный источник ведёт к андеррайтеру с причиной
route_source_unavailable, необязательный — к флагу. Демо-персонаsource_downпоказывает это на отказе БКИ (MOCK_SOURCES_SCENARIOSв.env). - Заявка не теряется. Статус и журнал пишутся в одной транзакции; захват заявки — переход
submitted → enrichingс проверкой версии строки, поэтому два worker не возьмут одну заявку; зависшая заявка возвращается в очередь по истечении аренды. - Повтор безопасен. Подача и действия клиента идемпотентны или проверяют версию строки (
revision, ответ 409). - Без LLM всё работает. Ассистент — надстройка, решения принимает детерминированный движок.
Сбои моков настраиваются для проверки этих путей: MOCK_SOURCES_FAILURES включает случайные ошибки и тайм-ауты с частотами из apps/sources/service.py, MOCK_SOURCES_SCENARIOS задаёт исход для конкретного ИНН (apps/sources/README.md).