fix: Use retryOnThrottled
This commit is contained in:
parent
7fcce1c7ef
commit
04605283f9
3 changed files with 37 additions and 62 deletions
|
|
@ -90,6 +90,7 @@ import MkPagingButtons from '@/components/MkPagingButtons.vue';
|
||||||
import { selectFile } from '@/utility/select-file.js';
|
import { selectFile } from '@/utility/select-file.js';
|
||||||
import { copyGridDataToClipboard, removeDataFromGrid } from '@/components/grid/grid-utils.js';
|
import { copyGridDataToClipboard, removeDataFromGrid } from '@/components/grid/grid-utils.js';
|
||||||
import { useLoading } from '@/components/hook/useLoading.js';
|
import { useLoading } from '@/components/hook/useLoading.js';
|
||||||
|
import { retryOnThrottled } from '@@/js/retry-on-throttled';
|
||||||
|
|
||||||
type GridItem = {
|
type GridItem = {
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
|
|
@ -334,37 +335,29 @@ async function onUpdateButtonClicked() {
|
||||||
err?: unknown;
|
err?: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
const executeWithRetries = async (item: any, retries: number = 3): Promise<ApiResponse> => {
|
const execute = async (item: any): Promise<ApiResponse> => {
|
||||||
for (let attempt = 0; attempt <= retries; attempt++) {
|
try {
|
||||||
try {
|
await retryOnThrottled(() => misskeyApi('admin/emoji/update', {
|
||||||
await misskeyApi('admin/emoji/update', {
|
id: item.id,
|
||||||
id: item.id,
|
name: item.name,
|
||||||
name: item.name,
|
category: emptyStrToNull(item.category),
|
||||||
category: emptyStrToNull(item.category),
|
aliases: emptyStrToEmptyArray(item.aliases),
|
||||||
aliases: emptyStrToEmptyArray(item.aliases),
|
license: emptyStrToNull(item.license),
|
||||||
license: emptyStrToNull(item.license),
|
isSensitive: item.isSensitive,
|
||||||
isSensitive: item.isSensitive,
|
localOnly: item.localOnly,
|
||||||
localOnly: item.localOnly,
|
roleIdsThatCanBeUsedThisEmojiAsReaction: item.roleIdsThatCanBeUsedThisEmojiAsReaction.map((it: any) => it.id),
|
||||||
roleIdsThatCanBeUsedThisEmojiAsReaction: item.roleIdsThatCanBeUsedThisEmojiAsReaction.map((it: any) => it.id),
|
fileId: item.fileId,
|
||||||
fileId: item.fileId,
|
}));
|
||||||
});
|
return { item, success: true };
|
||||||
return { item, success: true };
|
} catch (error) {
|
||||||
} catch (err) {
|
return { item, success: false, err: error };
|
||||||
if (attempt < retries) {
|
|
||||||
console.warn(`Retrying ${item.name}, attempt ${attempt + 1}`);
|
|
||||||
await delay(1000 * (attempt + 1));
|
|
||||||
} else {
|
|
||||||
return { item, success: false, err };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return { item, success: false, err: new Error('Unknown error') };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const action = async (): Promise<ApiResponse[]> => {
|
const action = async (): Promise<ApiResponse[]> => {
|
||||||
const results: ApiResponse[] = [];
|
const results: ApiResponse[] = [];
|
||||||
for (const item of updatedItems) {
|
for (const item of updatedItems) {
|
||||||
results.push(await executeWithRetries(item));
|
results.push(await execute(item));
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { onMounted, ref, useCssModule } from 'vue';
|
import { onMounted, ref, useCssModule } from 'vue';
|
||||||
|
import { retryOnThrottled } from '@@/js/retry-on-throttled';
|
||||||
import type { RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
import type { RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||||
import type { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
import type { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||||
import type { DroppedFile } from '@/utility/file-drop.js';
|
import type { DroppedFile } from '@/utility/file-drop.js';
|
||||||
|
|
@ -247,29 +248,19 @@ const registerButtonDisabled = ref<boolean>(false);
|
||||||
const requestLogs = ref<RequestLogItem[]>([]);
|
const requestLogs = ref<RequestLogItem[]>([]);
|
||||||
const isDragOver = ref<boolean>(false);
|
const isDragOver = ref<boolean>(false);
|
||||||
|
|
||||||
const delay = (ms: number) => new Promise(resolve => window.setTimeout(resolve, ms));
|
|
||||||
|
|
||||||
type ApiResponse = {
|
type ApiResponse = {
|
||||||
item: any;
|
item: any;
|
||||||
success: boolean;
|
success: boolean;
|
||||||
err?: unknown;
|
err?: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
const executeWithRetries = async (item: any, apiEndpoint: string, payload: any, retries = 3): Promise<ApiResponse> => {
|
const execute = async (item: any, apiEndpoint: string, payload: any): Promise<ApiResponse> => {
|
||||||
for (let attempt = 0; attempt <= retries; attempt++) {
|
try {
|
||||||
try {
|
await retryOnThrottled(() => misskeyApi(apiEndpoint, payload));
|
||||||
await misskeyApi(apiEndpoint, payload);
|
return { item, success: true };
|
||||||
return { item, success: true };
|
} catch (err) {
|
||||||
} catch (err) {
|
return { item, success: false, err };
|
||||||
if (attempt < retries) {
|
|
||||||
console.warn(`Retrying ${item.id || item.name}, attempt ${attempt + 1}`);
|
|
||||||
await delay(1000 * (attempt + 1)); // Exponential backoff
|
|
||||||
} else {
|
|
||||||
return { item, success: false, err };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return { item, success: false, err: new Error('Unknown error') }; // Ensures all code paths return a value
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const importEmojis = async (targets: any[]): Promise<void> => {
|
const importEmojis = async (targets: any[]): Promise<void> => {
|
||||||
|
|
@ -286,7 +277,7 @@ const importEmojis = async (targets: any[]): Promise<void> => {
|
||||||
async function action(): Promise<ApiResponse[]> {
|
async function action(): Promise<ApiResponse[]> {
|
||||||
const results: ApiResponse[] = [];
|
const results: ApiResponse[] = [];
|
||||||
for (const item of targets) {
|
for (const item of targets) {
|
||||||
results.push(await executeWithRetries(item, 'admin/emoji/copy', { emojiId: item.id }));
|
results.push(await execute(item, 'admin/emoji/copy', { emojiId: item.id }));
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|
@ -326,7 +317,7 @@ const onRegistryClicked = async (): Promise<void> => {
|
||||||
const results: ApiResponse[] = [];
|
const results: ApiResponse[] = [];
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
results.push(
|
results.push(
|
||||||
await executeWithRetries(item, 'admin/emoji/add', {
|
await execute(item, 'admin/emoji/add', {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
category: emptyStrToNull(item.category),
|
category: emptyStrToNull(item.category),
|
||||||
aliases: emptyStrToEmptyArray(item.aliases),
|
aliases: emptyStrToEmptyArray(item.aliases),
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref, useCssModule } from 'vue';
|
import { computed, onMounted, ref, useCssModule } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
|
import { retryOnThrottled } from '@@/js/retry-on-throttled';
|
||||||
import type { GridSortOrderKey, RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
import type { GridSortOrderKey, RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||||
import type { GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
import type { GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||||
import type { GridSetting } from '@/components/grid/grid.js';
|
import type { GridSetting } from '@/components/grid/grid.js';
|
||||||
|
|
@ -310,31 +311,21 @@ function onGridCellValueChange(event: GridCellValueChangeEvent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const delay = (ms: number) => new Promise(resolve => window.setTimeout(resolve, ms));
|
|
||||||
|
|
||||||
type ApiResponse = {
|
type ApiResponse = {
|
||||||
item: any;
|
item: any;
|
||||||
success: boolean;
|
success: boolean;
|
||||||
err?: unknown;
|
err?: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
const executeWithRetries = async (item: any, retries: number = 3): Promise<ApiResponse> => {
|
const execute = async (item: any): Promise<ApiResponse> => {
|
||||||
for (let attempt = 0; attempt <= retries; attempt++) {
|
try {
|
||||||
try {
|
await retryOnThrottled(() => misskeyApi('admin/emoji/copy', {
|
||||||
await misskeyApi('admin/emoji/copy', {
|
emojiId: item.id,
|
||||||
emojiId: item.id,
|
}));
|
||||||
});
|
return { item, success: true };
|
||||||
return { item, success: true };
|
} catch (err) {
|
||||||
} catch (err) {
|
return { item, success: false, err };
|
||||||
if (attempt < retries) {
|
|
||||||
console.warn(`Retrying ${item.id}, attempt ${attempt + 1}`);
|
|
||||||
await delay(1000 * (attempt + 1)); // Exponential backoff
|
|
||||||
} else {
|
|
||||||
return { item, success: false, err };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return { item, success: false, err: new Error('Unknown error') }; // Ensures all code paths return a value
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const importEmojis = async (targets: any[]): Promise<void> => {
|
const importEmojis = async (targets: any[]): Promise<void> => {
|
||||||
|
|
@ -350,7 +341,7 @@ const importEmojis = async (targets: any[]): Promise<void> => {
|
||||||
|
|
||||||
const results: ApiResponse[] = [];
|
const results: ApiResponse[] = [];
|
||||||
for (const item of targets) {
|
for (const item of targets) {
|
||||||
results.push(await executeWithRetries(item));
|
results.push(await execute(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
const failedItems = results.filter(it => !it.success);
|
const failedItems = results.filter(it => !it.success);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue