(t *testing.T)
| 263 | } |
| 264 | |
| 265 | func TestBatchNodeItemRetryAndFallback(t *testing.T) { |
| 266 | itemExecCounts := make(map[string]int) |
| 267 | itemFallbackCalled := make(map[string]bool) |
| 268 | |
| 269 | bnode := pf.NewBatchNode(). |
| 270 | SetRetry(3, 1*time.Millisecond). // Use time.Millisecond - Retries per item |
| 271 | SetPrep(func(ctx *pf.PfContext, params map[string]any) ([]any, error) { |
| 272 | return []any{"ok", "fail_once", "fail_always"}, nil |
| 273 | }). |
| 274 | SetExecItem(func(ctx *pf.PfContext, params map[string]any, item any) (any, error) { |
| 275 | key := item.(string) |
| 276 | itemExecCounts[key]++ |
| 277 | switch key { |
| 278 | case "ok": |
| 279 | return "OK_RES", nil |
| 280 | case "fail_once": |
| 281 | if itemExecCounts[key] < 2 { |
| 282 | return nil, fmt.Errorf("temp fail %s", key) |
| 283 | } |
| 284 | return "FAIL_ONCE_RES", nil // Success on retry |
| 285 | case "fail_always": |
| 286 | return nil, fmt.Errorf("perm fail %s", key) // Always fail |
| 287 | } |
| 288 | return nil, fmt.Errorf("unknown item") |
| 289 | }). |
| 290 | SetItemFallback(func(ctx *pf.PfContext, params map[string]any, item any, lastErr error) (any, error) { |
| 291 | key := item.(string) |
| 292 | if key == "fail_always" { |
| 293 | itemFallbackCalled[key] = true |
| 294 | assert.ErrorContains(t, lastErr, "perm fail fail_always") |
| 295 | return "FAIL_ALWAYS_FALLBACK_RES", nil // Fallback success |
| 296 | } |
| 297 | // Fallback should not be called for others |
| 298 | return nil, fmt.Errorf("unexpected fallback for %s", key) |
| 299 | }). |
| 300 | SetPost(func(ctx *pf.PfContext, params map[string]any, prepResult []any, execResult []any) (string, error) { |
| 301 | // Store results in context for assertion |
| 302 | ctx.SetValue("results", execResult) |
| 303 | return "batch_done", nil |
| 304 | }) |
| 305 | |
| 306 | ctx := pf.WithParam(context.Background(), nil) |
| 307 | //ctx := context.Background() |
| 308 | |
| 309 | action, err := bnode.Run(ctx) |
| 310 | |
| 311 | require.NoError(t, err) |
| 312 | assert.Equal(t, "batch_done", action) |
| 313 | |
| 314 | // Check execution counts |
| 315 | assert.Equal(t, 1, itemExecCounts["ok"]) |
| 316 | assert.Equal(t, 2, itemExecCounts["fail_once"]) |
| 317 | assert.Equal(t, 3, itemExecCounts["fail_always"]) // All retries used |
| 318 | |
| 319 | // Check fallback calls |
| 320 | assert.False(t, itemFallbackCalled["ok"]) |
| 321 | assert.False(t, itemFallbackCalled["fail_once"]) |
| 322 | assert.True(t, itemFallbackCalled["fail_always"]) |
nothing calls this directly
no test coverage detected