Поправка по кэшу: по интервалу снова сверяем modified, всегда качает только кнопка

Как и просили: фоновое обновление по интервалу сначала смотрит на дату
изменения файла и, если таблица не менялась, не скачивает её. Всегда
перечитывать таблицу — только принудительное обновление из админки
(force_reload, кнопка «Обновить сейчас»).

Тесты: по интервалу — без скачивания при неизменном modified; кнопка —
скачивает независимо от modified (test_force_refresh_ignores_ttl_and_modified).
This commit is contained in:
2026-10-06 15:01:07 +03:00
parent 475eb3801e
commit a4798c4a36
3 changed files with 30 additions and 19 deletions

View File

@@ -101,16 +101,18 @@ nginx (https://schedule.our-place.ru) → 127.0.0.1:8090
ошибка, число групп); ошибка, число групп);
- **вставить новую ссылку**: она проверяется скачиванием и разбором таблицы - **вставить новую ссылку**: она проверяется скачиванием и разбором таблицы
до сохранения — нерабочая не применится, данные на сайте не пострадают; до сохранения — нерабочая не применится, данные на сайте не пострадают;
- **принудительно обновить расписание** — вне интервала, не дожидаясь - **принудительно обновить расписание** — вне интервала: кнопка перечитывает
фонового обновления (интервал и так перечитывает таблицу целиком); таблицу всегда, не глядя на дату изменения файла;
- **задать интервал обновления** в минутах (`1…1440`). - **задать интервал обновления** в минутах (`1…1440`).
Каждое обновление (и по кнопке, и по интервалу) **всегда перечитывает таблицу**, Фоновое обновление по интервалу работает как раньше: сначала сверяется
а в панели и в логе видно, изменился ли файл на Диске: `sha256`, время `modified` файла, и если таблица не менялась — скачивания не происходит.
последнего изменения содержимого и отметка «изменился / без изменений». Принудительное обновление (кнопка) скачивает файл **всегда**, поэтому его и
Если вы поправили таблицу, а после обновления написано «без изменений» — значит стоит нажимать сразу после правок в таблице. В панели и в логе при этом видно,
публичная ссылка Яндекса отдаёт прежнюю версию файла (бывает с задержкой), изменилось ли содержимое файла: `sha256`, время последнего изменения и отметка
стоит повторить обновление через минуту. «изменился / без изменений». Если вы поправили таблицу, а после обновления
написано «без изменений» — значит публичная ссылка Яндекса отдаёт прежнюю
версию файла (бывает с задержкой), стоит повторить обновление через минуту.
Как это устроено: Как это устроено:

View File

@@ -2,9 +2,9 @@
- однопоточная перезагрузка (lock): параллельные запросы во время загрузки - однопоточная перезагрузка (lock): параллельные запросы во время загрузки
ждут один download вместо N скачиваний; ждут один download вместо N скачиваний;
- интервал обновления: по его истечении таблица перечитывается целиком - интервал обновления: по его истечении сверяем modified таблицы — если файл
(поле modified у публичной ссылки может «застыть», поэтому на него не не менялся, скачивание не повторяется; принудительное обновление из админки
опираемся — оно только показывается в админке); (force_reload) перечитывает таблицу всегда;
- stale-while-error: если таблица перестала скачиваться, отдаём последнее - stale-while-error: если таблица перестала скачиваться, отдаём последнее
удачное состояние и повторяем попытку не чаще, чем раз в retry_after секунд удачное состояние и повторяем попытку не чаще, чем раз в retry_after секунд
(вместо скачивания на каждый запрос); (вместо скачивания на каждый запрос);
@@ -218,10 +218,19 @@ class ScheduleCache:
if not self._link: if not self._link:
self._fail(ScheduleError(NO_LINK_ERROR), now) self._fail(ScheduleError(NO_LINK_ERROR), now)
return return
# Обновление интервала всегда перечитывает таблицу: поле modified у # Обновление по интервалу: сначала сверяем modified — если файл не
# публичной ссылки может «застыть» (кэш на стороне Диска), и тогда # менялся, скачивание не повторяем. Принудительное обновление (кнопка
# проверка «таблица не менялась» держала бы старые данные бесконечно. # в админке) идёт через force_reload и качает файл всегда.
modified = fetch_table_modified(self._link) modified = fetch_table_modified(self._link)
if (
self._data is not None
and modified is not None
and modified == self._modified
):
# таблица не менялась — источник доступен, данные актуальны
self._loaded_at = now
self._error = None
return
try: try:
self._load(now, modified) self._load(now, modified)
except ScheduleError as exc: except ScheduleError as exc:

View File

@@ -170,16 +170,16 @@ def test_cache_no_repeated_download(client, cache):
assert cache.calls["download"] == 1 assert cache.calls["download"] == 1
def test_interval_refresh_always_downloads(cache): def test_modified_unchanged_no_download(cache):
"""По интервалу таблица перечитывается всегда. """По интервалу сверяем modified: если таблица не менялась — не скачиваем.
Поле modified у публичной ссылки может «застыть», поэтому на него не Принудительное обновление из админки при этом качает файл всегда
опираемся: иначе стенд показывал бы старые данные бесконечно. (см. test_force_refresh_ignores_ttl_and_modified).
""" """
cache._ttl = 0 cache._ttl = 0
cache.get() cache.get()
cache.get() cache.get()
assert cache.calls["download"] == 2 # оба обновления по интервалу скачали таблицу assert cache.calls["download"] == 1
assert cache.calls["modified"] >= 2 assert cache.calls["modified"] >= 2