feat: notification service
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
// Package intentstream defines the frozen Redis Stream contract used for
|
||||
// Notification Service intent intake.
|
||||
package intentstream
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"galaxy/notification/internal/service/malformedintent"
|
||||
"galaxy/notificationintent"
|
||||
)
|
||||
|
||||
const (
|
||||
fieldNotificationType = "notification_type"
|
||||
fieldProducer = "producer"
|
||||
fieldAudienceKind = "audience_kind"
|
||||
fieldRecipientUserIDs = "recipient_user_ids_json"
|
||||
fieldIdempotencyKey = "idempotency_key"
|
||||
fieldOccurredAtMS = "occurred_at_ms"
|
||||
fieldRequestID = "request_id"
|
||||
fieldTraceID = "trace_id"
|
||||
fieldPayloadJSON = "payload_json"
|
||||
defaultResolvedLocale = "en"
|
||||
)
|
||||
|
||||
// NotificationType identifies one supported normalized notification type.
|
||||
type NotificationType = notificationintent.NotificationType
|
||||
|
||||
const (
|
||||
// NotificationTypeGeoReviewRecommended identifies the
|
||||
// `geo.review_recommended` notification.
|
||||
NotificationTypeGeoReviewRecommended = notificationintent.NotificationTypeGeoReviewRecommended
|
||||
|
||||
// NotificationTypeGameTurnReady identifies the `game.turn.ready`
|
||||
// notification.
|
||||
NotificationTypeGameTurnReady = notificationintent.NotificationTypeGameTurnReady
|
||||
|
||||
// NotificationTypeGameFinished identifies the `game.finished`
|
||||
// notification.
|
||||
NotificationTypeGameFinished = notificationintent.NotificationTypeGameFinished
|
||||
|
||||
// NotificationTypeGameGenerationFailed identifies the
|
||||
// `game.generation_failed` notification.
|
||||
NotificationTypeGameGenerationFailed = notificationintent.NotificationTypeGameGenerationFailed
|
||||
|
||||
// NotificationTypeLobbyRuntimePausedAfterStart identifies the
|
||||
// `lobby.runtime_paused_after_start` notification.
|
||||
NotificationTypeLobbyRuntimePausedAfterStart = notificationintent.NotificationTypeLobbyRuntimePausedAfterStart
|
||||
|
||||
// NotificationTypeLobbyApplicationSubmitted identifies the
|
||||
// `lobby.application.submitted` notification.
|
||||
NotificationTypeLobbyApplicationSubmitted = notificationintent.NotificationTypeLobbyApplicationSubmitted
|
||||
|
||||
// NotificationTypeLobbyMembershipApproved identifies the
|
||||
// `lobby.membership.approved` notification.
|
||||
NotificationTypeLobbyMembershipApproved = notificationintent.NotificationTypeLobbyMembershipApproved
|
||||
|
||||
// NotificationTypeLobbyMembershipRejected identifies the
|
||||
// `lobby.membership.rejected` notification.
|
||||
NotificationTypeLobbyMembershipRejected = notificationintent.NotificationTypeLobbyMembershipRejected
|
||||
|
||||
// NotificationTypeLobbyInviteCreated identifies the
|
||||
// `lobby.invite.created` notification.
|
||||
NotificationTypeLobbyInviteCreated = notificationintent.NotificationTypeLobbyInviteCreated
|
||||
|
||||
// NotificationTypeLobbyInviteRedeemed identifies the
|
||||
// `lobby.invite.redeemed` notification.
|
||||
NotificationTypeLobbyInviteRedeemed = notificationintent.NotificationTypeLobbyInviteRedeemed
|
||||
|
||||
// NotificationTypeLobbyInviteExpired identifies the
|
||||
// `lobby.invite.expired` notification.
|
||||
NotificationTypeLobbyInviteExpired = notificationintent.NotificationTypeLobbyInviteExpired
|
||||
)
|
||||
|
||||
// Producer identifies one supported upstream producer.
|
||||
type Producer = notificationintent.Producer
|
||||
|
||||
const (
|
||||
// ProducerGeoProfile identifies Geo Profile Service.
|
||||
ProducerGeoProfile = notificationintent.ProducerGeoProfile
|
||||
|
||||
// ProducerGameMaster identifies Game Master.
|
||||
ProducerGameMaster = notificationintent.ProducerGameMaster
|
||||
|
||||
// ProducerGameLobby identifies Game Lobby.
|
||||
ProducerGameLobby = notificationintent.ProducerGameLobby
|
||||
)
|
||||
|
||||
// AudienceKind identifies one supported target-audience kind.
|
||||
type AudienceKind = notificationintent.AudienceKind
|
||||
|
||||
const (
|
||||
// AudienceKindUser identifies user-targeted notifications.
|
||||
AudienceKindUser = notificationintent.AudienceKindUser
|
||||
|
||||
// AudienceKindAdminEmail identifies administrator-email notifications.
|
||||
AudienceKindAdminEmail = notificationintent.AudienceKindAdminEmail
|
||||
)
|
||||
|
||||
// Channel identifies one durable notification-delivery channel slot.
|
||||
type Channel = notificationintent.Channel
|
||||
|
||||
const (
|
||||
// ChannelPush identifies the push-delivery channel.
|
||||
ChannelPush = notificationintent.ChannelPush
|
||||
|
||||
// ChannelEmail identifies the email-delivery channel.
|
||||
ChannelEmail = notificationintent.ChannelEmail
|
||||
)
|
||||
|
||||
// Intent stores one normalized notification intent accepted from the Redis
|
||||
// Stream ingress contract.
|
||||
type Intent = notificationintent.Intent
|
||||
|
||||
// DecodeIntent validates one raw Redis Stream entry and returns the normalized
|
||||
// notification intent frozen by the shared producer contract.
|
||||
func DecodeIntent(fields map[string]any) (Intent, error) {
|
||||
return notificationintent.DecodeIntent(fields)
|
||||
}
|
||||
|
||||
// ClassifyDecodeError maps one intake decoding or validation error to the
|
||||
// stable malformed-intent failure surface.
|
||||
func ClassifyDecodeError(err error) malformedintent.FailureCode {
|
||||
if err == nil {
|
||||
return malformedintent.FailureCodeInvalidIntent
|
||||
}
|
||||
|
||||
message := err.Error()
|
||||
switch {
|
||||
case strings.Contains(message, "payload_json"),
|
||||
strings.Contains(message, "turn_number"),
|
||||
strings.Contains(message, "final_turn_number"),
|
||||
strings.Contains(message, "failure_reason"),
|
||||
strings.Contains(message, "applicant_name"),
|
||||
strings.Contains(message, "inviter_name"),
|
||||
strings.Contains(message, "invitee_name"),
|
||||
strings.Contains(message, "review_reason"):
|
||||
return malformedintent.FailureCodeInvalidPayload
|
||||
default:
|
||||
return malformedintent.FailureCodeInvalidIntent
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultResolvedLocale returns the frozen fallback locale assigned when the
|
||||
// current rollout has no supported exact user locale other than English.
|
||||
func DefaultResolvedLocale() string {
|
||||
return defaultResolvedLocale
|
||||
}
|
||||
Reference in New Issue
Block a user