mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-17 20:32:25 +03:00
`proxy_logs` records `upstream_status`, the HTTP status the provider actually returned through the proxy, instead of only success/timeout/error.
Maintainer rework before merge (kept the idea, no default behavior change):
- The migration collided with the tip (177 was already taken): renumbered to `179_proxy_logs_upstream_status.sql`, the runner's already-applied check moved to `case "179"` (the old `"177"` would have skipped the tip's own 177), migration count bumped to 176 in README, AGENTS.md, llm.txt and its mirrors (operator-approved).
- A new test runs the real migration runner on the real SQL files and fails with the old case number.
Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests.
Thanks @maxmad64bis!
44 lines
2.0 KiB
TypeScript
44 lines
2.0 KiB
TypeScript
import { isProviderRequestCaptureActive, onDispatchStart } from "./providerRequestLogging.ts";
|
|
|
|
/**
|
|
* Wrap the process-wide fetch so the HTTP status the provider actually returned lands on
|
|
* the request's applied-proxy sink. Only calls that settle while a provider request is
|
|
* being dispatched count: side fetches of the same request (usage sync, dashboard events)
|
|
* and background calls an executor leaves running after it returns must not overwrite the
|
|
* provider's status. A new dispatch invalidates the earlier status at entry, so a retry
|
|
* that never reaches the network (local refusal, start timeout) leaves nothing stale
|
|
* behind; within the dispatch the last response received wins, which follows an
|
|
* executor's own retries. A background call keeps a settled dispatch token and never
|
|
* writes, so clearing at entry cannot race with it. A call that throws clears the
|
|
* status, so a network error on one proxy after a 429 on another leaves no stale 429
|
|
* behind. The response and any exception pass through. In cloud mode the default export
|
|
* is the unpatched fetch, so nothing is captured and the log keeps null.
|
|
*
|
|
* `isDispatching` is injectable for tests only.
|
|
*/
|
|
export function withUpstreamStatusCapture<A extends unknown[]>(
|
|
inner: (...args: A) => Promise<Response>,
|
|
getSink: () => { upstreamStatus?: number } | undefined,
|
|
isDispatching: () => boolean = isProviderRequestCaptureActive
|
|
): (...args: A) => Promise<Response> {
|
|
if (isDispatching === isProviderRequestCaptureActive) {
|
|
onDispatchStart(() => {
|
|
const sink = getSink();
|
|
if (sink) delete sink.upstreamStatus;
|
|
});
|
|
}
|
|
return async (...args: A) => {
|
|
const sink = isDispatching() ? getSink() : undefined;
|
|
if (!sink) return inner(...args);
|
|
let response: Response;
|
|
try {
|
|
response = await inner(...args);
|
|
} catch (error) {
|
|
if (isDispatching()) sink.upstreamStatus = undefined;
|
|
throw error;
|
|
}
|
|
if (isDispatching()) sink.upstreamStatus = response.status;
|
|
return response;
|
|
};
|
|
}
|