NewManager instantiates a new Manager instance which coordinates notification enqueuing and delivery. helpers is a map of template helpers which are used to customize notification messages to use global settings like access URL etc.
(cfg codersdk.NotificationsConfig, store Store, ps pubsub.Pubsub, helpers template.FuncMap, metrics *Metrics, log slog.Logger, opts ...ManagerOption)
| 78 | // helpers is a map of template helpers which are used to customize notification messages to use global settings like |
| 79 | // access URL etc. |
| 80 | func NewManager(cfg codersdk.NotificationsConfig, store Store, ps pubsub.Pubsub, helpers template.FuncMap, metrics *Metrics, log slog.Logger, opts ...ManagerOption) (*Manager, error) { |
| 81 | var method database.NotificationMethod |
| 82 | if err := method.Scan(cfg.Method.String()); err != nil { |
| 83 | return nil, xerrors.Errorf("notification method %q is invalid", cfg.Method) |
| 84 | } |
| 85 | |
| 86 | // If dispatch timeout exceeds lease period, it is possible that messages can be delivered in duplicate because the |
| 87 | // lease can expire before the notifier gives up on the dispatch, which results in the message becoming eligible for |
| 88 | // being re-acquired. |
| 89 | if cfg.DispatchTimeout.Value() >= cfg.LeasePeriod.Value() { |
| 90 | return nil, ErrInvalidDispatchTimeout |
| 91 | } |
| 92 | |
| 93 | m := &Manager{ |
| 94 | log: log, |
| 95 | cfg: cfg, |
| 96 | store: store, |
| 97 | |
| 98 | // Buffer successful/failed notification dispatches in memory to reduce load on the store. |
| 99 | // |
| 100 | // We keep separate buffered for success/failure right now because the bulk updates are already a bit janky, |
| 101 | // see BulkMarkNotificationMessagesSent/BulkMarkNotificationMessagesFailed. If we had the ability to batch updates, |
| 102 | // like is offered in https://docs.sqlc.dev/en/stable/reference/query-annotations.html#batchmany, we'd have a cleaner |
| 103 | // approach to this - but for now this will work fine. |
| 104 | success: make(chan dispatchResult, cfg.StoreSyncBufferSize), |
| 105 | failure: make(chan dispatchResult, cfg.StoreSyncBufferSize), |
| 106 | |
| 107 | metrics: metrics, |
| 108 | method: method, |
| 109 | |
| 110 | stop: make(chan any), |
| 111 | done: make(chan any), |
| 112 | |
| 113 | handlers: defaultHandlers(cfg, log, store, ps), |
| 114 | helpers: helpers, |
| 115 | |
| 116 | clock: quartz.NewReal(), |
| 117 | } |
| 118 | for _, o := range opts { |
| 119 | o(m) |
| 120 | } |
| 121 | return m, nil |
| 122 | } |
| 123 | |
| 124 | // defaultHandlers builds a set of known handlers; panics if any error occurs as these handlers should be valid at compile time. |
| 125 | func defaultHandlers(cfg codersdk.NotificationsConfig, log slog.Logger, store Store, ps pubsub.Pubsub) map[database.NotificationMethod]Handler { |