Files
dedinit.ru/openspec/changes/deploy-sftp-incremental/design.md
T

47 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Design: Инкрементальный SFTP-деплой
## Подход
Модифицируем единственный файл `tools/deploy_sftp.py`:
1. **Сравнение файлов (size + mtime)**:
- Для каждого локального файла вызываем `sftp.stat(remote_path)`.
- Если stat успешен И `(st_size, int(st_mtime))` совпадает с локальным
`(os.stat(lpath).st_size, int(os.stat(lpath).st_mtime))` — пропускаем (не льём).
- Если stat бросает IOError (нет файла) или не совпадает — заливаем.
- Метрику печатаем: `= пропущено, + залито`.
2. **Таймауты против зависания**:
- `paramiko.Transport` создаём с `banner_timeout=30`, `timeout=30`.
- Для каждого `put` используем `paramiko` окно: оборачиваем в `socket.setdefaulttimeout(120)`
(SFTP-канал унаследует) — если операция длится дольше 2 мин, канал падает с ошибкой,
скрипт падает с понятным сообщением вместо бесконечного висения.
- Удаление тоже не должно висеть: те же таймауты.
3. **Что НЕ меняется**:
- Mirror-логика (всё, чего нет локально, удаляется) — сохранена.
- Рекурсивное создание каталогов — сохранено.
- Интерфейс: `tools/deploy_sftp.py [--dry-run]`, переменные DEDINIT_* / SSHPASS.
- Вызов из `.gitea/workflows/deploy.yml` не меняется.
## Риски
- **mtime на сервере** (Jino) может отличаться от локального (часовой пояс, точность).
SFTP stat возвращает mtime в секундах; локально `int(st_mtime)` — тоже секунды.
Допуск: считаем «не изменился», если `|remote_mtime - local_mtime| <= 120` И размеры равны.
(Больше 2 мин расхождения не бывает при честном сравнении; зато гарантируем, что
файл, записанный «только что» локально и залитый минуту назад, не перельётся без нужды.)
Решение: допуск на mtime = 300 сек (5 мин) при равенстве размеров.
- **Ложные пропуски**: если сервер отдаёт mtime 0 (некоторые SFTP-сервера) — считаем файл
изменённым (льём всегда). Проверка `if remote_mtime > 0`.
- **Большой дерево**: rlist рекурсивно обходит всё дерево — оставляем как есть (работает,
это доли секунды на 500 файлов).
## Верификация
- `python3 tools/deploy_sftp.py --dry-run` локально: показывает список изменившихся
(должно быть 0 после сборки в тот же public/... фактически покажет все «+», т.к. на
сервере старый mtime — это ок, первый деплой льёт всё).
- После первого инкрементального деплоя повторный `--dry-run` покажет «=» (пропуски).