
Как известно, в программировании есть только две реально сложные задачи: именование переменных и инвалидация кэша1. С первой мы сделать ничего не можем, со второй, конечно, тоже, но что-то делать приходится…
И вот в процессе большого рефакторинга inat-get я в очередной раз задумался. Суть тут вот в чем: данные, которые требуется получать из API iNaturalist — очень большие (зависит от целей, конечно, но они могут быть очень большими), и логично их закэшировать в локальной базе данных. Естественно, кэшированные данные нужно обновлять.
Есть прекрасный параметр 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). Проблема тут опять же в отсутствии гарантий, поскольку в принципе поменяться может что угодно.
Продолжаю думать. Если у кого есть соображения по этому поводу, пишите в комментариях, не стесняйтесь.
-
Автор этой фразы, предположительно, Фил Карлтон (Phil Karlton), ведущий инженер компании Netscape. ↩