Сервис отложенных уведомлений. Принимает уведомления с указанием времени отправки, хранит их в PostgreSQL и доставляет через RabbitMQ с поддержкой Email и Telegram.
- Docker и Docker Compose
- Go 1.22+ (для локального запуска)
- Task (таск-раннер, опционально)
Task используется для удобства — все команды с описанием перечислены в Taskfile.yaml. Если не хотите устанавливать таск-раннер, просто берите нужные команды оттуда и вводите напрямую в консоль.
go install github.com/go-task/task/v3/cmd/task@latest
Скопируйте и отредактируйте конфиг:
cp config.yaml config.example.yamlЗаполните обязательные параметры (описание ниже в разделе Конфигурация).
Поднять все контейнеры (postgres + rabbitmq + приложение):
task docker:upПросмотр логов приложения в реальном времени:
task docker:logstask docker:infra # поднять postgres и rabbitmq
task run # запустить приложениеПосле запуска (локально или в контейнере) тестовый веб-интерфейс доступен по адресу:
http://<addr>/
Например, при стандартных настройках — http://localhost:8080/.
Тело запроса:
{
"text": "Текст уведомления",
"recipient": "user@example.com",
"sender": "email",
"scheduled_at": "2026-03-25T19:30:00+03:00"
}| Поле | Описание |
|---|---|
text |
Текст уведомления |
recipient |
Адресат: email-адрес или Telegram chat ID |
sender |
Канал доставки: email или tg |
scheduled_at |
Время отправки в формате RFC3339 (должно быть в будущем) |
Ответ 201 Created:
{ "id": 42 }При сбое в процессе обработки (падение сервиса после отправки, но до обновления статуса в БД) произойдёт повторная отправка сообщения.
При неудачной попытке доставки сервис автоматически переносит уведомление с экспоненциальным backoff (настраивается через retry_base и retry_unit). После достижения max_attempts уведомление переводится в статус failed.
Ответ 200 OK:
{ "status": "pending" }Возможные статусы:
| Статус | Описание |
|---|---|
pending |
Ожидает отправки |
processing |
Отправляется прямо сейчас |
sent |
Успешно доставлено |
rescheduled |
Перенесено из-за ошибки, будет повторная попытка |
failed |
Превышено максимальное число попыток |
cancelled |
Отменено пользователем |
Ответ 200 OK при успехе.
Отмена невозможна если:
- Уведомление уже отправлено, отменено или завершилось ошибкой
- До времени отправки осталось менее
cancel_window(по умолчанию 1 минута)
Отправка через SMTP. В качестве recipient передаётся email-адрес получателя.
Обязательные параметры конфига:
email:
host: sandbox.smtp.mailtrap.io # SMTP-хост
port: 587 # SMTP-порт
username: <mailtrap_username> # логин для аутентификации на SMTP
password: <mailtrap_password> # пароль для аутентификации на SMTP
from: sender@example.com # адрес отправителя в письме
ssl: false # true для порта 465 (implicit SSL), false для 587 (STARTTLS)Отправка через Telegram Bot API. В качестве recipient передаётся числовой chat ID получателя.
Важно: пользователь должен сам инициировать диалог с ботом (нажать Start), иначе бот не сможет отправить сообщение. Узнать свой chat ID можно через бота @userinfobot.
Обязательные параметры конфига:
telegram:
token: "123456:ABC-DEF..." # токен бота из @BotFatherНастройки server, postgres, rabbitmq и logger содержат стандартные параметры с понятными названиями и подробно описаны в config.example.yaml — здесь они пропущены.
service:
max_attempts: 5 # максимальное число попыток доставки уведомления
cancel_window: 1m # запрет отмены за это время до scheduled_at
retry_base: 2 # основание для экспоненциального backoff
retry_unit: 1h # единица времени backoff (задержка = base^attempt * unit)
send_timeout: 30s # максимальное время ожидания ответа от канала доставкиПример задержек при retry_base: 2, retry_unit: 1h:
| Попытка | Задержка |
|---|---|
| 1 | 2 часа |
| 2 | 4 часа |
| 3 | 8 часов |
| 4 | 16 часов |
| 5 | 32 часа |