fix(runway): retry the /v1/tasks submit on transient errors

A dropped proxy connection (EOF) or 5xx on the task-create failed the whole generation. submitTask now retries transient (ErrTemporaryUpstream) submits up to 3x with backoff, honoring ctx. Applies to both Nano Banana image and Gen-4 video. Validated: 10/10 4K images (19-24MB PNG each) generated across 10 accounts.
This commit is contained in:
2026-07-09 17:06:43 +08:00
parent cc6a2b1c54
commit 33b5fc3b0e
2 changed files with 20 additions and 3 deletions
+19 -1
View File
@@ -213,7 +213,7 @@ func (c *Client) createTask(ctx context.Context, client tlsclient.HttpClient, to
if assetGroupID != "" {
opts["assetGroupId"] = assetGroupID
}
res, err := c.apiJSON(ctx, client, token, teamID, http.MethodPost, "/v1/tasks", map[string]any{
res, err := c.submitTask(ctx, client, token, teamID, map[string]any{
"taskType": "gen4_turbo",
"options": opts,
"asTeamId": jsonNumberOrString(teamID),
@@ -271,6 +271,24 @@ func (c *Client) pollTask(ctx context.Context, client tlsclient.HttpClient, toke
}
}
// submitTask POSTs a /v1/tasks create, retrying a few times on transient
// (network / 5xx) failures. A dropped proxy connection ("EOF") on the submit
// would otherwise fail the whole generation even though a quick retry succeeds.
func (c *Client) submitTask(ctx context.Context, client tlsclient.HttpClient, token, teamID string, body map[string]any) (map[string]any, error) {
var res map[string]any
var err error
for attempt := 0; attempt < 3; attempt++ {
res, err = c.apiJSON(ctx, client, token, teamID, http.MethodPost, "/v1/tasks", body)
if err == nil || !errors.Is(err, ErrTemporaryUpstream) {
return res, err
}
if sleepCtx(ctx, time.Duration(attempt+1)*time.Second) != nil {
return nil, ctx.Err()
}
}
return res, err
}
// apiJSON performs an authed JSON request against the Runway API and returns the
// parsed body, mapping status codes to the shared provider error sentinels.
func (c *Client) apiJSON(ctx context.Context, client tlsclient.HttpClient, token, teamID, method, path string, body any) (map[string]any, error) {