@@ -119,7 +119,7 @@ func (h *Handlers) actionsRunDelete(w http.ResponseWriter, r *http.Request) { |
| 119 | return | 119 | return |
| 120 | } | 120 | } |
| 121 | if h.d.ObjectStore != nil && len(objectKeys) > 0 { | 121 | if h.d.ObjectStore != nil && len(objectKeys) > 0 { |
| 122 | - go h.purgeArtifactObjects(objectKeys) | 122 | + go h.purgeArtifactObjects(context.WithoutCancel(r.Context()), objectKeys) |
| 123 | } | 123 | } |
| 124 | w.WriteHeader(http.StatusNoContent) | 124 | w.WriteHeader(http.StatusNoContent) |
| 125 | } | 125 | } |
@@ -128,8 +128,12 @@ func (h *Handlers) actionsRunDelete(w http.ResponseWriter, r *http.Request) { |
| 128 | // request lifecycle. Failures are logged but never surfaced — the | 128 | // request lifecycle. Failures are logged but never surfaced — the |
| 129 | // authoritative DB row is gone, and the cleanup sweeper retries | 129 | // authoritative DB row is gone, and the cleanup sweeper retries |
| 130 | // orphan-object deletion on its own schedule. | 130 | // orphan-object deletion on its own schedule. |
| 131 | -func (h *Handlers) purgeArtifactObjects(keys []string) { | 131 | +// |
| 132 | - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | 132 | +// parent is expected to be `context.WithoutCancel(r.Context())` so |
| | 133 | +// the goroutine survives response completion while still carrying |
| | 134 | +// trace/log values from the originating request. |
| | 135 | +func (h *Handlers) purgeArtifactObjects(parent context.Context, keys []string) { |
| | 136 | + ctx, cancel := context.WithTimeout(parent, 30*time.Second) |
| 133 | defer cancel() | 137 | defer cancel() |
| 134 | for _, k := range keys { | 138 | for _, k := range keys { |
| 135 | if err := h.d.ObjectStore.Delete(ctx, k); err != nil { | 139 | if err := h.d.ObjectStore.Delete(ctx, k); err != nil { |
@@ -247,7 +251,7 @@ func (h *Handlers) actionsArtifactDelete(w http.ResponseWriter, r *http.Request) |
| 247 | return | 251 | return |
| 248 | } | 252 | } |
| 249 | if h.d.ObjectStore != nil { | 253 | if h.d.ObjectStore != nil { |
| 250 | - go h.purgeArtifactObjects([]string{artifact.ObjectKey}) | 254 | + go h.purgeArtifactObjects(context.WithoutCancel(r.Context()), []string{artifact.ObjectKey}) |
| 251 | } | 255 | } |
| 252 | w.WriteHeader(http.StatusNoContent) | 256 | w.WriteHeader(http.StatusNoContent) |
| 253 | } | 257 | } |