MCPcopy Index your code
hub / github.com/coder/coder / deliver

Method deliver

coderd/notifications/notifier.go:266–322  ·  view source on GitHub ↗

deliver sends a given notification message via its defined method. This method *only* returns an error when a context error occurs; any other error is interpreted as a failure to deliver the notification and as such the message will be marked as failed (to later be optionally retried).

(ctx context.Context, msg database.AcquireNotificationMessagesRow, deliver dispatch.DeliveryFunc, success, failure chan<- dispatchResult)

Source from the content-addressed store, hash-verified

264// This method *only* returns an error when a context error occurs; any other error is interpreted as a failure to
265// deliver the notification and as such the message will be marked as failed (to later be optionally retried).
266func (n *notifier) deliver(ctx context.Context, msg database.AcquireNotificationMessagesRow, deliver dispatch.DeliveryFunc, success, failure chan<- dispatchResult) error {
267 select {
268 case <-ctx.Done():
269 return ctx.Err()
270 default:
271 }
272
273 ctx, cancel := context.WithTimeout(ctx, n.cfg.DispatchTimeout.Value())
274 defer cancel()
275 logger := n.log.With(slog.F("msg_id", msg.ID), slog.F("method", msg.Method), slog.F("attempt", msg.AttemptCount+1))
276
277 if msg.AttemptCount > 0 {
278 n.metrics.RetryCount.WithLabelValues(string(msg.Method), msg.TemplateID.String()).Inc()
279 }
280
281 n.metrics.InflightDispatches.WithLabelValues(string(msg.Method), msg.TemplateID.String()).Inc()
282 n.metrics.QueuedSeconds.WithLabelValues(string(msg.Method)).Observe(msg.QueuedSeconds)
283
284 start := n.clock.Now()
285 retryable, err := deliver(ctx, msg.ID)
286
287 n.metrics.DispatcherSendSeconds.WithLabelValues(string(msg.Method)).Observe(n.clock.Since(start).Seconds())
288 n.metrics.InflightDispatches.WithLabelValues(string(msg.Method), msg.TemplateID.String()).Dec()
289
290 if err != nil {
291 // Don't try to accumulate message responses if the context has been canceled.
292 //
293 // This message's lease will expire in the store and will be requeued.
294 // It's possible this will lead to a message being delivered more than once, and that is why Stop() is preferable
295 // instead of canceling the context.
296 //
297 // In the case of backpressure (i.e. the success/failure channels are full because the database is slow),
298 // we can't append any more updates to the channels otherwise this, too, will block.
299 if xerrors.Is(err, context.Canceled) {
300 return err
301 }
302
303 select {
304 case <-ctx.Done():
305 logger.Warn(context.Background(), "cannot record dispatch failure result", slog.Error(ctx.Err()))
306 return ctx.Err()
307 case failure <- n.newFailedDispatch(msg, err, retryable):
308 logger.Warn(ctx, "message dispatch failed", slog.Error(err))
309 }
310 } else {
311 select {
312 case <-ctx.Done():
313 logger.Warn(context.Background(), "cannot record dispatch success result", slog.Error(ctx.Err()))
314 return ctx.Err()
315 case success <- n.newSuccessfulDispatch(msg):
316 logger.Debug(ctx, "message dispatch succeeded")
317 }
318 }
319 n.metrics.PendingUpdates.Set(float64(len(success) + len(failure)))
320
321 return nil
322}
323

Callers 1

processMethod · 0.95

Calls 10

newFailedDispatchMethod · 0.95
newSuccessfulDispatchMethod · 0.95
ErrMethod · 0.80
WithLabelValuesMethod · 0.80
SetMethod · 0.65
DoneMethod · 0.45
ValueMethod · 0.45
StringMethod · 0.45
IsMethod · 0.45
ErrorMethod · 0.45

Tested by

no test coverage detected