У меня есть в таблице постгрескл дата, мне нужно отправлять пользователям в телеграм 2 сообщение: когда остается один день и 3 часа.
Дата в бд может сильно колибаться, но возьмем длину до 3 месяцев, как я понимаю использовать планировщик задач с датой через 3 месяца может быть не самым оптимальным решением если учесть что таких задач может быть достаточно много, возможно я не прав и буду рад любому исправлению. Я читал про редис, но не совсем понял один момент, он сохраняет задачи в оперативную память но также может сохранять задачи на диск без настройки, но я не понял от чего зависит разное сохранение. Прошу подсказать какой планировщик лучше использовать, я думал над сохранением всех данных в бд или на диск в случаи падение редис или откл. сервера.
Чтобы постгрес сам что-то запускал по расписанию? есть и расширения и сторонние агенты, с синтаксисом, похожим на крон. всякие pg_agent и так далее. Будут выполнять psql команды, среди которых можно и внешнюю команду вызвать типа
COPY (SELECT text) TO PROGRAM '/bin/curl blablablabla...'
Или просто написать скрипт на чем угодно, запускать через крон регулярно, а скрипт уже будет делать select и там смотреть подошло ли время и что куда отправлять.
"достаточно много" это неясно сколько, чтобы понимать насколько нужно велосипедить.
Сто? тысяча? миллион? в день? в час? в минуту?
Например тысяча в час - просто скрипт на баше, данные в sqlite более чем достаточно.
извиняюсь за неточную информацию, было тяжело сформулировать. У меня есть бот на python + aiogram, пользователи регистрируюца на определнное событие дата которого может быть хоть через 3 месяца (может и больше, но пока что я взял эту орентировачную длину), так вот мне нужно чтобы когда до назначиной даты оставался день отправить сообщение предупреждающее + когда останиться 3 часа еще одно оповещение. Я просто не сильно вижу смысл помещать в планировщик задачи которые могут быть использованы через 3 месяца. Количество запросов я не могу точно сказать, но я орентируюсь на то что запланнированных задач может быть миллион. Я не совсем понимаю где планировщики хранят задачи, они хранят в оперативной памяти или сохраняют их на диск, просто если они сохраняются на диск то впринципе планировщики идеально подходят потому что мне не нужны задачи в оперативе которые исполняться только через 3 месяца
Maxwell012, Если это поможет, то я думаю сохранят в планировщик только одну переменную что является индентификатором на определнную строку в бд и когда ее время исполнение доходит то уже через айди достоется нужная информация с бд и отправляется оповещение клиенту. Я имею виду что я не буду хранить много информации для запуска одной задачи, поэтому миллион задач в планировщике даже если в оперативе это не так уж много, но мне нужно рассчитывать на то что вес задач может привышать обьем оперативной памяти поэтому лучше сохранять их на диск плюс это защитит меня от перезагрузки сервера и т.д.
Можно просто раз в минуту делать выборку по таймстампу, и если now > timestamp, то слать предупреждение.
Таким образом сами события хранишь в базе, а скрипт запускается через крон на регулярной основе.
Если выборка выполняется долго, или уведомлений много, посмотреть в сторону выполнять раз в 5 мин или раз в час.
Можно разные выборки для разных вариантов - разовое событие на timestamp или регулярное на дату месяца, день года, день недели.
Опять же, одинаковые события не обязательно хранить для каждого пользователя, можно в базе хранить список адресатов для одного события.
А так, конечно нет смысла хранить все в памяти, если много записей.
Saboteur, каждая дата это отдельная строка, просто проверяя каждую секунду например 1м записей это ужасная затрата ресурсов, раз в 5м тоже такое себе, нужно тогда учитывать что дата уже могла на 5м быть пройдена. Я думал может есть чет на подобие вебхуков, то есть когда остался час до даты отправлялся запрос мне в основной скрипт который обрабатывал его и все, то есть чтобы нужная дата сама отправлялась. Тоесть мой скрипт просто ожидает например запрос который прийдет от бд и тогда его исполняет, хотя возможно это так и устроенно что есть просто скрипт в постгрескл который постоянно проверяет дату, но я бы хотел какой-то триггер чтоли. Надеюсь я понятно высказался
Saboteur, 1 я просто уточнить хотел. 3 В базе у меня храниться timestamp. Мне вполне нравиться решение которое вы предложили, я приблизительно так и думал что оно будет, просто в силу того что я подобное не делал, а говнокод я не люблю, поэтому я посчитал будет лучше спросить.
Даже сейчас когда я уже сравнил планировщик с сохранением в бд, я чувствую некую неуверненность, хотя очевидно что в данной ситуации с достаточно длинным отлаживанием планировщик будет работать хуже.
Saboteur, Просто поймите меня правильно, я всего лишь пытаюсь найти самое производительное решение, чтобы потом не переписывать его много раз. Поэтому я думал например написать какой-то триггер в постгрескл который когда время указанное в колонке равно настольному времени будет вызывать функцию, может так будет лучше чем постоянно запросы слать внешне?
ну триггер делает тоже самое. Выборку сколько-то там раз в секунду или минуту. Надо почитать детали конкретного плагина.
Вы должны сами знать как часто для вас отправлять сообщения.
Я для себя писал бота в телеграмме с разными уведомлениями, и храню в таблице несколько видов напоминалок - разовые по таймстампу, регулярные ежедневные, еженедельные, ежемесячные и ежегодичные.
У меня нагрузка нулевая, поэтому обошелся sqlite и выборка раз в минуту.
Я планировал что если нагрузка сильно увеличиться, то мне не критично когда прийдет напоминалка - могу делать выборку раз в 10 минут. Может быть даже раз в час. Или перейти с sqlite на любую другу базу, которая будет лучше работать с мультиклиентами.
Но даже в самом плохом сне я не думаю, что мне нужно привязываться к секундам - это бессмысленно, так как даже при отправке уведомления, оно может на несколько секунд прийти позже по логистическим причинам. А с раз в минуту - вроде как и не проблема. Да и масштабировать это на кластер будет несложно
Saboteur, извиняюсь что долго не отвечал. Хочу тогда подвести итог, лучшим вариантом будет орендовать сервак с процессором на 3> ядер, сделать отдельный класс который будет вызываться каждую минуту с планировщика как отдельный скрипт (имею виду на отдельном ядре) для создания выборки с БД, потом соотвественно создание асинхронной задачи под каждое уведомление и запуск этого всего например через aiogram.gather(*tasks). В случаи падение производительности, просто уменьшать частоту вызова класса в планировщике. Если я правильно все понял, то так приблизительно выглядит план моих действий, верно?
да. Но 3 млн заданий если распределить на год, то может и на 1 cpu вполне будет работать
база индексированная по timestamp выборки делает очень быстро, вне зависимости от их количества
Saboteur, я пока что поставил предположительные границы для себя это 300к задач в день. Я подумал что если раз в минуту не потянет то увеличу до 5 или до 10мин так как это особо не повлияет на работу моего скрипта.