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
+1 -2
View File
@@ -9,7 +9,6 @@ import (
"strings" "strings"
"time" "time"
http "github.com/bogdanfinn/fhttp"
tlsclient "github.com/bogdanfinn/tls-client" tlsclient "github.com/bogdanfinn/tls-client"
"github.com/google/uuid" "github.com/google/uuid"
) )
@@ -127,7 +126,7 @@ func (c *Client) createImageTask(ctx context.Context, client tlsclient.HttpClien
if len(refImages) > 0 { if len(refImages) > 0 {
opts["reference_images"] = refImages opts["reference_images"] = refImages
} }
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": "gemini_3_1_flash_image", "taskType": "gemini_3_1_flash_image",
"options": opts, "options": opts,
"asTeamId": jsonNumberOrString(teamID), "asTeamId": jsonNumberOrString(teamID),
+19 -1
View File
@@ -213,7 +213,7 @@ func (c *Client) createTask(ctx context.Context, client tlsclient.HttpClient, to
if assetGroupID != "" { if assetGroupID != "" {
opts["assetGroupId"] = 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", "taskType": "gen4_turbo",
"options": opts, "options": opts,
"asTeamId": jsonNumberOrString(teamID), "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 // apiJSON performs an authed JSON request against the Runway API and returns the
// parsed body, mapping status codes to the shared provider error sentinels. // 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) { func (c *Client) apiJSON(ctx context.Context, client tlsclient.HttpClient, token, teamID, method, path string, body any) (map[string]any, error) {