fix(notification): dedupe due/overdue events to prevent resend on scan
This commit is contained in:
@@ -476,8 +476,7 @@ func (s *Service) PublishTaskEvent(ctx context.Context, eventType string, task T
|
|||||||
traceID = eventID
|
traceID = eventID
|
||||||
}
|
}
|
||||||
if eventType == "task.overdue" {
|
if eventType == "task.overdue" {
|
||||||
bucket := time.Now().UTC().Unix() / int64(s.cfg.OverdueThrottle/time.Second)
|
eventID = fmt.Sprintf("task-overdue:%d:%s", task.ID, task.DueAt)
|
||||||
eventID = fmt.Sprintf("task-overdue:%d:%d", task.ID, bucket)
|
|
||||||
traceID = eventID
|
traceID = eventID
|
||||||
}
|
}
|
||||||
payload := map[string]any{
|
payload := map[string]any{
|
||||||
@@ -681,14 +680,40 @@ func (s *Service) scheduleDueEvents(ctx context.Context) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if dueAt.After(now) && dueAt.Before(now.Add(s.cfg.DueSoonWindow)) {
|
if dueAt.After(now) && dueAt.Before(now.Add(s.cfg.DueSoonWindow)) {
|
||||||
|
if s.hasExistingTaskEvent(ctx, task.ID, "task.due_soon", task.DueAt) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
_ = s.PublishTaskEvent(ctx, "task.due_soon", task)
|
_ = s.PublishTaskEvent(ctx, "task.due_soon", task)
|
||||||
}
|
}
|
||||||
if dueAt.Before(now) {
|
if dueAt.Before(now) {
|
||||||
|
if s.hasExistingTaskEvent(ctx, task.ID, "task.overdue", task.DueAt) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
_ = s.PublishTaskEvent(ctx, "task.overdue", task)
|
_ = s.PublishTaskEvent(ctx, "task.overdue", task)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) hasExistingTaskEvent(ctx context.Context, taskID int64, eventType, dueAt string) bool {
|
||||||
|
var exists bool
|
||||||
|
err := s.pool.QueryRow(ctx, `
|
||||||
|
SELECT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM notification_events
|
||||||
|
WHERE event_type = $1
|
||||||
|
AND payload->>'task_id' = $2
|
||||||
|
AND payload->>'due_at' = $3
|
||||||
|
)`,
|
||||||
|
eventType,
|
||||||
|
strconv.FormatInt(taskID, 10),
|
||||||
|
dueAt,
|
||||||
|
).Scan(&exists)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) runDailySummaryScheduler(ctx context.Context) {
|
func (s *Service) runDailySummaryScheduler(ctx context.Context) {
|
||||||
ticker := time.NewTicker(s.cfg.SchedulerTick)
|
ticker := time.NewTicker(s.cfg.SchedulerTick)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|||||||
Reference in New Issue
Block a user