refactor(nbstore): improve HTTP connection timeout handling (#11985)

Closes: [BS-3344](https://linear.app/affine-design/issue/BS-3344/改进请求超时提示)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Refactor**
  - Improved internal request timeout handling for cloud operations, resulting in more robust and reliable network requests. No changes to user-facing features or functionality.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
fundon
2025-05-23 09:13:59 +00:00
parent 797646442d
commit 952650e1bc

View File

@@ -3,26 +3,24 @@ import { gqlFetcherFactory } from '@affine/graphql';
import { DummyConnection } from '../../connection'; import { DummyConnection } from '../../connection';
const TIMEOUT = 15000;
export class HttpConnection extends DummyConnection { export class HttpConnection extends DummyConnection {
readonly fetch = async (input: string, init?: RequestInit) => { readonly fetch = async (input: string, init?: RequestInit) => {
const externalSignal = init?.signal; const externalSignal = init?.signal;
if (externalSignal?.aborted) { if (externalSignal?.aborted) {
throw externalSignal.reason; throw externalSignal.reason;
} }
const abortController = new AbortController();
externalSignal?.addEventListener('abort', reason => {
abortController.abort(reason);
});
const timeout = 15000; const signals = [AbortSignal.timeout(TIMEOUT)];
const timeoutId = setTimeout(() => { if (externalSignal) signals.push(externalSignal);
abortController.abort(new Error('request timeout'));
}, timeout); const combinedSignal = AbortSignal.any(signals);
const res = await globalThis const res = await globalThis
.fetch(new URL(input, this.serverBaseUrl), { .fetch(new URL(input, this.serverBaseUrl), {
...init, ...init,
signal: abortController.signal, signal: combinedSignal,
headers: { headers: {
...this.requestHeaders, ...this.requestHeaders,
...init?.headers, ...init?.headers,
@@ -30,16 +28,18 @@ export class HttpConnection extends DummyConnection {
}, },
}) })
.catch(err => { .catch(err => {
const message =
err.name === 'TimeoutError' ? 'request timeout' : err.message;
throw new UserFriendlyError({ throw new UserFriendlyError({
status: 504, status: 504,
code: 'NETWORK_ERROR', code: 'NETWORK_ERROR',
type: 'NETWORK_ERROR', type: 'NETWORK_ERROR',
name: 'NETWORK_ERROR', name: 'NETWORK_ERROR',
message: `Network error: ${err.message}`, message: `Network error: ${message}`,
stacktrace: err.stack, stacktrace: err.stack,
}); });
}); });
clearTimeout(timeoutId);
if (!res.ok && res.status !== 404) { if (!res.ok && res.status !== 404) {
if (res.status === 413) { if (res.status === 413) {
throw new UserFriendlyError({ throw new UserFriendlyError({