(uid string)
| 463 | } |
| 464 | |
| 465 | func (m *Manager) requestCancellation(uid string) (invocationState, bool) { |
| 466 | m.invStateMux.Lock() |
| 467 | defer m.invStateMux.Unlock() |
| 468 | |
| 469 | rec, ok := m.invState[uid] |
| 470 | if !ok || rec == nil { |
| 471 | return 0, false |
| 472 | } |
| 473 | |
| 474 | // For stateQueued we deliberately ignore the cancel entirely: no |
| 475 | // cancelRequested flag, no ctx cancellation, no fallback timer, no |
| 476 | // tombstone. Reason: dyncfg commands (enable/disable/update/restart) |
| 477 | // carry side-effects that must reach jobmgr, otherwise the wait gate |
| 478 | // stays in 'accepted' forever (since the wait-decision timeout was |
| 479 | // removed). Setting cancelRequested would make startInvocation skip the |
| 480 | // handler when the worker pulls; the fallback timer's tryFinalize would |
| 481 | // also tombstone+remove from invState before the worker gets there. So |
| 482 | // either path wedges the function. We let it run to completion as if |
| 483 | // nothing happened; netdata already considers the transaction done (it |
| 484 | // 504'd before sending CANCEL), so the eventual terminal response just |
| 485 | // produces a benign "transaction not found" log on the netdata side. |
| 486 | if rec.state == stateQueued { |
| 487 | return rec.state, true |
| 488 | } |
| 489 | |
| 490 | if rec.cancelRequested { |
| 491 | return rec.state, true |
| 492 | } |
| 493 | rec.cancelRequested = true |
| 494 | if rec.cancel != nil { |
| 495 | rec.cancel() |
| 496 | } |
| 497 | |
| 498 | m.startCancelFallbackTimerLocked(uid, rec) |
| 499 | |
| 500 | return rec.state, true |
| 501 | } |
| 502 | |
| 503 | func (m *Manager) setStopping(v bool) { |
| 504 | m.stopping.Store(v) |
no test coverage detected