Skip to content

Commit d39c46b

Browse files
committed
Upload thermal reading to timeseries on completion
Inject ITimeseriesService into ThermalReadingResultHandler and upload the temperature reading after publishing the MQTT result, restoring the legacy behaviour from the pre-refactor ThermalReadingNotificationController.
1 parent a8b6a43 commit d39c46b

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

api.Tests/Services/ResultHandlers/WorkflowResultHandlers/ThermalReadingResultHandlerTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,40 @@ public async Task OnWorkflowCompleted_NullResultJson_PublishesMessageWithNullVal
138138
Assert.Null(published.Value);
139139
Assert.Null(published.Confidence);
140140
}
141+
142+
[Fact]
143+
public async Task OnWorkflowCompleted_ValidResult_UploadsTimeseries()
144+
{
145+
var record = await _db.NewInspectionRecord(inspectionId: "insp-123");
146+
var analysis = await _db.NewAnalysis(inspectionRecords: [record]);
147+
var run = await _db.NewAnalysisRun(analysis);
148+
var workflow = await _db.NewWorkflow(run, workflowType: "thermal-reading");
149+
const float temperature = 23.5f;
150+
workflow.ResultJson = JsonSerializer.Serialize(new { temperature = temperature });
151+
await _context.SaveChangesAsync(TestContext.Current.CancellationToken);
152+
153+
using var scope = _factory.Services.CreateScope();
154+
var handler = ResolveHandler(scope);
155+
156+
await handler.OnWorkflowCompleted(workflow);
157+
158+
var upload = Assert.Single(_factory.TimeseriesService.Uploads);
159+
Assert.Equal(temperature, upload.Value);
160+
}
161+
162+
[Fact]
163+
public async Task OnWorkflowCompleted_NullResultJson_DoesNotUploadTimeseries()
164+
{
165+
var record = await _db.NewInspectionRecord(inspectionId: "insp-123");
166+
var analysis = await _db.NewAnalysis(inspectionRecords: [record]);
167+
var run = await _db.NewAnalysisRun(analysis);
168+
var workflow = await _db.NewWorkflow(run, workflowType: "thermal-reading");
169+
170+
using var scope = _factory.Services.CreateScope();
171+
var handler = ResolveHandler(scope);
172+
173+
await handler.OnWorkflowCompleted(workflow);
174+
175+
Assert.Empty(_factory.TimeseriesService.Uploads);
176+
}
141177
}

api/Services/ResultHandlers/WorkflowResultHandlers/ThermalReadingResultHandler.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ internal sealed class ThermalReadingResult
1515
public class ThermalReadingResultHandler(
1616
SaraDbContext context,
1717
IMqttPublisherService mqttPublisherService,
18+
ITimeseriesService timeseriesService,
1819
ILogger<ThermalReadingResultHandler> logger
1920
) : IWorkflowResultHandler
2021
{
@@ -75,5 +76,56 @@ public async Task OnWorkflowCompleted(Workflow workflow)
7576
}
7677

7778
await mqttPublisherService.PublishSaraAnalysisResultAvailable(message);
79+
80+
await TryUploadTimeseries(workflow, inspectionRecord, result);
81+
}
82+
83+
private async Task TryUploadTimeseries(
84+
Workflow workflow,
85+
InspectionRecord inspectionRecord,
86+
ThermalReadingResult? result
87+
)
88+
{
89+
if (result is null)
90+
{
91+
logger.LogWarning(
92+
"Skipping thermal-reading timeseries upload for workflow {WorkflowId}: result is null",
93+
workflow.Id
94+
);
95+
return;
96+
}
97+
98+
var uploadRequest = new TriggerTimeseriesUploadRequest
99+
{
100+
Name =
101+
$"{inspectionRecord.InstallationCode}_{inspectionRecord.Tag}_{inspectionRecord.InspectionDescription?.Replace(" ", "-")}",
102+
Facility = inspectionRecord.InstallationCode,
103+
ExternalId = "",
104+
Description = "ThermalReading",
105+
Unit = "°C",
106+
AssetId = inspectionRecord.InstallationCode,
107+
Value = result.Temperature,
108+
Timestamp = inspectionRecord.Timestamp ?? DateTime.UtcNow,
109+
Step = true,
110+
Metadata = new Dictionary<string, string>
111+
{
112+
{ "tag_id", inspectionRecord.Tag ?? "" },
113+
{ "inspection_description", inspectionRecord.InspectionDescription ?? "" },
114+
{ "robot_name", inspectionRecord.RobotName ?? "" },
115+
},
116+
};
117+
118+
try
119+
{
120+
await timeseriesService.TriggerTimeseriesUpload(uploadRequest);
121+
}
122+
catch (Exception ex)
123+
{
124+
logger.LogError(
125+
ex,
126+
"Failed to upload thermal-reading datapoint to Timeseries for workflow {WorkflowId}",
127+
workflow.Id
128+
);
129+
}
78130
}
79131
}

0 commit comments

Comments
 (0)