Как реализовать обратную сторону — Inbox паттерн на стороне notification service? Как обеспечить идемпотентность обработки событий?
Answer from AI
sobes.tech AI
Inbox паттерн в notification service используется для обеспечения идемпотентной обработки входящих событий. Идея в том, чтобы сохранять уникальные идентификаторы обработанных событий (например, eventId) в специальной таблице (Inbox), чтобы при повторном получении того же события его не обрабатывать повторно.
Реализация:
- При получении события проверяем, есть ли eventId в таблице Inbox.
- Если нет — обрабатываем событие, сохраняем eventId в Inbox.
- Если есть — пропускаем обработку.
Для обеспечения идемпотентности важно, чтобы запись eventId и обработка события были атомарными. В Go с использованием базы данных это можно сделать в рамках транзакции.
Пример на Go (упрощённо):
func ProcessEvent(db *sql.DB, event Event) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
var exists bool
err = tx.QueryRow("SELECT EXISTS(SELECT 1 FROM inbox WHERE event_id = ?)", event.ID).Scan(&exists)
if err != nil {
return err
}
if exists {
// Уже обработано
return nil
}
// Обработка события
err = handleEvent(tx, event)
if err != nil {
return err
}
// Запись eventId в Inbox
_, err = tx.Exec("INSERT INTO inbox(event_id) VALUES(?)", event.ID)
if err != nil {
return err
}
return tx.Commit()
}
Таким образом, даже при повторной доставке события оно будет обработано только один раз.
Также можно использовать уникальные ограничения на столбец event_id, чтобы избежать дублирования при параллельной обработке.