shikhalev.*
КДПВ сгенерирована нейросетью по запросу «cache invalidation»

Как известно, в программировании есть только две реально сложные задачи: именование переменных и инвалидация кэша1. С первой мы сделать ничего не можем, со второй, конечно, тоже, но что-то делать приходится…

И вот в процессе большого рефакторинга inat-get я в очередной раз задумался. Суть тут вот в чем: данные, которые требуется получать из API iNa­tu­ra­list — очень большие (зависит от це­лей, конечно, но они могут быть очень большими), и логично их за­кэ­ши­ро­вать в локальной базе данных. Естественно, кэшированные данные нужно обновлять.

Есть прекрасный параметр updated_since в запросах к API, т.е. мы храним у себя информацию о сделанных запросах, и когда нам нужно получить новые данные по тем же условиям, указываем дату/время предыдущего запроса в этом параметре. Но полностью проблему это не решает: updated_since не отменяет (и не должен отменять) все остальные параметры запроса, т.е. те наблюдения, которые выпали из запроса, в выборку не попадут. И останутся в локальной БД в старом состоянии.

Ну, то есть, выбрали мы, например, данные по проекту, который фильтрует наблюдения с quality_grade=research, а потом пришел добрый человек и заметил, что в наблюдении культурное растение. Наблюдение выпадает из проекта, но мы об этом не можем узнать через обновление…

Какие есть пути решения? Вижу несколько вариантов, ни один из которых меня не устраивает полностью…

  • Первое, что сформулировалось после консультации с нейросетками, это делать помимо обновляющего второй запрос — без updated_since, зато с only_id, т.е. запрашивать список наблюдений без данных. Затем сравнивать этот список с тем, что у нас лежит в базе, и уже по расхождениям запрашивать данные через id.

    Это можно делать реже, чем обычное обновление, т.е. не при каждом запросе, а, скажем, когда от предыдущего прошла неделя (или другое настраиваемое время). Но тем не менее, несмотря на небольшой трафик, это потребует множества запросов, что не есть хорошо. Просто для понимания, сейчас по Свердловской об­лас­ти — более 400 ты­сяч наблюдений, а по России — почти 11 мил­ли­о­нов. Это более 2 ты­сяч и почти 550 ты­сяч запросов соответственно (за один запрос можно получить не бо­лее 200 на­б­лю­де­ний).

  • Как вариант, использовать в запросе only_id также и updated_since с датой, сдвинутой в прошлое на какое-то разумное время, аналогично и формировать список id из локальной базы. Т.е. исходить из того, что наблюдения, которые давно никто не трогал, имеют меньшую вероятность быть потроганными и впредь. Проблема тут в том, что гарантированно актуальной базы мы при таком подходе не получим никогда.

    Еще мне нейросеть предложила разбить массив данных на слои по древности, синхронизировать все, но с разной частотой. Так мы получим постепенное обновление все базы, но за счет существенного усложнения программы.

  • Еще один ва­ри­ант — формирование случайных выборок для обновления (в комбинации со слоями)… Довольно бессмысленно, как по мне.

    Но можно просто при каждом запросе апдейтить пакет наиболее старых (по времени последнего обновления в БД) наблюдений… Фоновую задачу не пред­ла­гать — просто не впи­сы­ва­ет­ся в архитектуру.

  • И последнее, что пришло мне в голову, это в обновляющем запросе (том, который с updated_since) ослаблять требования за счет условий, соответствие которым может легко штатно меняться (например, вышеупомянутый параметр quality_grade). Проблема тут опять же в отсутствии гарантий, поскольку в принципе поменяться может что угодно.

Продолжаю думать. Если у кого есть соображения по этому поводу, пишите в комментариях, не стесняйтесь.

  1. Автор этой фразы, предположительно, Фил Карлтон (Phil Karlton), ведущий инженер компании Netscape.