fix(opencode): cap session retries with jitter (#41939)
This commit is contained in:
@@ -35,10 +35,18 @@ function wrap(message: unknown): ReturnType<NamedError["toObject"]> {
|
||||
describe("session.retry.delay", () => {
|
||||
test("caps delay at 30 seconds when headers missing", () => {
|
||||
const error = apiError()
|
||||
const delays = Array.from({ length: 10 }, (_, index) => SessionRetry.delay(index + 1, error))
|
||||
const delays = Array.from({ length: 10 }, (_, index) => SessionRetry.delay(index + 1, error, 0))
|
||||
expect(delays).toStrictEqual([2000, 4000, 8000, 16000, 30000, 30000, 30000, 30000, 30000, 30000])
|
||||
})
|
||||
|
||||
test("adds jitter to exponential delays", () => {
|
||||
const error = apiError()
|
||||
expect(SessionRetry.delay(1, error, 0)).toBe(2000)
|
||||
expect(SessionRetry.delay(1, error, 1)).toBe(2500)
|
||||
expect(SessionRetry.delay(4, error, 1)).toBe(20000)
|
||||
expect(SessionRetry.delay(5, error, 1)).toBe(30000)
|
||||
})
|
||||
|
||||
test("prefers retry-after-ms when shorter than exponential", () => {
|
||||
const error = apiError({ "retry-after-ms": "1500" })
|
||||
expect(SessionRetry.delay(4, error)).toBe(1500)
|
||||
@@ -59,18 +67,18 @@ describe("session.retry.delay", () => {
|
||||
|
||||
test("ignores invalid retry hints", () => {
|
||||
const error = apiError({ "retry-after": "not-a-number" })
|
||||
expect(SessionRetry.delay(1, error)).toBe(2000)
|
||||
expect(SessionRetry.delay(1, error, 0)).toBe(2000)
|
||||
})
|
||||
|
||||
test("ignores malformed date retry hints", () => {
|
||||
const error = apiError({ "retry-after": "Invalid Date String" })
|
||||
expect(SessionRetry.delay(1, error)).toBe(2000)
|
||||
expect(SessionRetry.delay(1, error, 0)).toBe(2000)
|
||||
})
|
||||
|
||||
test("ignores past date retry hints", () => {
|
||||
const pastDate = new Date(Date.now() - 5000).toUTCString()
|
||||
const error = apiError({ "retry-after": pastDate })
|
||||
expect(SessionRetry.delay(1, error)).toBe(2000)
|
||||
expect(SessionRetry.delay(1, error, 0)).toBe(2000)
|
||||
})
|
||||
|
||||
test("uses retry-after values even when exceeding 10 minutes with headers", () => {
|
||||
@@ -115,6 +123,29 @@ describe("session.retry.delay", () => {
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("policy stops after five retries", () =>
|
||||
Effect.gen(function* () {
|
||||
const attempts: number[] = []
|
||||
const error = apiError({ "retry-after-ms": "0" })
|
||||
const step = yield* Schedule.toStepWithMetadata(
|
||||
SessionRetry.policy({
|
||||
provider: "test",
|
||||
parse: Schema.decodeUnknownSync(SessionV1.APIError.Schema),
|
||||
set: (info) =>
|
||||
Effect.sync(() => {
|
||||
attempts.push(info.attempt)
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
yield* Effect.forEach(Array.from({ length: SessionRetry.RETRY_MAX_RETRIES + 1 }), () =>
|
||||
Effect.ignore(step(error)),
|
||||
)
|
||||
|
||||
expect(attempts).toStrictEqual([1, 2, 3, 4, 5])
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
describe("session.retry.retryable", () => {
|
||||
|
||||
Reference in New Issue
Block a user