| 158 | } |
| 159 | |
| 160 | func (c *LongPollClient) pollEvents(ctx context.Context) error { |
| 161 | |
| 162 | initialBackoff := 1 * time.Second |
| 163 | maxBackoff := 30 * time.Second |
| 164 | currentBackoff := initialBackoff |
| 165 | |
| 166 | for { |
| 167 | select { |
| 168 | case <-c.t.Dying(): |
| 169 | c.logger.Debug("dying") |
| 170 | return nil |
| 171 | case <-ctx.Done(): |
| 172 | c.logger.Debug("context canceled") |
| 173 | return ctx.Err() |
| 174 | default: |
| 175 | c.logger.Debug("Polling PAPI") |
| 176 | err := c.poll(ctx) |
| 177 | if err != nil { |
| 178 | if errors.Is(err, errUnauthorized) { |
| 179 | c.logger.Errorf("unauthorized, stopping polling") |
| 180 | c.t.Kill(err) |
| 181 | close(c.c) |
| 182 | return err |
| 183 | } |
| 184 | if errors.Is(err, context.Canceled) { |
| 185 | c.logger.Debug("context canceled, stopping polling") |
| 186 | return nil |
| 187 | } |
| 188 | metrics.PapiPollErrors.Inc() |
| 189 | c.logger.Errorf("failed to poll: %s, retrying in %s", err, currentBackoff) |
| 190 | select { |
| 191 | case <-c.t.Dying(): |
| 192 | return nil |
| 193 | case <-ctx.Done(): |
| 194 | return ctx.Err() |
| 195 | case <-time.After(currentBackoff): |
| 196 | } |
| 197 | |
| 198 | currentBackoff *= 2 |
| 199 | if currentBackoff > maxBackoff { |
| 200 | currentBackoff = maxBackoff |
| 201 | } |
| 202 | continue |
| 203 | } |
| 204 | currentBackoff = initialBackoff |
| 205 | } |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | func (c *LongPollClient) Start(ctx context.Context, since time.Time) chan Event { |
| 210 | c.logger.Infof("starting polling client") |