feat(platform): harden telemetry pipeline and unify Semi UI workspaces

This commit is contained in:
lingniu
2026-07-18 00:26:36 +08:00
parent 65b4e4f055
commit 159c80b0ae
136 changed files with 21616 additions and 1785 deletions

View File

@@ -1091,6 +1091,91 @@ func TestWriterRetriesExpiredMissingPreviousDayBaseline(t *testing.T) {
}
}
func TestWriterRefreshesExpiredFoundPreviousDayBaseline(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("sqlmock.New() error = %v", err)
}
defer db.Close()
loc := time.FixedZone("Asia/Shanghai", 8*3600)
writer := NewWriter(db, loc)
writer.SetBaselineHitTTL(time.Minute)
candidate := SourceMileageSample{
VIN: "LMRKH9AC6R1004111",
StatDate: "2026-07-17",
Protocol: envelope.ProtocolYutongMQTT,
SourceKey: "YUTONG_MQTT:LMRKH9AC6R1004111@PLATFORM:yutong",
}
cacheKey := mileageCacheKey(MetricSample{
VIN: candidate.VIN,
Protocol: candidate.Protocol,
StatDate: candidate.StatDate,
SourceKey: candidate.SourceKey,
})
staleTime := time.Date(2026, 7, 12, 4, 12, 20, 0, loc)
writer.baselineCache[cacheKey] = sourceBaselineCacheEntry{
baseline: sourceBaseline{LatestTotalKM: 90778, LatestEventTime: staleTime},
found: true,
cachedAt: time.Now().Add(-2 * time.Minute),
}
refreshedTime := time.Date(2026, 7, 16, 23, 59, 59, 0, loc)
mock.ExpectQuery(`SELECT latest_total_mileage_km, latest_event_time FROM vehicle_daily_mileage_source`).
WithArgs(candidate.VIN, candidate.StatDate, "YUTONG_MQTT", candidate.SourceKey).
WillReturnRows(sqlmock.NewRows([]string{"latest_total_mileage_km", "latest_event_time"}).
AddRow(91302.0, refreshedTime))
baseline, found, err := writer.previousBaseline(context.Background(), candidate)
if err != nil || !found {
t.Fatalf("previousBaseline() found=%v error=%v, want refreshed baseline", found, err)
}
if baseline.LatestTotalKM != 91302 || !baseline.LatestEventTime.Equal(refreshedTime) {
t.Fatalf("baseline = %+v, want nearest refreshed baseline", baseline)
}
if err := mock.ExpectationsWereMet(); err != nil {
t.Fatalf("sql expectations: %v", err)
}
}
func TestWriterMarkBaselineKeepsCacheAgeForUnchangedBoundary(t *testing.T) {
db, _, err := sqlmock.New()
if err != nil {
t.Fatalf("sqlmock.New() error = %v", err)
}
defer db.Close()
loc := time.FixedZone("Asia/Shanghai", 8*3600)
writer := NewWriter(db, loc)
candidate := SourceMileageSample{
VIN: "LMRKH9AC6R1004111",
StatDate: "2026-07-17",
Protocol: envelope.ProtocolYutongMQTT,
SourceKey: "YUTONG_MQTT:LMRKH9AC6R1004111@PLATFORM:yutong",
FirstTotalKM: 91302,
FirstEventTime: time.Date(2026, 7, 16, 23, 59, 59, 0, loc),
}
sample := MetricSample{
VIN: candidate.VIN,
Protocol: candidate.Protocol,
StatDate: candidate.StatDate,
SourceKey: candidate.SourceKey,
}
cacheKey := mileageCacheKey(sample)
cachedAt := time.Now().Add(-4 * time.Minute)
writer.baselineCache[cacheKey] = sourceBaselineCacheEntry{
baseline: sourceBaseline{LatestTotalKM: candidate.FirstTotalKM, LatestEventTime: candidate.FirstEventTime},
found: true,
cachedAt: cachedAt,
}
writer.markBaselineWritten(sample, candidate)
if got := writer.baselineCache[cacheKey].cachedAt; !got.Equal(cachedAt) {
t.Fatalf("cachedAt = %s, want unchanged %s", got, cachedAt)
}
}
func TestWriterAppendUsesPreviousSourceBaselineForRealtimeCandidate(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {