@@ -25,6 +25,11 @@ type EmailNotificationService struct {
2525 cache cache.Cache
2626}
2727
28+ const (
29+ fifteenMinuteTimeout = 15 * time .Minute
30+ oneHourTimeout = 1 * time .Hour
31+ )
32+
2833// NewEmailNotificationService creates a new EmailNotificationService
2934func NewEmailNotificationService (
3035 logger telemetry.Logger ,
@@ -78,7 +83,7 @@ func (service *EmailNotificationService) NotifyMessageExpired(ctx context.Contex
7883
7984 ctxLogger .Info (fmt .Sprintf ("[%s] email sent to [%s] for message with ID [%s]" , events .EventTypeMessageSendExpired , user .ID , payload .MessageID ))
8085
81- service .addToCache (ctx , events .EventTypeMessageSendExpired , payload .Owner )
86+ service .addToCache (ctx , fifteenMinuteTimeout , events .EventTypeMessageSendExpired , payload .Owner )
8287 return nil
8388}
8489
@@ -111,7 +116,73 @@ func (service *EmailNotificationService) NotifyMessageFailed(ctx context.Context
111116
112117 ctxLogger .Info (fmt .Sprintf ("[%s] email sent to [%s] for message with ID [%s]" , events .EventTypeMessageSendFailed , user .ID , payload .ID ))
113118
114- service .addToCache (ctx , events .EventTypeMessageSendFailed , payload .Owner )
119+ service .addToCache (ctx , fifteenMinuteTimeout , events .EventTypeMessageSendFailed , payload .Owner )
120+ return nil
121+ }
122+
123+ // NotifyWebhookSendFailed sends an email to the user about a failed webhook
124+ func (service * EmailNotificationService ) NotifyWebhookSendFailed (ctx context.Context , payload * events.WebhookSendFailedPayload ) error {
125+ ctx , span , ctxLogger := service .tracer .StartWithLogger (ctx , service .logger )
126+ defer span .End ()
127+
128+ if ! service .canSendEmail (ctx , payload .EventType , payload .Owner ) {
129+ ctxLogger .Info (fmt .Sprintf ("[%s] email already sent to user [%s] with owner [%s]" , events .EventTypeWebhookSendFailed , payload .UserID , payload .Owner ))
130+ return nil
131+ }
132+
133+ user , err := service .userRepository .Load (ctx , payload .UserID )
134+ if err != nil {
135+ msg := fmt .Sprintf ("cannot load user with ID [%s] for [%s] event with ID [%s]" , payload .UserID , events .EventTypeWebhookSendFailed , payload .EventID )
136+ return service .tracer .WrapErrorSpan (span , stacktrace .PropagateWithCode (err , stacktrace .GetCode (err ), msg ))
137+ }
138+
139+ email , err := service .factory .WebhookSendFailed (user , payload )
140+ if err != nil {
141+ msg := fmt .Sprintf ("cannot create [%s] email for user with ID [%s] for [%s] event with ID [%s]" , events .EventTypeWebhookSendFailed , payload .UserID , payload .EventType , payload .EventID )
142+ return service .tracer .WrapErrorSpan (span , stacktrace .Propagate (err , msg ))
143+ }
144+
145+ if err = service .mailer .Send (ctx , email ); err != nil {
146+ msg := fmt .Sprintf ("cannot send [%s] email for user with ID [%s] for [%s] event with ID [%s]" , events .EventTypeWebhookSendFailed , payload .UserID , payload .EventType , payload .EventID )
147+ return service .tracer .WrapErrorSpan (span , stacktrace .Propagate (err , msg ))
148+ }
149+
150+ ctxLogger .Info (fmt .Sprintf ("[%s] email sent to [%s] for [%s] event with ID [%s]" , events .EventTypeWebhookSendFailed , user .ID , payload .EventType , payload .EventID ))
151+
152+ service .addToCache (ctx , oneHourTimeout , events .EventTypeWebhookSendFailed , payload .Owner )
153+ return nil
154+ }
155+
156+ // NotifyDiscordSendFailed sends an email to the user about a failed discord webhook event
157+ func (service * EmailNotificationService ) NotifyDiscordSendFailed (ctx context.Context , payload * events.DiscordSendFailedPayload ) error {
158+ ctx , span , ctxLogger := service .tracer .StartWithLogger (ctx , service .logger )
159+ defer span .End ()
160+
161+ if ! service .canSendEmail (ctx , payload .EventType , payload .Owner ) {
162+ ctxLogger .Info (fmt .Sprintf ("[%s] email already sent to user [%s] with owner [%s]" , events .EventTypeWebhookSendFailed , payload .UserID , payload .Owner ))
163+ return nil
164+ }
165+
166+ user , err := service .userRepository .Load (ctx , payload .UserID )
167+ if err != nil {
168+ msg := fmt .Sprintf ("cannot load user with ID [%s] for [%s] event for message with ID [%s]" , payload .UserID , payload .EventType , payload .MessageID )
169+ return service .tracer .WrapErrorSpan (span , stacktrace .PropagateWithCode (err , stacktrace .GetCode (err ), msg ))
170+ }
171+
172+ email , err := service .factory .DiscordSendFailed (user , payload )
173+ if err != nil {
174+ msg := fmt .Sprintf ("cannot create email for user with ID [%s] for [%s] event and message with ID [%s]" , payload .UserID , payload .EventType , payload .MessageID )
175+ return service .tracer .WrapErrorSpan (span , stacktrace .Propagate (err , msg ))
176+ }
177+
178+ if err = service .mailer .Send (ctx , email ); err != nil {
179+ msg := fmt .Sprintf ("cannot send email for user with ID [%s] for [%s] message with ID [%s]" , payload .UserID , events .EventTypeMessageSendFailed , payload .MessageID )
180+ return service .tracer .WrapErrorSpan (span , stacktrace .Propagate (err , msg ))
181+ }
182+
183+ ctxLogger .Info (fmt .Sprintf ("[%s] email sent to [%s] for [%s] event with ID [%s]" , payload .EventType , user .ID , payload .EventType , payload .MessageID ))
184+
185+ service .addToCache (ctx , oneHourTimeout , events .EventTypeDiscordSendFailed , payload .Owner )
115186 return nil
116187}
117188
@@ -124,12 +195,12 @@ func (service *EmailNotificationService) canSendEmail(ctx context.Context, event
124195 return err != nil
125196}
126197
127- func (service * EmailNotificationService ) addToCache (ctx context.Context , event string , owner string ) {
198+ func (service * EmailNotificationService ) addToCache (ctx context.Context , timeout time. Duration , event string , owner string ) {
128199 ctx , span , ctxLogger := service .tracer .StartWithLogger (ctx , service .logger )
129200 defer span .End ()
130201
131202 cacheKey := service .getCacheKey (event , owner )
132- if err := service .cache .Set (ctx , cacheKey , "" , time . Minute * 15 ); err != nil {
203+ if err := service .cache .Set (ctx , cacheKey , "" , timeout ); err != nil {
133204 ctxLogger .Error (stacktrace .Propagate (err , fmt .Sprintf ("cannot set item in redis with key [%s] for owner [%s]" , cacheKey , owner )))
134205 }
135206}
0 commit comments