(ctx context.Context, event cloudevents.Event, owner string, webhook *entities.Webhook)
| 208 | } |
| 209 | |
| 210 | func (service *WebhookService) sendNotification(ctx context.Context, event cloudevents.Event, owner string, webhook *entities.Webhook) { |
| 211 | ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger) |
| 212 | defer span.End() |
| 213 | |
| 214 | attempts := 0 |
| 215 | err := retry.New(retry.Attempts(2)).Do(func() error { |
| 216 | attempts++ |
| 217 | |
| 218 | requestCtx, cancel := context.WithTimeout(ctx, 5*time.Second) |
| 219 | defer cancel() |
| 220 | |
| 221 | request, err := service.createRequest(requestCtx, event, webhook) |
| 222 | if err != nil { |
| 223 | msg := fmt.Sprintf("cannot create [%s] event to webhook [%s] for user [%s] after [%d] attempts", event.Type(), webhook.URL, webhook.UserID, attempts) |
| 224 | return service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg)) |
| 225 | } |
| 226 | |
| 227 | response, err := service.client.Do(request) |
| 228 | if err != nil { |
| 229 | ctxLogger.Warn(stacktrace.Propagate(err, fmt.Sprintf("cannot send [%s] event to webhook [%s] for user [%s] after [%d] attempts", event.Type(), webhook.URL, webhook.UserID, attempts))) |
| 230 | if attempts == 1 { |
| 231 | return err |
| 232 | } |
| 233 | service.handleWebhookSendFailed(ctx, event, webhook, owner, err, response) |
| 234 | return nil |
| 235 | } |
| 236 | |
| 237 | defer func() { |
| 238 | err = response.Body.Close() |
| 239 | if err != nil { |
| 240 | ctxLogger.Error(stacktrace.Propagate(err, fmt.Sprintf("cannot close response body for [%s] event with ID [%s] after [%d] attempts", event.Type(), event.ID(), attempts))) |
| 241 | } |
| 242 | }() |
| 243 | |
| 244 | if response.StatusCode >= 400 { |
| 245 | ctxLogger.Info(fmt.Sprintf("cannot send [%s] event to webhook [%s] for user [%s] with response code [%d] after [%d] attempts", event.Type(), webhook.URL, webhook.UserID, response.StatusCode, attempts)) |
| 246 | if attempts == 1 { |
| 247 | return stacktrace.NewError(http.StatusText(response.StatusCode)) |
| 248 | } |
| 249 | service.handleWebhookSendFailed(ctx, event, webhook, owner, stacktrace.NewError(http.StatusText(response.StatusCode)), response) |
| 250 | return nil |
| 251 | } |
| 252 | |
| 253 | ctxLogger.Info(fmt.Sprintf("sent webhook to url [%s] for event [%s] with ID [%s] and response code [%d]", webhook.URL, event.Type(), event.ID(), response.StatusCode)) |
| 254 | return nil |
| 255 | }) |
| 256 | if err != nil { |
| 257 | msg := fmt.Sprintf("cannot handle [%s] event to webhook [%s] for user [%s] after [%d] attempts", event.Type(), webhook.URL, webhook.UserID, attempts) |
| 258 | ctxLogger.Error(service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))) |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | func (service *WebhookService) createRequest(ctx context.Context, event cloudevents.Event, webhook *entities.Webhook) (*http.Request, error) { |
| 263 | ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger) |
no test coverage detected