У меня есть личный AI-ассистент в Telegram, которого я зову Алиса. Она мониторит мои чаты, отвечает на вопросы, запускает задачи и в целом работает как мой виртуальный помощник. Но был один огромный недостаток: уведомления. Когда что-то изменялось в системе (новая бронь, ошибка в боте, сообщение в группе), Алиса писала мне уведомление. Но иногда этих уведомлений было 20-30 в час. От одного события! Просто потому, что один процесс порождал десятки микро-событий подряд.
Проблема: уведомления как спам
Вот типичный сценарий: приходит новое бронирование в eZee. Это порождает цепь событий:
- Парсер eZee вычитал бронь → уведомление "Новая бронь"
- Данные синхронизировались в PostgreSQL → "Синхронизация завершена"
- Google Sheets обновилась → "Google Sheets синхронизирован"
- Проверилась доступность виллы → "Занятость обновлена"
- Запустилась фотогалерея → "Фото загружены"
- Запустилась проверка отзывов → "Отзывы обновлены"
- И так далее...
В итоге я получал 8-10 уведомлений за 30 секунд об одном-единственном событии. Это было полной трагедией, потому что я не мог нормально работать — мой Telegram был просто завален этой чепухой. И самое страшное: я мог пропустить действительно важное уведомление в этом спаме.
Решение: Debounce
Debounce — это паттерн, который давно используется в frontend-разработке. Если коротко: вместо того, чтобы срабатывать на каждое событие, функция ждёт, пока события перестанут приходить, и срабатывает только один раз после периода тишины.
Я применил этот принцип к уведомлениям. Вот как это работает:
1. Событие приходит (новая бронь) → не отправляем уведомление сразу
2. Вместо этого запускаем таймер на 45 секунд
3. Пока приходят другие события (синхронизация, обновления) → ничего не отправляем, но перезапускаем таймер
4. Когда 45 секунд тишины → отправляем одно объединённое уведомление "Новая бронь +4 обновления"
Результат: вместо 8-10 уведомлений я получаю 1-2. И этот один концентрированный отчёт содержит всю релевантную информацию об одном событии.
Техническая реализация
На практике я реализовал это на Python (для Telegram-бота) с использованием Redis как хранилища состояния. Вот упрощённый алгоритм:
class NotificationDebouncer:
def __init__(self, wait_time=45):
self.wait_time = wait_time
self.pending = {} # event_type: {time, data}
self.timers = {}
def add_event(self, event_type, data):
# Отменяем старый таймер
if event_type in self.timers:
self.timers[event_type].cancel()
# Добавляем/обновляем событие
self.pending[event_type] = data
# Запускаем новый таймер
timer = threading.Timer(
self.wait_time,
self.send_notification,
args=[event_type]
)
self.timers[event_type] = timer
timer.start()
def send_notification(self, event_type):
# Отправляем одно объединённое уведомление
data = self.pending.pop(event_type)
self.bot.send_message(
chat_id=OWNER_ID,
text=self.format_notification(event_type, data)
)
del self.timers[event_type]
Ключевый момент: когда приходит новое событие того же типа, мы не отправляем уведомление — мы перезапускаем таймер. Это обеспечивает, что в очереди событий мы накапливаем их в течение 45 секунд, а потом отправляем всё одним пакетом.
Уточнения и граничные случаи
Конечно, нельзя просто так debounce все события. Некоторые уведомления критичны и должны приходить сразу:
- Критичные события (priority=HIGH): ошибка в системе, отказ платежа, проблема с сервером — отправляются без debounce сразу
- Малозначительные события (priority=LOW): обновления логов, мониторинг здоровья — debounce 60+ секунд
- Обычные события (priority=NORMAL): новые бронирования, обновления данных — debounce 45 секунд
Также я различаю события по типам: события типа "booking" debounce независимо от событий типа "review". То есть уведомления о бронированиях группируются отдельно от уведомлений об отзывах.
Результаты
Когда я внедрил debounce, изменилось буквально всё:
- Раньше: 20-30 уведомлений в час в пиковое время
- Сейчас: 2-3 уведомления в час, концентрированные и содержательные
- Качество: каждое уведомление теперь несёт значимую информацию
- Важные события: всё ещё приходят сразу, потому что они отмечены как критичные
Важный бонус: так как я теперь получаю меньше уведомлений, я действительно их читаю. Раньше я их просто игнорировал как спам. Теперь каждое уведомление — это сигнал к действию.