fix(stats): recover durable daily mileage projections
This commit is contained in:
@@ -888,6 +888,51 @@ func TestWriterPendingProjectionFailureDoesNotBlockOtherVehicles(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriterReconcilesDurableProjectionAfterPendingQueueIsLost(t *testing.T) {
|
||||
db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
|
||||
if err != nil {
|
||||
t.Fatalf("sqlmock.New() error = %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
writer := NewWriter(db, time.FixedZone("Asia/Shanghai", 8*3600))
|
||||
vin := "LMRKH9AC7R1004120"
|
||||
statDate := "2026-07-19"
|
||||
protocol := envelope.ProtocolJT808
|
||||
mock.ExpectQuery(staleDailyMileageProjectionTargetsSQL).
|
||||
WithArgs(statDate).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"vin", "protocol"}).AddRow(vin, string(protocol)))
|
||||
expectProjectDailyMileageSQL(mock, vin, statDate, protocol)
|
||||
mock.ExpectCommit()
|
||||
|
||||
result, err := writer.ReconcileDateProjections(context.Background(), statDate)
|
||||
if err != nil {
|
||||
t.Fatalf("ReconcileDateProjections() error = %v", err)
|
||||
}
|
||||
if result.Targets != 1 || result.Attempted != 1 || result.Written != 1 || result.Failed != 0 {
|
||||
t.Fatalf("reconcile result = %+v, want one recovered projection", result)
|
||||
}
|
||||
if got := writer.CacheStats().PendingProjectionEntries; got != 0 {
|
||||
t.Fatalf("startup reconciliation should not depend on pending memory, got %d entries", got)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("sql expectations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriterProjectionReconciliationRequiresQueryableStore(t *testing.T) {
|
||||
writer := NewWriter(&recordingExec{}, time.FixedZone("Asia/Shanghai", 8*3600))
|
||||
|
||||
result, err := writer.ReconcileDateProjections(context.Background(), "2026-07-19")
|
||||
|
||||
if err == nil || !strings.Contains(err.Error(), "query support") {
|
||||
t.Fatalf("ReconcileDateProjections() error = %v, want query support failure", err)
|
||||
}
|
||||
if result != (ProjectionReconcileResult{}) {
|
||||
t.Fatalf("reconcile result = %+v, want empty", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriterAppendProjectsImmediatelyForNewSource(t *testing.T) {
|
||||
exec := &recordingExec{}
|
||||
loc := time.FixedZone("Asia/Shanghai", 8*3600)
|
||||
|
||||
Reference in New Issue
Block a user