diff options
| author | Christian Cleberg <[email protected]> | 2026-04-24 15:04:54 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-04-24 15:04:54 -0500 |
| commit | 3f0b7746b1bee4c2f626eb805e3fd13c5f2f5d22 (patch) | |
| tree | 17c710faf6191ac86ea5b6cab4df240cf2cefef9 /DomainDataPortabilityService.swift | |
| parent | d0b3b7a15b59266b4ae4262fdb0364245092c17c (diff) | |
| download | domain-dig-3f0b7746b1bee4c2f626eb805e3fd13c5f2f5d22.tar.gz domain-dig-3f0b7746b1bee4c2f626eb805e3fd13c5f2f5d22.tar.bz2 domain-dig-3f0b7746b1bee4c2f626eb805e3fd13c5f2f5d22.zip | |
DomainDig v3.8.0 — Smart Monitoring
* Stable domain intervals
* Frequent changes decrease intervals
* Duplicate states do not trigger alerts
* Quiet hours suppress alerts
* Quiet hours across midnight work correctly
* Sensitivity levels alter behavior as expected
Diffstat (limited to 'DomainDataPortabilityService.swift')
| -rw-r--r-- | DomainDataPortabilityService.swift | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/DomainDataPortabilityService.swift b/DomainDataPortabilityService.swift index fabdfdd..ab0bc0b 100644 --- a/DomainDataPortabilityService.swift +++ b/DomainDataPortabilityService.swift @@ -231,7 +231,9 @@ enum DataPortabilityCSV { certificateWarningLevel: certificateLevel, certificateDaysRemaining: Int(row["certificateDaysRemaining"] ?? ""), lastMonitoredAt: parseDate(row["lastMonitoredAt"]), - lastAlertAt: parseDate(row["lastAlertAt"]) + lastAlertAt: parseDate(row["lastAlertAt"]), + monitoringState: MonitoringState(), + pendingMonitoringAlerts: [] ) } } @@ -1104,7 +1106,9 @@ enum DomainDataPortabilityService { certificateWarningLevel: higherCertificateWarningLevel(existing.certificateWarningLevel, incoming.certificateWarningLevel), certificateDaysRemaining: winner.certificateDaysRemaining ?? existing.certificateDaysRemaining ?? incoming.certificateDaysRemaining, lastMonitoredAt: [existing.lastMonitoredAt, incoming.lastMonitoredAt].compactMap { $0 }.max(), - lastAlertAt: [existing.lastAlertAt, incoming.lastAlertAt].compactMap { $0 }.max() + lastAlertAt: [existing.lastAlertAt, incoming.lastAlertAt].compactMap { $0 }.max(), + monitoringState: preferredMonitoringState(existing.monitoringState, incoming.monitoringState), + pendingMonitoringAlerts: deduplicatedPendingAlerts(existing.pendingMonitoringAlerts + incoming.pendingMonitoringAlerts) ) } @@ -1272,10 +1276,30 @@ enum DomainDataPortabilityService { certificateWarningLevel: trackedDomain.certificateWarningLevel, certificateDaysRemaining: trackedDomain.certificateDaysRemaining, lastMonitoredAt: trackedDomain.lastMonitoredAt, - lastAlertAt: trackedDomain.lastAlertAt + lastAlertAt: trackedDomain.lastAlertAt, + monitoringState: trackedDomain.monitoringState, + pendingMonitoringAlerts: trackedDomain.pendingMonitoringAlerts ) } + private static func preferredMonitoringState(_ lhs: MonitoringState, _ rhs: MonitoringState) -> MonitoringState { + let lhsDate = [lhs.lastCheck, lhs.lastAlertDate, lhs.lastChangeDate].compactMap { $0 }.max() ?? .distantPast + let rhsDate = [rhs.lastCheck, rhs.lastAlertDate, rhs.lastChangeDate].compactMap { $0 }.max() ?? .distantPast + return lhsDate >= rhsDate ? lhs : rhs + } + + private static func deduplicatedPendingAlerts(_ alerts: [MonitoringPendingAlert]) -> [MonitoringPendingAlert] { + var uniqueByHash: [String: MonitoringPendingAlert] = [:] + for alert in alerts { + if let existing = uniqueByHash[alert.changeHash] { + uniqueByHash[alert.changeHash] = existing.detectedAt >= alert.detectedAt ? existing : alert + } else { + uniqueByHash[alert.changeHash] = alert + } + } + return uniqueByHash.values.sorted { $0.detectedAt < $1.detectedAt } + } + private static func normalizedWorkflow(_ workflow: DomainWorkflow) -> DomainWorkflow { DomainWorkflow( id: workflow.id, |
