### Дизайн кэша для клиента kakoisegodnyaprazdnik.ru. Мы исходим из следующих предпосылок: 1. Необходимо делать минимальное количество запросов, чтобы нас не забанили. 2. На каждый запрос мы меняем строку user-agent. Делаем выборку из списка в зависимости от номера дня в месяце. 3. Кэш актуален до ~ 0:01 следующего дня В идеале в сутки делается всего один запрос в ихнее "api" (там на самом деле парсинг странцы, что какбэ не айс, но ничего не поделать - api как таковое у них отсутствует). ### Техническая часть Вроде как [pebble db](github.com/cockroachdb/pebble) показала себя как впорлне рабочее решение для хранения данных типа key-value. Так что задействуем её. Из минусов этого решения - в этой базе экспайринг ключей не предусмотрен в принципе. То есть именно сам экспайринг надо проводить самостоятельно. Технически это делать несложно. Берём базу cache и в неё складываем 2 k-v записи: prazdnikisegodhyaru_timestamp->date и prazdnikisegodhyaru_value->value. Далее, при любом обращении к клиенту, мы извлекаем prazdnikisegodhyaru_timestamp->date и сравниваем с датой предполагаемого экспайра кэша, если извлечённая дата больше предполагаемая, достаём данные из кэша, если извлечённая дата меньше или равна извлечённой, то делаем запрос в "api", складываем api в prazdnikisegodhyaru_value->value, обновляем timestamp в prazdnikisegodhyaru_timestamp->date, а данные возвращаем в качестве ответа наверх, по цепочке. ## Дизайн кэша для клиента openweathermap Здесь предпосылки другие: 1. Согласно показаниям openweathermap данные для "погоды в текущий момент времени" обновляются раз в три часа. 2. Делать много запросов и их api тоже нежелательно - они в ведут учёт запросов и там есть верхнее ограничение, которое сбрасывается раз в месяц. 3. Точных моментов времени, когда происходит обновление данных они не приводят. ### Техническая часть Таже самая pebbledb, заводить новую смысла особого нету. Название базы тоже cache. Кэшировать имеет смысл не более, чем на 3 часа. Слишком большой ttl кэша приведёт к "неправдаподобности", особенно в ситуациях, когда мы запросили данные в когда они "скоро протухнут" на источнике. Слишком малое значение ttl снижает эффективность кэша. В перловой реализации мы брали 3 часа, выглядит, как отличной вариант для начала. Далее, реализация. Важным моментом является ключ. Ключ должен содержать в себе данные, уникальные для типа запроса. То есть, собственно имя города. В нашем случае имя города, после "нормализации". Собственно, ключ будет содержать имя города + тип значения, от кторого взята sha256, например, sha256(London+timestamp) или sha256(Tokyo+value) (sha256 на себя берёт враппер бд - функции GetValue и saveKeyWithValue). (В идеале, было бы неплохо составить табличку с названиями городов на разных языках, которые мапятся либо в одно название, либо в geo координаты, тогда эффективность кэша будем максимальной, но для этого нужна либо периодическая джоба, которая обновляет соответсвующий кэш, либо обновлять его on-request, по мере протухания). N.B. вероятность коллизий sha256 сравнительно минимальна, но она есть, поэтому timestamp необходимо проверять на валидность формата. Тоже касается и прогнозов погоды. Проверки по длине вполне хватает. ### Механика взаимодействия с кэшом На поступивший запрос мы 1. извлекаем из базы timestamp 1. если timestamp валиден 1. если он не просрочен, извлекаем из базы значение, если 1. оно валидно, отправляем его в качестве ответа 2. если оно не валидно, делаем запрос в api, обновляем кэш 2. если timestamp просрочен делаем запрос в api, обновляем кэш 2. если timestamp не валиден, делаем запрос в api, обновляем кэш 2. если извлеклась пустая строка, делаем запрос в api, обновляем кэш Обновление кэша подразумевает вычисление timestamp, когда он должен просрочиться (текущее время + ttl), обновление 2-х ключей в кэше: city+timestamp и city+value.