cutsio 0.2.4 → 0.2.5
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/index.js +34 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -137,6 +137,18 @@ var ApiError = class extends Error {
|
|
|
137
137
|
this.status = status;
|
|
138
138
|
}
|
|
139
139
|
};
|
|
140
|
+
var MAX_REQUEST_RETRIES = 3;
|
|
141
|
+
var BASE_RETRY_DELAY_MS = 1e3;
|
|
142
|
+
var MAX_RETRY_DELAY_MS = 3e4;
|
|
143
|
+
function retryDelayMs(attempt, retryAfter) {
|
|
144
|
+
const headerSeconds = retryAfter ? Number(retryAfter) : Number.NaN;
|
|
145
|
+
const headerMs = Number.isFinite(headerSeconds) && headerSeconds >= 0 ? headerSeconds * 1e3 : null;
|
|
146
|
+
const backoffMs = Math.min(BASE_RETRY_DELAY_MS * 2 ** attempt, MAX_RETRY_DELAY_MS);
|
|
147
|
+
return Math.min(headerMs ?? backoffMs, MAX_RETRY_DELAY_MS) + Math.random() * 500;
|
|
148
|
+
}
|
|
149
|
+
function sleep(ms) {
|
|
150
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
151
|
+
}
|
|
140
152
|
var CutsioClient = class {
|
|
141
153
|
base;
|
|
142
154
|
apiKey;
|
|
@@ -181,17 +193,21 @@ var CutsioClient = class {
|
|
|
181
193
|
...init?.body ? { "Content-Type": "application/json" } : {},
|
|
182
194
|
...init?.headers ?? {}
|
|
183
195
|
};
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
196
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
197
|
+
const response = await fetch(`${this.base}${path}`, { ...init, headers });
|
|
198
|
+
if (response.ok) return response.json();
|
|
199
|
+
const retryable = response.status === 429 || response.status === 502 || response.status === 503 || response.status === 504;
|
|
200
|
+
if (!retryable || attempt >= MAX_REQUEST_RETRIES) {
|
|
201
|
+
let message = `HTTP ${response.status}`;
|
|
202
|
+
try {
|
|
203
|
+
const body = await response.json();
|
|
204
|
+
if (typeof body.error === "string") message = body.error;
|
|
205
|
+
} catch {
|
|
206
|
+
}
|
|
207
|
+
throw new ApiError(message, response.status);
|
|
191
208
|
}
|
|
192
|
-
|
|
209
|
+
await sleep(retryDelayMs(attempt, response.headers.get("retry-after")));
|
|
193
210
|
}
|
|
194
|
-
return response.json();
|
|
195
211
|
}
|
|
196
212
|
};
|
|
197
213
|
|
|
@@ -751,12 +767,16 @@ async function sync(client, options) {
|
|
|
751
767
|
while (queue.size > 0) {
|
|
752
768
|
const ready = [];
|
|
753
769
|
const ids = [...queue.keys()];
|
|
770
|
+
let serverDelayMs = 0;
|
|
754
771
|
for (let index = 0; index < ids.length; index += PREPARE_BATCH_SIZE) {
|
|
755
772
|
const batch = ids.slice(index, index + PREPARE_BATCH_SIZE);
|
|
756
773
|
const results = await client.prepare(batch);
|
|
757
774
|
for (const result of results) {
|
|
758
775
|
const item = queue.get(result.id);
|
|
759
776
|
if (!item) continue;
|
|
777
|
+
if (typeof result.retryAfterSeconds === "number" && result.retryAfterSeconds > 0) {
|
|
778
|
+
serverDelayMs = Math.max(serverDelayMs, result.retryAfterSeconds * 1e3);
|
|
779
|
+
}
|
|
760
780
|
switch (result.status) {
|
|
761
781
|
case "ready":
|
|
762
782
|
if (result.url) {
|
|
@@ -850,7 +870,7 @@ async function sync(client, options) {
|
|
|
850
870
|
}
|
|
851
871
|
break;
|
|
852
872
|
}
|
|
853
|
-
await
|
|
873
|
+
await sleep2(Math.min(Math.max(serverDelayMs, prepareDelayMs), MAX_PREPARE_DELAY_MS));
|
|
854
874
|
prepareDelayMs = Math.min(prepareDelayMs * 2, MAX_PREPARE_DELAY_MS);
|
|
855
875
|
}
|
|
856
876
|
return { downloaded, unchanged, skipped, failed };
|
|
@@ -870,7 +890,7 @@ async function runPool(items, concurrency, worker) {
|
|
|
870
890
|
})
|
|
871
891
|
);
|
|
872
892
|
}
|
|
873
|
-
function
|
|
893
|
+
function sleep2(ms) {
|
|
874
894
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
875
895
|
}
|
|
876
896
|
|
|
@@ -903,7 +923,7 @@ var color = {
|
|
|
903
923
|
};
|
|
904
924
|
var isInteractive = colorEnabled;
|
|
905
925
|
var animationsEnabled = colorEnabled && process.env.CUTSIO_NO_ANIM !== "1";
|
|
906
|
-
function
|
|
926
|
+
function sleep3(ms) {
|
|
907
927
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
908
928
|
}
|
|
909
929
|
|
|
@@ -1253,12 +1273,12 @@ async function revealBanner() {
|
|
|
1253
1273
|
for (let index = 0; index < WORDMARK.length; index += 1) {
|
|
1254
1274
|
process.stdout.write(`${shade(WORDMARK[index] ?? "", index)}
|
|
1255
1275
|
`);
|
|
1256
|
-
if (animationsEnabled) await
|
|
1276
|
+
if (animationsEnabled) await sleep3(38);
|
|
1257
1277
|
}
|
|
1258
1278
|
process.stdout.write(`${color.dim(" mezzanine sync for your Mac")}
|
|
1259
1279
|
|
|
1260
1280
|
`);
|
|
1261
|
-
if (animationsEnabled) await
|
|
1281
|
+
if (animationsEnabled) await sleep3(60);
|
|
1262
1282
|
}
|
|
1263
1283
|
|
|
1264
1284
|
// src/commands/welcome.ts
|