5.7 KiB
Context
Запись входящего файла сейчас — двухфазная: Tmp/.<имя>.part, затем rename (SMB) / жёсткая ссылка (local) в Input
без замены (решения №17, №26, №32, №35 Среза 3a). Старый АРМ писал файл прямо в Input и в контуре работал. Владелец
09.10.2026 выбрал повторить старый АРМ и перезаписывать существующий файл.
Goals / Non-Goals
Goals: прямая запись в Input в обоих режимах; меньше требований к правам на шаре; срок ожидания ответа 20 мин.
Non-Goals: см. proposal.
Decisions
D-1. Прямая запись с усечением (решение владельца 09.10.2026)
SmbHotFolder.put: smbclient.open_file(<Input>\<имя>, mode="wb", **credentials) и write. LocalHotFolder.put:
open(<input>/<имя>, "wb") (Path.write_bytes). Существующий файл перезаписывается. Повторная запись в рамках одного
процесса по-прежнему исключена дедупликацией по job_id в воркере (требование «Подтверждение запроса до обработки»);
перезапись возможна только при повторе задания ядром в другом процессе.
D-2. Каталог Input создаётся, как раньше
Перед записью Input создаётся без родителей, «уже есть» и отказ в правах при существующем каталоге — не ошибка
(_ensure_dir в smb, mkdir(exist_ok=True) в local); корень не создаётся. Старый АРМ каталог не создавал, но
терпимое создание поведения в контуре не меняет, а dev-режим и тесты на нём держатся.
D-3. Tmp остаётся только у эмулятора
SCAN_TMP_DIR удаляется из настроек шлюза (Settings, extra="ignore" — старое значение в .env не ломает старт).
Эмулятор читает свою переменную SCAN_TMP_DIR (EmulatorSettings) и собирает набор ответа через
LocalHotFolder.tmp_dir, поэтому параметр tmp_dir у LocalHotFolder остаётся, но put его не использует.
D-4. Срок ожидания 20 мин
SCAN_TIMEOUT_SECONDS по умолчанию 1200. Эффективный дедлайн — min(reply_deadline, старт + SCAN_TIMEOUT_SECONDS),
поэтому arm-core поднимает срок ответа OCR до 20 мин отдельным PR (RSHB/arm-core#87).
D-5. Ошибка записи
При исключении во время открытия/записи put снимает недописанный <Input>/<имя> только при включённой очистке
(ошибка снятия подавляется, исходное исключение поднимается) — R-3.
Risks / Trade-offs
- ИС может увидеть недописанный файл (OQ-79) → смягчение: монопольное открытие
smbclientна время записи; так же работал старый АРМ. Откат — вернуть двухфазную запись из истории ветки. - Ошибка посреди записи оставляет обрезанный файл в
Input→ удаляется только приSCAN_CLEANUP=true(как.partраньше, D-5); иначе остаётся, конвертRECOGNITION_FAILED.
Decisions made without discussion
| # | Дата | Решение | Обоснование | Цена ошибки |
|---|---|---|---|---|
| R-1 | 2026-10-09 | Режим local тоже пишет прямо в Input (не только smb) |
Одинаковая семантика режимов, один набор тестов; эмулятор пишет/читает локально мгновенно | Эмулятор может прочитать недописанный файл — на локальной ФС практически невозможно; откат — вернуть .part в local |
| R-2 | 2026-10-09 | Input по-прежнему создаётся перед записью (D-2), хотя старый АРМ этого не делал |
Отказ в правах на mkdir при существующем каталоге уже не ошибка; dev и тесты на этом держатся |
Лишний вызов mkdir на шаре на каждое задание |
| R-3 | 2026-10-09 | Ошибка записи: недописанный файл в Input удаляется только при SCAN_CLEANUP=true (D-5) |
Требование «при SCAN_CLEANUP=false ничего не удалять» (OQ-144) сохраняется |
Обрезанный файл остаётся в Input, ИС может его распознать с ошибкой; ядро получит RECOGNITION_FAILED от шлюза раньше |
| R-4 | 2026-10-09 | SCAN_TMP_DIR удаляется из шлюза, у эмулятора остаётся (D-3) |
Шлюзу каталог больше не нужен; эмулятору нужен для атомарной сборки ответа | Нет: extra="ignore" — старые .env стартуют |