diff --git a/lib/icinga/checkable-check.cpp b/lib/icinga/checkable-check.cpp index d0c49b80e..da1e8bd39 100644 --- a/lib/icinga/checkable-check.cpp +++ b/lib/icinga/checkable-check.cpp @@ -242,6 +242,20 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig OnReachabilityChanged(this, cr, children, origin); } + if (recovery) { + for (auto& child : children) { + if (child->GetProblem() && child->GetEnableActiveChecks()) { + auto nextCheck (now + Utility::Random() % 60); + + ObjectLock oLock (child); + + if (nextCheck < child->GetNextCheck()) { + child->SetNextCheck(nextCheck); + } + } + } + } + if (!reachable) SetLastStateUnreachable(cr->GetExecutionEnd()); diff --git a/lib/icinga/checkable-notification.cpp b/lib/icinga/checkable-notification.cpp index 8dc0dfd58..7d9fcb6b1 100644 --- a/lib/icinga/checkable-notification.cpp +++ b/lib/icinga/checkable-notification.cpp @@ -10,6 +10,7 @@ #include "base/exception.hpp" #include "base/context.hpp" #include "base/convert.hpp" +#include "base/lazy-init.hpp" #include "remote/apilistener.hpp" using namespace icinga; @@ -145,35 +146,58 @@ static void FireSuppressedNotifications(Checkable* checkable) int subtract = 0; - for (auto type : {NotificationProblem, NotificationRecovery, NotificationFlappingStart, NotificationFlappingEnd}) { - if (suppressed_types & type) { - bool still_applies = checkable->NotificationReasonApplies(type); + { + LazyInit wasLastParentRecoveryRecent ([&checkable]() { + auto cr (checkable->GetLastCheckResult()); - if (still_applies) { - bool still_suppressed; + if (!cr) { + return true; + } - switch (type) { - case NotificationProblem: - /* Fall through. */ - case NotificationRecovery: - still_suppressed = !checkable->IsReachable(DependencyNotification) || checkable->IsInDowntime() || checkable->IsAcknowledged(); - break; - case NotificationFlappingStart: - /* Fall through. */ - case NotificationFlappingEnd: - still_suppressed = checkable->IsInDowntime(); - break; - default: - break; + auto threshold (cr->GetExecutionStart()); + + for (auto& dep : checkable->GetDependencies()) { + auto parent (dep->GetParent()); + ObjectLock oLock (parent); + + if (!parent->GetProblem() && parent->GetLastStateChange() >= threshold) { + return true; } + } - if (!still_suppressed && !checkable->IsLikelyToBeCheckedSoon()) { - Checkable::OnNotificationsRequested(checkable, type, checkable->GetLastCheckResult(), "", "", nullptr); + return false; + }); + for (auto type : {NotificationProblem, NotificationRecovery, NotificationFlappingStart, NotificationFlappingEnd}) { + if (suppressed_types & type) { + bool still_applies = checkable->NotificationReasonApplies(type); + + if (still_applies) { + bool still_suppressed; + + switch (type) { + case NotificationProblem: + /* Fall through. */ + case NotificationRecovery: + still_suppressed = !checkable->IsReachable(DependencyNotification) || checkable->IsInDowntime() || checkable->IsAcknowledged(); + break; + case NotificationFlappingStart: + /* Fall through. */ + case NotificationFlappingEnd: + still_suppressed = checkable->IsInDowntime(); + break; + default: + break; + } + + if (!still_suppressed && !checkable->IsLikelyToBeCheckedSoon() && !wasLastParentRecoveryRecent.Get()) { + Checkable::OnNotificationsRequested(checkable, type, checkable->GetLastCheckResult(), "", "", nullptr); + + subtract |= type; + } + } else { subtract |= type; } - } else { - subtract |= type; } } }