Skip to content

Commit e51c19d

Browse files
committed
refactor: resolve request defaults once in embedTexts (CL-9052)
1 parent 5e458c5 commit e51c19d

2 files changed

Lines changed: 20 additions & 17 deletions

File tree

‎src/embed.ts‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { type } from "arktype";
22
import {
33
classifyProtocolMismatch,
4+
createDefaultRetryPolicy,
45
createDefaultScheduler,
56
type BuiltRequest,
67
} from "@intx/inference";
78
import type { RetryPolicy } from "@intx/types/runtime";
89

910
import {
11+
DEFAULT_TIMEOUT_MS,
1012
EmbeddingRequestError,
13+
extractRetryAfterMs,
1114
runJSONRequest,
1215
type RequestDependencies,
1316
type RetryAfterExtractor,
@@ -58,10 +61,11 @@ const PROBE_TEXT = "embedding dimension probe";
5861
export type EmbedOptions = {
5962
/** Defaults to global `fetch` and Interchange's default scheduler. */
6063
deps?: RequestDependencies;
64+
/** Defaults to Interchange's policy: back off retryables, abort the rest. */
6165
retryPolicy?: RetryPolicy;
6266
/**
6367
* Reads `Retry-After` off a failed response, for a provider that signals
64-
* pacing its own way. Named after `ProviderAdapter.extractRetryAfterMs`.
68+
* pacing its own way. Defaults to seconds or HTTP-date parsing. Named after `ProviderAdapter.extractRetryAfterMs`.
6569
* There is no adapter object here because every provider serves the one
6670
* `/v1/embeddings` shape, so this hangs off the options instead.
6771
*/
@@ -187,13 +191,17 @@ export async function embedTexts(
187191
scheduler: createDefaultScheduler(),
188192
};
189193

194+
const retryPolicy = options.retryPolicy ?? createDefaultRetryPolicy();
195+
const timeoutMs = valid.timeoutMs ?? DEFAULT_TIMEOUT_MS;
196+
const extractRetryAfter = options.extractRetryAfterMs ?? extractRetryAfterMs;
197+
190198
const vectors: number[][] = [];
191199
for (const batch of batches(texts, valid.batchSize ?? DEFAULT_BATCH_SIZE)) {
192200
const request = buildRequest(valid, batch);
193201
const body = await runJSONRequest(request, deps, {
194-
retryPolicy: options.retryPolicy,
195-
timeoutMs: valid.timeoutMs,
196-
extractRetryAfterMs: options.extractRetryAfterMs,
202+
retryPolicy,
203+
timeoutMs,
204+
extractRetryAfterMs: extractRetryAfter,
197205
signal: options.signal,
198206
});
199207
vectors.push(...parseResponse(body, request.url, batch.length));

‎src/request.ts‎

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
classifyHTTPError,
44
classifyNetworkError,
55
classifyProtocolMismatch,
6-
createDefaultRetryPolicy,
76
type BuiltRequest,
87
type Dependencies,
98
} from "@intx/inference";
@@ -54,28 +53,26 @@ export class EmbeddingRequestError extends Error {
5453
export type RetryAfterExtractor = (headers: Headers) => number | undefined;
5554

5655
type RunRequestOptions = {
57-
/** Defaults to Interchange's policy: back off retryables, abort the rest. */
58-
retryPolicy: RetryPolicy | undefined;
56+
retryPolicy: RetryPolicy;
5957
/**
6058
* Per-attempt ceiling, enforced alongside any caller `signal` rather than
6159
* instead of it. A cold local model can take a while to page in.
6260
*/
63-
timeoutMs: number | undefined;
61+
timeoutMs: number;
6462
/**
6563
* Reads `Retry-After` off a failed response. Mirrors `ProviderAdapter`'s
6664
* member of the same name, so a provider that signals pacing its own way can
67-
* override without touching the transport. Defaults to
68-
* {@link extractRetryAfterMs}.
65+
* override without touching the transport.
6966
*/
70-
extractRetryAfterMs: RetryAfterExtractor | undefined;
67+
extractRetryAfterMs: RetryAfterExtractor;
7168
signal: AbortSignal | undefined;
7269
};
7370

7471
type Attempt =
7572
| { ok: true; body: unknown }
7673
| { ok: false; error: InferenceError };
7774

78-
const DEFAULT_TIMEOUT_MS = 30_000;
75+
export const DEFAULT_TIMEOUT_MS = 30_000;
7976

8077
/**
8178
* `Retry-After` in seconds or as an HTTP date; undefined when absent.
@@ -88,7 +85,7 @@ const DEFAULT_TIMEOUT_MS = 30_000;
8885
* absolute instant, so it cannot be resolved against the harness scheduler's
8986
* virtual clock. Upstream's extractor has the same constraint.
9087
*/
91-
const extractRetryAfterMs: RetryAfterExtractor = (headers) => {
88+
export const extractRetryAfterMs: RetryAfterExtractor = (headers) => {
9289
const header = headers.get("retry-after")?.trim();
9390
if (header === undefined || header === "") return undefined;
9491

@@ -195,10 +192,8 @@ export async function runJSONRequest(
195192
deps: RequestDependencies,
196193
options: RunRequestOptions,
197194
): Promise<unknown> {
198-
const { signal } = options;
199-
const policy = options.retryPolicy ?? createDefaultRetryPolicy();
200-
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
201-
const extractRetryAfter = options.extractRetryAfterMs ?? extractRetryAfterMs;
195+
const { retryPolicy: policy, timeoutMs, signal } = options;
196+
const extractRetryAfter = options.extractRetryAfterMs;
202197

203198
// Time comes from the harness scheduler, not globals, so a virtual-clock
204199
// test scheduler drives the retry loop deterministically.

0 commit comments

Comments
 (0)