mcp-duojie-image 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/provider.js +21 -0
- package/package.json +1 -1
package/dist/provider.js
CHANGED
|
@@ -10,11 +10,28 @@ async function fetchWithRetry(url, init, timeoutMs, retries = 0) {
|
|
|
10
10
|
try {
|
|
11
11
|
const res = await fetch(url, { ...init, signal: controller.signal });
|
|
12
12
|
clearTimeout(timer);
|
|
13
|
+
// 5xx: 上游随机故障(EOF等),立刻 abort body 连接并重试,不等 chunked 终止
|
|
14
|
+
if (res.status >= 500 && attempt < retries) {
|
|
15
|
+
try {
|
|
16
|
+
controller.abort();
|
|
17
|
+
}
|
|
18
|
+
catch { }
|
|
19
|
+
const delayMs = 1000 * Math.pow(2, attempt) + Math.random() * 500;
|
|
20
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
13
23
|
return res;
|
|
14
24
|
}
|
|
15
25
|
catch (err) {
|
|
16
26
|
clearTimeout(timer);
|
|
17
27
|
const isAbort = err instanceof Error && err.name === "AbortError";
|
|
28
|
+
// AbortError from our manual abort above is not a real timeout
|
|
29
|
+
if (isAbort && attempt < retries) {
|
|
30
|
+
lastErr = err;
|
|
31
|
+
const delayMs = 1000 * Math.pow(2, attempt) + Math.random() * 500;
|
|
32
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
18
35
|
if (isAbort) {
|
|
19
36
|
throw new AppError("E_PROVIDER_TIMEOUT", "Request timed out");
|
|
20
37
|
}
|
|
@@ -77,6 +94,10 @@ async function handleProviderError(res) {
|
|
|
77
94
|
if (res.status === 429) {
|
|
78
95
|
throw new AppError("E_PROVIDER_RATE_LIMIT", "Rate limit exceeded");
|
|
79
96
|
}
|
|
97
|
+
// 5xx: 上游随机故障,不读 body(chunked 连接挂 120s),直接秒回
|
|
98
|
+
if (res.status >= 500) {
|
|
99
|
+
throw new AppError("E_PROVIDER_BAD_REQUEST", `Upstream error ${res.status} (body skipped to avoid chunked hang)`);
|
|
100
|
+
}
|
|
80
101
|
const text = await res.text().catch(() => "");
|
|
81
102
|
throw new AppError("E_PROVIDER_BAD_REQUEST", `Upstream error ${res.status}: ${text.slice(0, 200)}`);
|
|
82
103
|
}
|