diff --git a/plugin/webhook/webhook.go b/plugin/webhook/webhook.go index a9b846cd7..af1724ffe 100644 --- a/plugin/webhook/webhook.go +++ b/plugin/webhook/webhook.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "io" + "log/slog" "net/http" "time" @@ -63,3 +64,17 @@ func Post(requestPayload *v1pb.WebhookRequestPayload) error { return nil } + +// PostAsync posts the message to webhook endpoint asynchronously. +// It spawns a new goroutine to handle the request and does not wait for the response. +func PostAsync(requestPayload *v1pb.WebhookRequestPayload) { + go func() { + if err := Post(requestPayload); err != nil { + // Since we're in a goroutine, we can only log the error + slog.Warn("Failed to dispatch webhook asynchronously", + slog.String("url", requestPayload.Url), + slog.String("activityType", requestPayload.ActivityType), + slog.Any("err", err)) + } + }() +} diff --git a/server/router/api/v1/memo_service.go b/server/router/api/v1/memo_service.go index 3053b6c6f..399ea7197 100644 --- a/server/router/api/v1/memo_service.go +++ b/server/router/api/v1/memo_service.go @@ -689,9 +689,9 @@ func (s *APIV1Service) dispatchMemoRelatedWebhook(ctx context.Context, memo *v1p } payload.ActivityType = activityType payload.Url = hook.URL - if err := webhook.Post(payload); err != nil { - return errors.Wrap(err, "failed to post webhook") - } + + // Use asynchronous webhook dispatch + webhook.PostAsync(payload) } return nil }