Видно, изменился ли файл при обновлении (sha256 + отметка в админке)

Просьба с эксплуатации: после «Обновить сейчас» непонятно, подхватились ли
правки таблицы. Теперь кэш считает sha256 скачанного файла и сравнивает с
предыдущим чтением:

- в логе: «Расписание загружено: N групп …; файл изменился/не изменился
  (sha256 ab12cd34)»;
- состояние для админки дополнено полями changed / changed_at / content_hash;
- в панели чипы «Файл при последнем обновлении», «Содержимое менялось»,
  «sha256 файла», а после кнопки — понятное сообщение: «обнаружены изменения»
  либо «файл не изменился (на Диске та же версия)» с подсказкой про задержку
  публикации у Яндекса;
- ответы API отдаются с Cache-Control: no-store, чтобы браузер не показывал
  закэшированные данные после обновления;
- запросы к Яндекс.Диску идут с no-cache заголовками и меткой времени —
  меньше шансов получить закэшированную версию файла.

Тест: test_state_reports_file_changes (первая загрузка, изменение файла,
повторное чтение без изменений).
This commit is contained in:
2026-09-29 15:27:01 +03:00
parent d4b47c30bf
commit d177560f7d
6 changed files with 96 additions and 8 deletions

View File

@@ -168,6 +168,38 @@ def test_interval_refresh_always_downloads(cache):
assert cache.calls["modified"] >= 2
def test_state_reports_file_changes(monkeypatch):
"""Кэш показывает, изменилось ли содержимое файла при последнем чтении."""
import schedule.cache as cache_mod
from fixtures import fixture_sheets
from xlsx_builder import build_workbook
def xlsx_with_room(room: str) -> bytes:
sheets = fixture_sheets()
sheets["Бакалавры и магистры"].rows[2][6] = f"Математика\nСмирнов А.В.\nауд. {room}"
return build_workbook(sheets)
files = {"data": xlsx_with_room("215")}
monkeypatch.setattr(cache_mod, "fetch_table_modified", lambda url, timeout=20.0: "m1")
monkeypatch.setattr(cache_mod, "download_schedule", lambda url, timeout=60.0: files["data"])
cache = ScheduleCache("test-link", ttl_seconds=3600, retry_after=60)
cache.get()
first = cache.state()
assert first["content_hash"]
assert first["changed"] is False # первая загрузка — не «изменение»
assert first["changed_at"] is not None
files["data"] = xlsx_with_room("216")
cache.force_reload()
changed = cache.state()
assert changed["changed"] is True
assert changed["content_hash"] != first["content_hash"]
cache.force_reload()
assert cache.state()["changed"] is False # тот же файл — изменений нет
def test_cache_stale_while_error(cache):
cache._ttl = 0 # форсим повторную попытку
cache.get()