summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--DomainDig/IntegrationService.swift58
1 files changed, 52 insertions, 6 deletions
diff --git a/DomainDig/IntegrationService.swift b/DomainDig/IntegrationService.swift
index 9c9541c..23085d3 100644
--- a/DomainDig/IntegrationService.swift
+++ b/DomainDig/IntegrationService.swift
@@ -100,9 +100,22 @@ final class IntegrationService {
func enqueue(events: [MonitoringEvent]) {
guard !events.isEmpty else { return }
- let eligibleTargets = targets.filter(\.isEnabled)
for event in events {
- for target in eligibleTargets {
+ for target in targets {
+ guard target.isEnabled else {
+ appendRecord(
+ DeliveryRecord(
+ integrationID: target.id,
+ eventID: event.id,
+ status: .skipped,
+ destination: destinationLabel(for: target),
+ summary: event.summary,
+ failureReason: Self.disabledTargetReason
+ )
+ )
+ continue
+ }
+
if let reason = filterMismatchReason(for: event, target: target) {
appendRecord(
DeliveryRecord(
@@ -150,7 +163,7 @@ final class IntegrationService {
}
func sendTest(for targetID: UUID) {
- guard targets.contains(where: { $0.id == targetID }) else { return }
+ guard let target = targets.first(where: { $0.id == targetID }) else { return }
let event = MonitoringEvent(
type: .test,
severity: .info,
@@ -161,13 +174,31 @@ final class IntegrationService {
"environment": "local-first"
]
)
- queue.append(QueuedDelivery(integrationID: targetID, event: event))
+
+ // Real events skip a disabled target, so a test event must too —
+ // otherwise a test succeeds against a target that silently drops
+ // everything monitoring sends it.
+ guard target.isEnabled else {
+ appendRecord(
+ DeliveryRecord(
+ integrationID: target.id,
+ eventID: event.id,
+ status: .skipped,
+ destination: destinationLabel(for: target),
+ summary: event.summary,
+ failureReason: Self.disabledTargetReason
+ )
+ )
+ return
+ }
+
+ queue.append(QueuedDelivery(integrationID: target.id, event: event))
appendRecord(
DeliveryRecord(
- integrationID: targetID,
+ integrationID: target.id,
eventID: event.id,
status: .pending,
- destination: targets.first(where: { $0.id == targetID }).map(destinationLabel(for:)) ?? "Unknown",
+ destination: destinationLabel(for: target),
summary: event.summary
)
)
@@ -175,7 +206,20 @@ final class IntegrationService {
scheduleProcessing()
}
+ /// Restarting the processing task alone leaves any item still in retry
+ /// backoff undue, so the loop would skip it and sleep again. Pulling every
+ /// queued item forward is what makes this button mean "now".
func processQueueNow() {
+ guard !queue.isEmpty else {
+ statusMessage = "No deliveries are waiting."
+ return
+ }
+
+ let now = Date()
+ for index in queue.indices {
+ queue[index].nextAttemptAt = now
+ }
+ persistQueue()
scheduleProcessing(force: true)
}
@@ -427,6 +471,8 @@ final class IntegrationService {
URL(string: string)?.host ?? "Configured"
}
+ private static let disabledTargetReason = "This integration is disabled."
+
private static func secretReference(for integrationID: UUID, suffix: String) -> String {
"integration.\(integrationID.uuidString).\(suffix)"
}