diff --git a/apps/api/cmd/acceptance-load/main.go b/apps/api/cmd/acceptance-load/main.go index bb85519..b4b3335 100644 --- a/apps/api/cmd/acceptance-load/main.go +++ b/apps/api/cmd/acceptance-load/main.go @@ -279,7 +279,7 @@ func parseOptions() (options, error) { return options{}, errors.New("requests must be between 0 and 10000") } switch opts.profile { - case "simulated-smoke", "simulated-all", "gemini-baseline", "gemini-multi-image", "gemini-large", "gemini-peak", "video-throughput", "video-recovery", + case "simulated-smoke", "simulated-all", "gemini-baseline", "gemini-multi-image", "gemini-large", "gemini-peak", "video-throughput", "video-capacity", "video-recovery", "mixed-soak", "mixed-overload": if opts.emulatorURL == "" { return options{}, errors.New("AI_GATEWAY_ACCEPTANCE_EMULATOR_URL is required for simulated profiles") @@ -365,6 +365,12 @@ func run(ctx context.Context, opts options) ([]phaseResult, error) { requests = opts.requestCount } result = runVideo(ctx, client, opts, name, opts.shardRequestCount(requests), false, opts.emulatorFixtureURLs(), false, opts.shardIndex, opts.shardCount) + case "video-capacity": + requests := 1200 + if opts.requestCount > 0 { + requests = opts.requestCount + } + result = runVideo(ctx, client, opts, name, opts.shardRequestCount(requests), false, opts.emulatorFixtureURLs(), false, opts.shardIndex, opts.shardCount) case "video-recovery": result = runVideo(ctx, client, opts, name, opts.shardRequestCount(96), true, opts.emulatorFixtureURLs(), false, opts.shardIndex, opts.shardCount) case "mixed-soak", "mixed-overload": @@ -659,6 +665,9 @@ func runVideo( if longRun { prompt += " acceptance-long-recovery" } + if name == "video-capacity" { + prompt += " acceptance-capacity-ladder" + } if !realUpstream && logicalIndex%4 == 0 { prompt += " acceptance-force-conversion" } diff --git a/apps/api/internal/acceptanceemulator/server.go b/apps/api/internal/acceptanceemulator/server.go index 1f2e89a..d7aa913 100644 --- a/apps/api/internal/acceptanceemulator/server.go +++ b/apps/api/internal/acceptanceemulator/server.go @@ -674,9 +674,24 @@ func videoDelay(body map[string]any, longRun bool) time.Duration { if longRun { return 2*time.Minute + time.Duration(seed%61)*time.Second } + if videoPromptContains(body, "acceptance-capacity-ladder") { + return 30*time.Second + time.Duration(seed%16)*time.Second + } return 5*time.Second + time.Duration(seed%11)*time.Second } +func videoPromptContains(body map[string]any, marker string) bool { + content, _ := body["content"].([]any) + for _, raw := range content { + item, _ := raw.(map[string]any) + if strings.TrimSpace(stringValue(item["type"])) == "text" && + strings.Contains(strings.ToLower(stringValue(item["text"])), marker) { + return true + } + } + return false +} + func requestOrigin(r *http.Request) string { scheme := strings.TrimSpace(r.Header.Get("X-Forwarded-Proto")) if scheme == "" { diff --git a/apps/api/internal/acceptanceemulator/server_test.go b/apps/api/internal/acceptanceemulator/server_test.go index 6477365..48a3d54 100644 --- a/apps/api/internal/acceptanceemulator/server_test.go +++ b/apps/api/internal/acceptanceemulator/server_test.go @@ -228,6 +228,20 @@ func TestScaledDelayStaysOnWholeSecondsWithinProfile(t *testing.T) { } } +func TestVideoCapacityDelay(t *testing.T) { + body := map[string]any{ + "seed": json.Number("7"), + "content": []any{map[string]any{ + "type": "text", + "text": "capacity acceptance-capacity-ladder", + }}, + } + delay := videoDelay(body, false) + if delay < 30*time.Second || delay > 45*time.Second { + t.Fatalf("video capacity delay=%s, want 30s..45s", delay) + } +} + func TestVolcesProtocolAcceptsThreeSixAndNineReferenceImages(t *testing.T) { server := New(Config{Wait: func(context.Context, time.Duration) error { return nil }}) httpServer := httptest.NewServer(server.Handler()) diff --git a/scripts/cluster/run-production-acceptance.sh b/scripts/cluster/run-production-acceptance.sh index 21b86b8..c037bd6 100755 --- a/scripts/cluster/run-production-acceptance.sh +++ b/scripts/cluster/run-production-acceptance.sh @@ -3819,7 +3819,7 @@ run_single_node_acceptance() { apply_single_node_capacity "$slots" || break requests=$((slots * 3)) (( requests < 32 )) && requests=32 - if ! run_single_node_profile image-video video-throughput "$slots" "$requests"; then + if ! run_single_node_profile image-video video-capacity "$slots" "$requests"; then break fi single_node_stable_slots=$slots