Что показывать, когда внешний сервис не отвечает
Сохранённая копия данных позволяет сайту пережить сбой внешнего сервиса: статьи и фотографии остаются доступны, пока источник не отвечает. Но без обновлений сайт не узнает, что автор добавил или удалил. Поэтому вместе с сохранением копии нужно решить, как долго её можно показывать без свежего подтверждения от источника.
В статье о личном сайте я рассказывал, как сохранял данные из социальных сервисов до следующего удачного обновления. Tumblr мог не работать, а статьи оставались доступны. У такого подхода есть особенность: по самой странице трудно заметить, что обновления прекратились.
Рассмотрим ленту фотографий, которая последний раз обновилась вчера. После ошибки запроса мы знаем только то, что получили тогда. Может быть, новых фотографий нет. Может быть, их уже двадцать. Может быть, автор успел удалить одну из старых. Неудачный запрос не даёт выбрать между этими вариантами.
Поэтому вместе с копией нужно сохранять время её последнего успешного обновления. Время очередной попытки здесь не подходит: фоновая задача может исправно запускаться весь день и ни разу не получить данные. Подпись «Обновлено минуту назад» в таком случае расскажет о запуске скрипта, хотя посетитель прочитает её как обещание свежих фотографий.
Саму подпись не обязательно ставить возле каждого изображения. Пока обновления идут нормально, она может быть лишней. Но если очередное обновление задержалось, а старую копию ещё разрешено показывать, полезно сообщить, какую копию мы показываем: «Фотографии по состоянию на 22 апреля. Обновить пока не удалось». Теперь посетитель знает, насколько свежие фотографии он видит. После предельного срока показа одной подписи уже недостаточно: вместо ленты нужно сообщить, что актуальные данные пока недоступны.
Пустой ответ тоже бывает результатом
Есть соблазн свести обработку ответа к одной проверке: если записей нет, оставить старые. Так мы защищаемся от исчезновения ленты во время сбоя. Заодно запрещаем ей стать пустой по желанию автора.
Успешный ответ с пустым списком и ошибка запроса требуют разных действий. Если сервис подтвердил, что в выбранной коллекции ничего нет, старые фотографии пора убрать. Если ответа нет, мы не знаем, изменилась ли коллекция. Прежнюю копию можно пока оставить, если для неё ещё не истёк допустимый срок показа. А когда вместо ожидаемого списка пришло что-то непонятное, это ошибка получения данных, даже если соединение завершилось успешно.
С удалением сложнее. Допустим, запрос возвращает только последние десять фотографий. Обновить ленту этим списком можно, но считать остальные фотографии удалёнными из источника — нет: они могли просто выйти за пределы выборки. Если мы сохраняем и более старые фотографии, для их удаления нужен полный список или отдельное подтверждение от сервиса. Состав ответа определяет, какие выводы мы вообще вправе из него сделать.
Эти различия стоит прояснить до выбора хранилища. Ни файл, ни база данных не помогут отличить удалённую фотографию от той, которая просто не попала в последние десять.
Обновление без пустой страницы
Новую копию удобно готовить отдельно от той, которую читает сайт. Получить ответ, проверить его и сохранить целиком, после чего заменить доступную читателю версию. Удалять старый файл перед запросом не стоит: на всё время ожидания мы сами устраиваем тот сбой, от которого хотели защититься.
Если обновлений несколько, появляется ещё одна неприятность. Первый запрос может задержаться, а второй уже принести более свежую копию. Поздно завершившаяся первая попытка не должна затереть её своим результатом. Для небольшой ленты можно вообще не допускать пересечения обновлений. При параллельной работе придётся сравнивать версии и заранее решить, какая из них считается новой.
При первом запуске старой копии ещё нет. Если запрос завершился ошибкой, на месте ленты можно написать, что фотографии загрузить не удалось. Остальная страница при этом остаётся доступной: сбой одного блока не мешает читать статьи и переходить по сайту.
Однако не всякую сохранённую копию можно показывать сколько угодно. Если фотографию убрали из публичного доступа, надпись о давности обновления проблему не исправит. Получив подтверждение удаления или закрытия доступа, сайт должен перестать выдавать копию, даже если срок её показа ещё не истёк. Пока подтверждения нет, этот срок лишь ограничивает задержку. Если и такая задержка недопустима, перед каждой выдачей нужно проверять доступ у источника; не удалось проверить — не показываем. Уведомления об изменениях помогают убрать копию раньше, но могут прийти с опозданием.
Чтобы проверить этот выбор, достаточно представить: внешний сервис не работает несколько дней. Что в это время увидит посетитель? Публичная фотография может по-прежнему быть интересна, а сообщение «новых записей нет» уже нельзя подтвердить. Мне важно сохранить полезное содержимое и при этом ясно обозначить, чего мы о нём больше не знаем.