UAS_Kelompok5/lost-and-found/internal/workers/notification_worker.go
2025-11-17 12:17:44 +07:00

116 lines
2.8 KiB
Go

package workers
import (
"log"
"lost-and-found/internal/models"
"lost-and-found/internal/repositories"
"time"
"gorm.io/gorm"
)
// NotificationWorker handles sending notifications asynchronously
type NotificationWorker struct {
db *gorm.DB
notificationRepo *repositories.NotificationRepository
matchRepo *repositories.MatchResultRepository
stopChan chan bool
}
// NewNotificationWorker creates a new notification worker
func NewNotificationWorker(db *gorm.DB) *NotificationWorker {
return &NotificationWorker{
db: db,
notificationRepo: repositories.NewNotificationRepository(db),
matchRepo: repositories.NewMatchResultRepository(db),
stopChan: make(chan bool),
}
}
// Start starts the notification worker
func (w *NotificationWorker) Start() {
log.Println("📬 Notification Worker started")
// Run every 5 minutes
ticker := time.NewTicker(5 * time.Minute)
defer ticker.Stop()
for {
select {
case <-ticker.C:
w.sendPendingNotifications()
case <-w.stopChan:
log.Println("📬 Notification Worker stopped")
return
}
}
}
// Stop stops the notification worker
func (w *NotificationWorker) Stop() {
w.stopChan <- true
}
// sendPendingNotifications sends notifications for unnotified matches
func (w *NotificationWorker) sendPendingNotifications() {
log.Println("🔍 Checking for pending notifications...")
// Get unnotified matches
matches, err := w.matchRepo.FindUnnotifiedMatches()
if err != nil {
log.Printf("❌ Error fetching unnotified matches: %v", err)
return
}
if len(matches) == 0 {
log.Println("✅ No pending notifications")
return
}
log.Printf("📧 Found %d pending notifications", len(matches))
sentCount := 0
for _, match := range matches {
// Send notification to lost item owner
if err := w.sendMatchNotification(&match); err != nil {
log.Printf("❌ Failed to send notification for match ID %d: %v", match.ID, err)
continue
}
// Mark as notified
if err := w.matchRepo.MarkAsNotified(match.ID); err != nil {
log.Printf("❌ Failed to mark match ID %d as notified: %v", match.ID, err)
continue
}
sentCount++
}
log.Printf("✅ Sent %d notifications", sentCount)
}
// sendMatchNotification sends a match notification
func (w *NotificationWorker) sendMatchNotification(match *models.MatchResult) error {
// Create notification
err := models.CreateMatchNotification(
w.db,
match.LostItem.UserID,
match.Item.Name,
match.ID,
)
if err != nil {
return err
}
log.Printf("📧 Sent match notification to user ID %d for item: %s",
match.LostItem.UserID, match.Item.Name)
return nil
}
// RunNow runs notification sending immediately (for testing)
func (w *NotificationWorker) RunNow() {
log.Println("▶️ Running notification sending manually...")
w.sendPendingNotifications()
}