diff options
| author | Christian Cleberg <[email protected]> | 2026-07-20 15:31:51 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-07-20 15:52:42 -0500 |
| commit | 8b661d9f36381ee432ece5e77a17d5ae6357d327 (patch) | |
| tree | 3c4fb904b2fcae44f060a387cd2c469fd51597fe /DomainDig | |
| parent | d9bd61cc745b3f1d6ff481fd300abf3216d07d48 (diff) | |
| download | domain-dig-8b661d9f36381ee432ece5e77a17d5ae6357d327.tar.gz domain-dig-8b661d9f36381ee432ece5e77a17d5ae6357d327.tar.bz2 domain-dig-8b661d9f36381ee432ece5e77a17d5ae6357d327.zip | |
fix: make disabled targets and forced queue processing visible
Closes #8, closes #9.
enqueue(events:) filtered to enabled targets before writing any
DeliveryRecord, so events routed to a disabled integration disappeared
with nothing in the Delivery Log. Disabled targets now record a .skipped
entry with a reason, matching how filter mismatches are already surfaced.
sendTest bypassed the isEnabled check entirely, so a test event
delivered against a target that silently dropped every real event —
exactly the wrong signal when someone is verifying their setup. It now
skips with the same reason.
processQueueNow only restarted the processing task; it never moved
nextAttemptAt, so an item in retry backoff stayed undue and the fresh
task went straight back to sleep. Backoff reaches an hour, so the button
appeared inert for the one case it exists to handle. It now pulls every
queued item forward, and reports when the queue is empty instead of
returning silently.
Diffstat (limited to 'DomainDig')
| -rw-r--r-- | DomainDig/IntegrationService.swift | 58 |
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)" } |
