@@ -38,9 +38,10 @@ type Service struct {
3838
3939 client client
4040
41- cache * cache.Cache [domain. Event ]
41+ cache * cache.Cache [eventWrapper ]
4242
4343 enqueuedCounter * prometheus.CounterVec
44+ retriesCounter * prometheus.CounterVec
4445
4546 logger * zap.Logger
4647}
@@ -60,12 +61,22 @@ func New(params Params) *Service {
6061 Help : "Total number of messages enqueued" ,
6162 }, []string {"event" })
6263
64+ retriesCounter := promauto .NewCounterVec (prometheus.CounterOpts {
65+ Namespace : "sms" ,
66+ Subsystem : "push" ,
67+ Name : "retries_total" ,
68+ Help : "Total retry attempts" ,
69+ }, []string {"outcome" })
70+
6371 return & Service {
64- config : params .Config ,
65- client : params .Client ,
66- cache : cache.New [domain.Event ](cache.Config {}),
72+ config : params .Config ,
73+ client : params .Client ,
74+ cache : cache.New [eventWrapper ](cache.Config {}),
75+
6776 enqueuedCounter : enqueuedCounter ,
68- logger : params .Logger ,
77+ retriesCounter : retriesCounter ,
78+
79+ logger : params .Logger ,
6980 }
7081}
7182
@@ -86,7 +97,13 @@ func (s *Service) Run(ctx context.Context) {
8697
8798// Enqueue adds the data to the cache and immediately sends all messages if the debounce is 0.
8899func (s * Service ) Enqueue (token string , event * domain.Event ) error {
89- if err := s .cache .Set (token , * event ); err != nil {
100+ wrapper := eventWrapper {
101+ token : token ,
102+ event : * event ,
103+ retries : 0 ,
104+ }
105+
106+ if err := s .cache .Set (token , wrapper ); err != nil {
90107 return fmt .Errorf ("can't add message to cache: %w" , err )
91108 }
92109
@@ -102,9 +119,35 @@ func (s *Service) sendAll(ctx context.Context) {
102119 return
103120 }
104121
105- s .logger .Info ("Sending messages" , zap .Int ("count" , len (targets )))
122+ messages := make (map [string ]domain.Event , len (targets ))
123+ for _ , w := range targets {
124+ if w .retries >= 3 {
125+ s .retriesCounter .WithLabelValues ("max_attempts" ).Inc ()
126+ s .logger .Warn ("Retries exceeded" , zap .String ("token" , w .token ))
127+ continue
128+ }
129+
130+ messages [w .token ] = w .event
131+ }
132+
133+ if len (messages ) == 0 {
134+ return
135+ }
136+
137+ s .logger .Info ("Sending messages" , zap .Int ("count" , len (messages )))
106138 ctx , cancel := context .WithTimeout (ctx , s .config .Timeout )
107- if err := s .client .Send (ctx , targets ); err != nil {
139+ if errs , err := s .client .Send (ctx , messages ); err != nil {
140+ for token := range errs {
141+ wrapper := targets [token ]
142+ wrapper .retries ++
143+ if s .cache .SetOrFail (token , wrapper ) != nil {
144+ s .logger .Info ("Can't set message to cache" , zap .Error (err ))
145+ } else {
146+ s .logger .Info ("Retrying message" , zap .String ("token" , token ))
147+ }
148+ s .retriesCounter .WithLabelValues ("retried" ).Inc ()
149+ }
150+
108151 s .logger .Error ("Can't send messages" , zap .Error (err ))
109152 }
110153 cancel ()
0 commit comments