Skip to content

Commit 3781d9b

Browse files
author
Steve Hansen
committed
fix: add deduplication check to SaveReportAsync
Prevent duplicate reports by checking if a report already exists for the same incidentId before saving. Returns bool to indicate if the report was saved (true) or skipped as duplicate (false). Worker now logs warnings when duplicates are detected, helping identify the root cause of duplicate report generation.
1 parent 5b1d965 commit 3781d9b

2 files changed

Lines changed: 29 additions & 5 deletions

File tree

src/FleetClaim.Core/Geotab/AddInDataRepository.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ public interface IAddInDataRepository
1414
Task<WorkerState?> GetWorkerStateAsync(IGeotabApi api, string database, CancellationToken ct = default);
1515
Task SaveWorkerStateAsync(IGeotabApi api, string database, WorkerState state, CancellationToken ct = default);
1616

17-
Task SaveReportAsync(IGeotabApi api, IncidentReport report, CancellationToken ct = default);
17+
/// <summary>
18+
/// Saves a report, checking for duplicates by incidentId.
19+
/// Returns true if saved, false if a report already exists for this incident.
20+
/// </summary>
21+
Task<bool> SaveReportAsync(IGeotabApi api, IncidentReport report, CancellationToken ct = default);
1822
Task SaveRequestAsync(IGeotabApi api, ReportRequest request, CancellationToken ct = default);
1923
Task UpdateRequestStatusAsync(IGeotabApi api, string requestId, ReportRequestStatus status, string? error = null, int? incidentsFound = null, int? reportsGenerated = null, string? errorMessage = null, CancellationToken ct = default);
2024

@@ -126,12 +130,23 @@ public async Task SaveWorkerStateAsync(IGeotabApi api, string database, WorkerSt
126130
}
127131
}
128132

129-
public async Task SaveReportAsync(IGeotabApi api, IncidentReport report, CancellationToken ct = default)
133+
public async Task<bool> SaveReportAsync(IGeotabApi api, IncidentReport report, CancellationToken ct = default)
130134
{
135+
// Check if a report already exists for this incident (deduplication)
136+
var whereClause = $"type == \"report\" && payload.incidentId == \"{report.IncidentId}\"";
137+
var existing = await GetFilteredAddInDataAsync(api, whereClause, ct);
138+
139+
if (existing.Count > 0)
140+
{
141+
// Report already exists for this incident - skip to prevent duplicates
142+
return false;
143+
}
144+
131145
// Compact the report to fit within AddInData 10KB limit
132146
var compactedReport = CompactReportForStorage(report);
133147
var wrapper = AddInDataWrapper.ForReport(compactedReport);
134148
await AddNewRecordAsync(api, wrapper, ct);
149+
return true;
135150
}
136151

137152
/// <summary>

src/FleetClaim.Worker/IncidentPollerWorker.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -743,10 +743,19 @@ private async Task GenerateAndSaveReportAsync(
743743
var report = await _reportGenerator.GenerateReportAsync(api, incident, database, ct);
744744
report.Source = source; // Set the source based on how the report was triggered
745745

746-
await _repository.SaveReportAsync(api, report, ct);
746+
var wasSaved = await _repository.SaveReportAsync(api, report, ct);
747747

748-
_logger.LogInformation("Saved report {ReportId} for incident {IncidentId}",
749-
report.Id, incident.Id);
748+
if (wasSaved)
749+
{
750+
_logger.LogInformation("Saved report {ReportId} for incident {IncidentId}",
751+
report.Id, incident.Id);
752+
}
753+
else
754+
{
755+
_logger.LogWarning("Skipped duplicate report for incident {IncidentId} - report already exists",
756+
incident.Id);
757+
return; // Don't send notifications for duplicates
758+
}
750759

751760
// Send notifications if configured
752761
if (report.Severity >= config.SeverityThreshold)

0 commit comments

Comments
 (0)