Add data-aware batch planning
This commit is contained in:
@@ -2237,7 +2237,7 @@ func TestRunBatchContinuesAfterReportFailure(t *testing.T) {
|
||||
server := dailyBundleServer(t)
|
||||
cfg := dailyWorkspaceConfig(t, server)
|
||||
renderer := &selectiveRenderer{
|
||||
failRenderPrompt: "weather.three_day_outlook",
|
||||
failRenderPrompt: "weather.tomorrow_generated_text",
|
||||
runBody: "# Batch Report\n",
|
||||
}
|
||||
|
||||
@@ -2251,23 +2251,23 @@ func TestRunBatchContinuesAfterReportFailure(t *testing.T) {
|
||||
t.Fatalf("RunBatchDetailed() error = %v", err)
|
||||
}
|
||||
|
||||
if result.Total != 3 || result.Succeeded != 2 || result.Failed != 1 {
|
||||
t.Fatalf("summary total/succeeded/failed = %d/%d/%d, want 3/2/1", result.Total, result.Succeeded, result.Failed)
|
||||
if result.Total != 2 || result.Succeeded != 1 || result.Failed != 1 {
|
||||
t.Fatalf("summary total/succeeded/failed = %d/%d/%d, want 2/1/1", result.Total, result.Succeeded, result.Failed)
|
||||
}
|
||||
if renderer.runCalls != 1 || renderer.structuredRunCalls != 1 {
|
||||
if renderer.runCalls != 0 || renderer.structuredRunCalls != 1 {
|
||||
t.Fatalf("renderer calls run=%d structured=%d, want successful reports to continue", renderer.runCalls, renderer.structuredRunCalls)
|
||||
}
|
||||
var failedThreeDay bool
|
||||
var failedTomorrow bool
|
||||
for _, item := range result.Reports {
|
||||
if item.ReportID == report.ThreeDay && item.Status == "failed" && strings.Contains(item.Error, "render failed") {
|
||||
failedThreeDay = true
|
||||
if item.ReportID == report.Tomorrow && item.Status == "failed" && strings.Contains(item.Error, "render failed") {
|
||||
failedTomorrow = true
|
||||
}
|
||||
if item.ReportID != report.ThreeDay && item.Status != "succeeded" {
|
||||
if item.ReportID != report.Tomorrow && item.Status != "succeeded" {
|
||||
t.Fatalf("report %s status = %s, want succeeded", item.ReportID, item.Status)
|
||||
}
|
||||
}
|
||||
if !failedThreeDay {
|
||||
t.Fatalf("reports = %#v, want failed 3-day item", result.Reports)
|
||||
if !failedTomorrow {
|
||||
t.Fatalf("reports = %#v, want failed Tomorrow item", result.Reports)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2276,7 +2276,7 @@ func TestRunBatchContinuesAfterNotificationFailure(t *testing.T) {
|
||||
cfg := dailyNotificationConfig(t, server)
|
||||
notifier := &recordingNotifier{
|
||||
errByReport: map[report.ID]error{
|
||||
report.ThreeDay: errors.New("distributor unavailable"),
|
||||
report.Tomorrow: errors.New("distributor unavailable"),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2291,26 +2291,26 @@ func TestRunBatchContinuesAfterNotificationFailure(t *testing.T) {
|
||||
t.Fatalf("RunBatchDetailed() error = %v", err)
|
||||
}
|
||||
|
||||
if result.Total != 3 || result.Succeeded != 2 || result.Failed != 1 {
|
||||
t.Fatalf("summary total/succeeded/failed = %d/%d/%d, want 3/2/1", result.Total, result.Succeeded, result.Failed)
|
||||
if result.Total != 2 || result.Succeeded != 1 || result.Failed != 1 {
|
||||
t.Fatalf("summary total/succeeded/failed = %d/%d/%d, want 2/1/1", result.Total, result.Succeeded, result.Failed)
|
||||
}
|
||||
if len(notifier.requests) != 3 {
|
||||
if len(notifier.requests) != 2 {
|
||||
t.Fatalf("notification requests = %d, want one per generated report", len(notifier.requests))
|
||||
}
|
||||
var failedThreeDay bool
|
||||
var failedTomorrow bool
|
||||
for _, item := range result.Reports {
|
||||
if item.ReportID == report.ThreeDay {
|
||||
if item.ReportID == report.Tomorrow {
|
||||
if item.Status == "failed" && strings.Contains(item.Error, "notify report") && strings.Contains(item.Error, "distributor unavailable") {
|
||||
failedThreeDay = true
|
||||
failedTomorrow = true
|
||||
}
|
||||
if item.NotificationStatus != "failed" {
|
||||
t.Fatalf("3-day notification status = %q, want failed", item.NotificationStatus)
|
||||
t.Fatalf("Tomorrow notification status = %q, want failed", item.NotificationStatus)
|
||||
}
|
||||
if item.NotificationPipelineID != "weatherreporter.three-day" {
|
||||
t.Fatalf("3-day notification pipeline = %q, want weatherreporter.three-day", item.NotificationPipelineID)
|
||||
if item.NotificationPipelineID != "weatherreporter.tomorrow" {
|
||||
t.Fatalf("Tomorrow notification pipeline = %q, want weatherreporter.tomorrow", item.NotificationPipelineID)
|
||||
}
|
||||
if !strings.Contains(item.NotificationError, "distributor unavailable") {
|
||||
t.Fatalf("3-day notification error = %q, want distributor unavailable", item.NotificationError)
|
||||
t.Fatalf("Tomorrow notification error = %q, want distributor unavailable", item.NotificationError)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -2324,8 +2324,8 @@ func TestRunBatchContinuesAfterNotificationFailure(t *testing.T) {
|
||||
t.Fatalf("report %s notification pipeline is empty", item.ReportID)
|
||||
}
|
||||
}
|
||||
if !failedThreeDay {
|
||||
t.Fatalf("reports = %#v, want notification failure on 3-day item", result.Reports)
|
||||
if !failedTomorrow {
|
||||
t.Fatalf("reports = %#v, want notification failure on Tomorrow item", result.Reports)
|
||||
}
|
||||
|
||||
cfg.Workspace.Root = t.TempDir()
|
||||
@@ -2338,7 +2338,7 @@ func TestRunBatchContinuesAfterNotificationFailure(t *testing.T) {
|
||||
},
|
||||
Notifier: &recordingNotifier{
|
||||
errByReport: map[report.ID]error{
|
||||
report.ThreeDay: errors.New("distributor unavailable"),
|
||||
report.Tomorrow: errors.New("distributor unavailable"),
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -2346,7 +2346,7 @@ func TestRunBatchContinuesAfterNotificationFailure(t *testing.T) {
|
||||
if !errors.As(err, &batchErr) {
|
||||
t.Fatalf("RunBatch() error = %T %v, want BatchError", err, err)
|
||||
}
|
||||
if batchErr.Result == nil || batchErr.Result.Failed != 1 || batchErr.Result.Succeeded != 2 {
|
||||
if batchErr.Result == nil || batchErr.Result.Failed != 1 || batchErr.Result.Succeeded != 1 {
|
||||
t.Fatalf("RunBatch() result = %#v, want notification failure aggregate", batchErr.Result)
|
||||
}
|
||||
}
|
||||
@@ -2404,7 +2404,7 @@ func TestRunBatchMorningUsesTodayOutputName(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("RunBatchDetailed() error = %v", err)
|
||||
}
|
||||
if result.Failed != 0 || len(result.Reports) != 3 {
|
||||
if result.Failed != 0 || len(result.Reports) != 2 {
|
||||
t.Fatalf("summary = %#v, want successful morning batch", result)
|
||||
}
|
||||
var todayItem *BatchReportResult
|
||||
@@ -2448,26 +2448,18 @@ func TestRunBatchDetailedUsesProvidedCollector(t *testing.T) {
|
||||
collector := &recordingCollector{err: errors.New("batch collector failed")}
|
||||
renderer := &recordingRenderer{}
|
||||
|
||||
result, err := RunBatchDetailed(context.Background(), BatchRequest{
|
||||
_, err := RunBatchDetailed(context.Background(), BatchRequest{
|
||||
Config: cfg,
|
||||
Batch: BatchMorning,
|
||||
Now: mustParse("2026-05-29T05:00:00-05:00"),
|
||||
Collector: collector,
|
||||
Renderer: renderer,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("RunBatchDetailed() error = %v", err)
|
||||
if err == nil || !strings.Contains(err.Error(), "batch collector failed") {
|
||||
t.Fatalf("RunBatchDetailed() error = %v, want fake collector error", err)
|
||||
}
|
||||
if result.Total == 0 || result.Failed != result.Total {
|
||||
t.Fatalf("batch result = %#v, want every report failed by collector", result)
|
||||
}
|
||||
if len(collector.requests) != result.Total {
|
||||
t.Fatalf("collector requests = %d, want %d", len(collector.requests), result.Total)
|
||||
}
|
||||
for _, reportResult := range result.Reports {
|
||||
if !strings.Contains(reportResult.Error, "batch collector failed") {
|
||||
t.Fatalf("report error = %q, want fake collector error", reportResult.Error)
|
||||
}
|
||||
if len(collector.requests) != 1 {
|
||||
t.Fatalf("collector requests = %d, want one planning collection", len(collector.requests))
|
||||
}
|
||||
if renderer.renderCalls != 0 || renderer.runCalls != 0 || renderer.structuredRunCalls != 0 {
|
||||
t.Fatalf("renderer calls render=%d run=%d structured=%d, want none after collection failure", renderer.renderCalls, renderer.runCalls, renderer.structuredRunCalls)
|
||||
|
||||
Reference in New Issue
Block a user