chore: move retryOnThrottled to frontend-shared

This commit is contained in:
Outvi V 2025-06-01 06:30:28 +08:00
parent e36ea27517
commit de7f7984cd
2 changed files with 42 additions and 42 deletions

View file

@ -0,0 +1,40 @@
async function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
window.setTimeout(() => {
resolve();
}, ms);
});
}
export async function retryOnThrottled<T>(f: ()=>Promise<T>, retryCount = 5): Promise<T> {
let lastOk = false;
let lastResultOrError: T;
for (let i = 0; i < retryCount; i++) {
const [ok, resultOrError] = await f()
.then(result => [true, result])
.catch(err => [false, err]);
lastOk = ok;
lastResultOrError = resultOrError;
if (ok) {
break;
}
// RATE_LIMIT_EXCEEDED
if (resultOrError?.id === 'd5826d14-3982-4d2e-8011-b9e9f02499ef') {
await sleep(resultOrError?.info?.fullResetMs ?? 1000);
continue;
}
// Throw for non-throttling errors
throw resultOrError;
}
if (lastOk) {
return lastResultOrError!;
} else {
// Give up after getting throttled too many times
throw lastResultOrError!;
}
}

View file

@ -13,6 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue';
import * as Misskey from 'misskey-js';
import { retryOnThrottled } from '@@/js/retry-on-throttled.js';
import MkNote from '@/components/MkNote.vue';
import MkNoteDetailed from '@/components/MkNoteDetailed.vue';
import { misskeyApi } from '@/utility/misskey-api.js';
@ -28,51 +29,10 @@ const note = ref<Misskey.entities.Note | null>(null);
// eslint-disable-next-line id-denylist
let timeoutId: ReturnType<typeof window.setTimeout> | null = null;
async function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
window.setTimeout(() => {
resolve();
}, ms);
});
}
async function retryOnThrottle<T>(f: ()=>Promise<T>, retryCount = 5): Promise<T> {
let lastOk: boolean;
let lastResultOrError: T;
for (let i = 0; i < retryCount; i++) {
const [ok, resultOrError] = await f()
.then(result => [true, result])
.catch(err => [false, err]);
lastOk = ok;
lastResultOrError = resultOrError;
if (ok) {
break;
}
// RATE_LIMIT_EXCEEDED
if (resultOrError?.id === 'd5826d14-3982-4d2e-8011-b9e9f02499ef') {
await sleep(resultOrError?.info?.fullResetMs ?? 1000);
continue;
}
// Throw for non-throttling errors
throw resultOrError;
}
if (lastOk) {
return lastResultOrError;
} else {
// Give up after getting throttled too many times
throw lastResultOrError;
}
}
onMounted(() => {
if (props.block.note == null) return;
timeoutId = window.setTimeout(() => {
retryOnThrottle(() => misskeyApi('notes/show', { noteId: props.block.note })).then(result => {
retryOnThrottled(() => misskeyApi('notes/show', { noteId: props.block.note })).then(result => {
note.value = result;
});
}, 500 * props.index); // rate limit is 2 reqs per sec