Enhance notification entity and service for improved delivery channel handling

- Introduced new event types for notifications, including email and push, to support a broader range of delivery methods.
- Added a `persistedEventType` function to map delivery channels to their corresponding event types, improving clarity and maintainability.
- Updated the `sendToRecipient` method to ensure in-app notifications are always persisted, enhancing the reliability of notification records.
- Improved error logging for in-app notification persistence failures, providing better context for debugging.

This update enhances the notification system's flexibility and reliability by supporting multiple delivery channels and improving error handling.
This commit is contained in:
Mazyar
2026-07-11 21:06:29 +03:30
parent 9d8ce12816
commit aafae2a26f
2 changed files with 36 additions and 7 deletions
+20 -2
View File
@@ -28,8 +28,26 @@ const (
DeliveryChannelInApp DeliveryChannel = "in_app" DeliveryChannelInApp DeliveryChannel = "in_app"
) )
// EventTypeInApp identifies notifications stored for the in-app notification center. // Persisted event types for stored notifications (admin list / notification center).
const EventTypeInApp = "in_app" const (
EventTypeInApp = "in_app"
EventTypeEmail = "email"
EventTypePush = "push"
)
// persistedEventType maps a delivery channel to the event_type stored in MongoDB.
func persistedEventType(channel DeliveryChannel) (string, bool) {
switch channel {
case DeliveryChannelEmail:
return EventTypeEmail, true
case DeliveryChannelPush:
return EventTypePush, true
case DeliveryChannelInApp:
return EventTypeInApp, true
default:
return "", false
}
}
// DeliveryStatus represents the delivery status of notification // DeliveryStatus represents the delivery status of notification
type NotificationStatus string type NotificationStatus string
+16 -5
View File
@@ -99,7 +99,18 @@ func (s *notificationService) Send(ctx context.Context, req *NotificationRequest
} }
func (s *notificationService) sendToRecipient(ctx context.Context, recipient notificationRecipient, req *NotificationRequest, link, image string) { func (s *notificationService) sendToRecipient(ctx context.Context, recipient notificationRecipient, req *NotificationRequest, link, image string) {
// Always persist an in-app record so every send appears in the notification center.
if err := s.persistNotification(ctx, recipient, req, link, image, DeliveryChannelInApp); err != nil {
s.logger.Error("Failed to persist in-app notification", map[string]interface{}{
"error": err.Error(),
"user_id": recipient.UserID,
})
}
for _, channel := range req.Channels { for _, channel := range req.Channels {
if channel == DeliveryChannelInApp {
continue
}
if err := s.persistNotification(ctx, recipient, req, link, image, channel); err != nil { if err := s.persistNotification(ctx, recipient, req, link, image, channel); err != nil {
s.logger.Error("Failed to persist notification", map[string]interface{}{ s.logger.Error("Failed to persist notification", map[string]interface{}{
"error": err.Error(), "error": err.Error(),
@@ -153,9 +164,12 @@ func (s *notificationService) sendToRecipient(ctx context.Context, recipient not
} }
func (s *notificationService) persistNotification(ctx context.Context, recipient notificationRecipient, req *NotificationRequest, link, image string, channel DeliveryChannel) error { func (s *notificationService) persistNotification(ctx context.Context, recipient notificationRecipient, req *NotificationRequest, link, image string, channel DeliveryChannel) error {
methods := map[string]string{} eventType, ok := persistedEventType(channel)
eventType := string(channel) if !ok {
return nil
}
methods := map[string]string{}
switch channel { switch channel {
case DeliveryChannelEmail: case DeliveryChannelEmail:
if recipient.Email == "" { if recipient.Email == "" {
@@ -168,10 +182,7 @@ func (s *notificationService) persistNotification(ctx context.Context, recipient
} }
methods["push"] = recipient.DeviceTokens[0] methods["push"] = recipient.DeviceTokens[0]
case DeliveryChannelInApp: case DeliveryChannelInApp:
eventType = EventTypeInApp
methods["in_app"] = "true" methods["in_app"] = "true"
default:
return nil
} }
status := string(DeliveryStatusSent) status := string(DeliveryStatusSent)