fix rate limit issue
This commit is contained in:
1 file changed
+37
-69
+37
-69
@@ -50,7 +50,6 @@ const WORKSHOP_DETAIL_BURST_CAPACITY = 20;
|
|||||||
const WORKSHOP_DETAIL_FAILURE_COOLDOWN_MS = 60_000;
|
const WORKSHOP_DETAIL_FAILURE_COOLDOWN_MS = 60_000;
|
||||||
const WORKSHOP_DETAIL_PREFETCH_MARGIN = '500px';
|
const WORKSHOP_DETAIL_PREFETCH_MARGIN = '500px';
|
||||||
const MODS_AUTOSAVE_DEBOUNCE_MS = 1_500;
|
const MODS_AUTOSAVE_DEBOUNCE_MS = 1_500;
|
||||||
const UPGRADE_ALL_DETAIL_BATCH_SIZE = 8;
|
|
||||||
|
|
||||||
const workshopDetailLimiter = {
|
const workshopDetailLimiter = {
|
||||||
inFlight: false,
|
inFlight: false,
|
||||||
@@ -89,7 +88,6 @@ function ModsBody({ slug, user }: { slug: string; user: CurrentUser }) {
|
|||||||
const [activeTab, setActiveTab] = useState<ModsTab>('installed');
|
const [activeTab, setActiveTab] = useState<ModsTab>('installed');
|
||||||
const [checkEnabled, setCheckEnabled] = useState(false);
|
const [checkEnabled, setCheckEnabled] = useState(false);
|
||||||
const [saveStatus, setSaveStatus] = useState<SaveStatus>('idle');
|
const [saveStatus, setSaveStatus] = useState<SaveStatus>('idle');
|
||||||
const [isUpgradingAll, setIsUpgradingAll] = useState(false);
|
|
||||||
const checkQuery = useServerModsCheck(slug, checkEnabled);
|
const checkQuery = useServerModsCheck(slug, checkEnabled);
|
||||||
|
|
||||||
const serverMods = data?.mods ?? [];
|
const serverMods = data?.mods ?? [];
|
||||||
@@ -196,45 +194,13 @@ function ModsBody({ slug, user }: { slug: string; user: CurrentUser }) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const upgradeAllVersions = async () => {
|
const applyKnownVersionUpgrades = (upgraded: ReforgerConfigMod[], changed: number) => {
|
||||||
if (!canManage || isUpgradingAll || isSavingMods || mods.length === 0) return;
|
|
||||||
|
|
||||||
setIsUpgradingAll(true);
|
|
||||||
setMessage(null);
|
setMessage(null);
|
||||||
try {
|
setDraft(upgraded);
|
||||||
const details = await fetchWorkshopDetailsForMods(mods);
|
setSaveStatus('pending');
|
||||||
let changed = 0;
|
setMessage(
|
||||||
let foundVersions = 0;
|
`Updated ${changed} known version number${changed === 1 ? '' : 's'}. Autosave will write the changes shortly.`,
|
||||||
const upgraded = mods.map((mod) => {
|
);
|
||||||
const detail = details.get(mod.modId.toUpperCase());
|
|
||||||
if (!detail?.version) return mod;
|
|
||||||
foundVersions += 1;
|
|
||||||
if (mod.version === detail.version) return mod;
|
|
||||||
changed += 1;
|
|
||||||
return {
|
|
||||||
...mod,
|
|
||||||
name: mod.name ?? detail.name,
|
|
||||||
version: detail.version,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
if (changed === 0) {
|
|
||||||
setMessage(
|
|
||||||
foundVersions === 0
|
|
||||||
? 'No workshop version info was available for the installed mods.'
|
|
||||||
: 'All installed mods are already on the latest known versions.',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setDraft(upgraded);
|
|
||||||
setSaveStatus('pending');
|
|
||||||
setMessage(
|
|
||||||
`Updated ${changed} version number${changed === 1 ? '' : 's'}. Autosave will write the changes shortly.`,
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
setIsUpgradingAll(false);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetMission = () => {
|
const resetMission = () => {
|
||||||
@@ -297,7 +263,6 @@ function ModsBody({ slug, user }: { slug: string; user: CurrentUser }) {
|
|||||||
dirty={dirty}
|
dirty={dirty}
|
||||||
isSaving={isSavingMods}
|
isSaving={isSavingMods}
|
||||||
saveStatus={saveStatus}
|
saveStatus={saveStatus}
|
||||||
isUpgradingAll={isUpgradingAll}
|
|
||||||
isResettingMission={savePerf.isPending}
|
isResettingMission={savePerf.isPending}
|
||||||
missingVersionIds={missingVersionIds}
|
missingVersionIds={missingVersionIds}
|
||||||
selectedModId={selectedModId}
|
selectedModId={selectedModId}
|
||||||
@@ -320,7 +285,7 @@ function ModsBody({ slug, user }: { slug: string; user: CurrentUser }) {
|
|||||||
setSaveStatus('idle');
|
setSaveStatus('idle');
|
||||||
}}
|
}}
|
||||||
onPatchVersions={patchVersions}
|
onPatchVersions={patchVersions}
|
||||||
onUpgradeAll={upgradeAllVersions}
|
onUpgradeAll={applyKnownVersionUpgrades}
|
||||||
onCheckDeps={runCheck}
|
onCheckDeps={runCheck}
|
||||||
onAddMods={addMods}
|
onAddMods={addMods}
|
||||||
onResetMission={resetMission}
|
onResetMission={resetMission}
|
||||||
@@ -367,26 +332,6 @@ async function addAllDeps(
|
|||||||
addMods(mods);
|
addMods(mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchWorkshopDetailsForMods(
|
|
||||||
mods: ReforgerConfigMod[],
|
|
||||||
): Promise<Map<string, WorkshopModDetail>> {
|
|
||||||
const details = new Map<string, WorkshopModDetail>();
|
|
||||||
|
|
||||||
for (let i = 0; i < mods.length; i += UPGRADE_ALL_DETAIL_BATCH_SIZE) {
|
|
||||||
const batch = mods.slice(i, i + UPGRADE_ALL_DETAIL_BATCH_SIZE);
|
|
||||||
const results = await Promise.allSettled(
|
|
||||||
batch.map((mod) => api.get<WorkshopModDetail>(`/api/workshop/mods/${mod.modId}`)),
|
|
||||||
);
|
|
||||||
for (const result of results) {
|
|
||||||
if (result.status === 'fulfilled') {
|
|
||||||
details.set(result.value.id.toUpperCase(), result.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return details;
|
|
||||||
}
|
|
||||||
|
|
||||||
function workshopModQueryKey(modId: string) {
|
function workshopModQueryKey(modId: string) {
|
||||||
return ['workshop', 'mod', modId] as const;
|
return ['workshop', 'mod', modId] as const;
|
||||||
}
|
}
|
||||||
@@ -489,7 +434,6 @@ function InstalledModsPanel({
|
|||||||
dirty,
|
dirty,
|
||||||
isSaving,
|
isSaving,
|
||||||
saveStatus,
|
saveStatus,
|
||||||
isUpgradingAll,
|
|
||||||
isResettingMission,
|
isResettingMission,
|
||||||
missingVersionIds,
|
missingVersionIds,
|
||||||
selectedModId,
|
selectedModId,
|
||||||
@@ -519,7 +463,6 @@ function InstalledModsPanel({
|
|||||||
dirty: boolean;
|
dirty: boolean;
|
||||||
isSaving: boolean;
|
isSaving: boolean;
|
||||||
saveStatus: SaveStatus;
|
saveStatus: SaveStatus;
|
||||||
isUpgradingAll: boolean;
|
|
||||||
isResettingMission: boolean;
|
isResettingMission: boolean;
|
||||||
missingVersionIds: Set<string>;
|
missingVersionIds: Set<string>;
|
||||||
selectedModId: string | null;
|
selectedModId: string | null;
|
||||||
@@ -538,7 +481,7 @@ function InstalledModsPanel({
|
|||||||
onSave: () => void;
|
onSave: () => void;
|
||||||
onDiscard: () => void;
|
onDiscard: () => void;
|
||||||
onPatchVersions: () => void;
|
onPatchVersions: () => void;
|
||||||
onUpgradeAll: () => void;
|
onUpgradeAll: (upgraded: ReforgerConfigMod[], changed: number) => void;
|
||||||
onCheckDeps: () => void;
|
onCheckDeps: () => void;
|
||||||
onAddMods: (mods: ReforgerConfigMod[]) => void;
|
onAddMods: (mods: ReforgerConfigMod[]) => void;
|
||||||
onResetMission: () => void;
|
onResetMission: () => void;
|
||||||
@@ -562,6 +505,23 @@ function InstalledModsPanel({
|
|||||||
installedModIds,
|
installedModIds,
|
||||||
visibleModIds,
|
visibleModIds,
|
||||||
);
|
);
|
||||||
|
const knownVersionUpgrades = useMemo(() => {
|
||||||
|
let changed = 0;
|
||||||
|
let knownVersions = 0;
|
||||||
|
const upgraded = mods.map((mod) => {
|
||||||
|
const detail = detailByModId.get(mod.modId.toUpperCase());
|
||||||
|
if (!detail?.version) return mod;
|
||||||
|
knownVersions += 1;
|
||||||
|
if (mod.version === detail.version) return mod;
|
||||||
|
changed += 1;
|
||||||
|
return {
|
||||||
|
...mod,
|
||||||
|
name: mod.name ?? detail.name,
|
||||||
|
version: detail.version,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { changed, knownVersions, upgraded };
|
||||||
|
}, [detailByModId, mods]);
|
||||||
const handleInstalledModVisibility = useCallback((modId: string, visible: boolean) => {
|
const handleInstalledModVisibility = useCallback((modId: string, visible: boolean) => {
|
||||||
setVisibleModIds((current) => {
|
setVisibleModIds((current) => {
|
||||||
const next = new Set(current);
|
const next = new Set(current);
|
||||||
@@ -585,11 +545,19 @@ function InstalledModsPanel({
|
|||||||
{canManage && mods.length > 0 && (
|
{canManage && mods.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
variant="accent"
|
variant="accent"
|
||||||
onClick={onUpgradeAll}
|
onClick={() =>
|
||||||
disabled={isSaving || isUpgradingAll}
|
onUpgradeAll(knownVersionUpgrades.upgraded, knownVersionUpgrades.changed)
|
||||||
title="Fetch the latest Workshop version for every installed mod"
|
}
|
||||||
|
disabled={isSaving || knownVersionUpgrades.changed === 0}
|
||||||
|
title={
|
||||||
|
knownVersionUpgrades.changed > 0
|
||||||
|
? `Upgrade ${knownVersionUpgrades.changed} mod${knownVersionUpgrades.changed === 1 ? '' : 's'} with known newer versions`
|
||||||
|
: knownVersionUpgrades.knownVersions > 0
|
||||||
|
? 'No loaded mods have newer known versions'
|
||||||
|
: 'No loaded Workshop version info yet'
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{isUpgradingAll ? 'Upgrading…' : 'Upgrade all'}
|
Upgrade all
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{saveStatus === 'pending' && (
|
{saveStatus === 'pending' && (
|
||||||
|
|||||||
Reference in new issue
Block a user