Resume migration on initial load
This commit is contained in:
12
src/App.tsx
12
src/App.tsx
@@ -33,6 +33,7 @@ import { ReactRouter } from '@/lib/react-router/ReactRouter.ts';
|
|||||||
import { AuthManager } from '@/features/authentication/AuthManager.ts';
|
import { AuthManager } from '@/features/authentication/AuthManager.ts';
|
||||||
import { ImageProcessingType } from '@/features/settings/Settings.types.ts';
|
import { ImageProcessingType } from '@/features/settings/Settings.types.ts';
|
||||||
import { MigrationFABIndicator } from '@/features/migration/components/MigrationFABIndicator.tsx';
|
import { MigrationFABIndicator } from '@/features/migration/components/MigrationFABIndicator.tsx';
|
||||||
|
import { MigrationManager } from '@/features/migration/MigrationManager.ts';
|
||||||
|
|
||||||
const { Browse } = loadable(() => import('@/features/browse/screens/Browse.tsx'), lazyLoadFallback);
|
const { Browse } = loadable(() => import('@/features/browse/screens/Browse.tsx'), lazyLoadFallback);
|
||||||
const { DownloadQueue } = loadable(() => import('@/features/downloads/screens/DownloadQueue.tsx'), lazyLoadFallback);
|
const { DownloadQueue } = loadable(() => import('@/features/downloads/screens/DownloadQueue.tsx'), lazyLoadFallback);
|
||||||
@@ -156,6 +157,16 @@ const ReactRouterSetter = () => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ResumeMigration = () => {
|
||||||
|
useEffect(() => {
|
||||||
|
if (!MigrationManager.isActive()) {
|
||||||
|
MigrationManager.resume().catch(defaultPromiseErrorHandler('ResumeMigration'));
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
const PrivateRoutes = () => {
|
const PrivateRoutes = () => {
|
||||||
const isAuthenticated = AuthManager.useIsAuthenticated();
|
const isAuthenticated = AuthManager.useIsAuthenticated();
|
||||||
|
|
||||||
@@ -342,6 +353,7 @@ export const App: React.FC = () => (
|
|||||||
<WebUIUpdateChecker />
|
<WebUIUpdateChecker />
|
||||||
<InitialBackgroundRequests />
|
<InitialBackgroundRequests />
|
||||||
<BackgroundSubscriptions />
|
<BackgroundSubscriptions />
|
||||||
|
<ResumeMigration />
|
||||||
|
|
||||||
<Box sx={{ display: 'flex' }}>
|
<Box sx={{ display: 'flex' }}>
|
||||||
<Box sx={{ flexShrink: 0, position: 'relative', height: '100vh' }}>
|
<Box sx={{ flexShrink: 0, position: 'relative', height: '100vh' }}>
|
||||||
|
|||||||
@@ -347,8 +347,24 @@ export class MigrationManager {
|
|||||||
draft.groupExpandState = MIGRATE_SEARCH_ENTRY_GROUP_EXPAND_DEFAULT_STATE;
|
draft.groupExpandState = MIGRATE_SEARCH_ENTRY_GROUP_EXPAND_DEFAULT_STATE;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await MigrationManager.search(Object.values(state.entries));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async search(entries: TMigrationEntry[]): Promise<void> {
|
||||||
|
const { signal } = MigrationManager.abortAndCreateAbortController('search');
|
||||||
|
|
||||||
|
const searchPromises = entries.map((entry) =>
|
||||||
|
MigrationManager.mangaProcessQueue(async () => {
|
||||||
|
if (signal.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await MigrationManager.searchForManga(entry.mangaId, entry.mangaTitle, signal);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await MigrationManager.search(Object.values(state.entries));
|
await Promise.allSettled(searchPromises);
|
||||||
} finally {
|
} finally {
|
||||||
const { searchProgress } = MigrationManager.getState();
|
const { searchProgress } = MigrationManager.getState();
|
||||||
|
|
||||||
@@ -368,28 +384,12 @@ export class MigrationManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async search(entries: TMigrationEntry[]): Promise<void> {
|
|
||||||
const { signal } = MigrationManager.abortAndCreateAbortController('search');
|
|
||||||
|
|
||||||
const searchPromises = entries.map((entry) =>
|
|
||||||
MigrationManager.mangaProcessQueue(async () => {
|
|
||||||
if (signal.aborted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await MigrationManager.searchForManga(entry.mangaId, entry.mangaTitle, signal);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
await Promise.allSettled(searchPromises);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getMigratableEntries(): MigratableEntry[] {
|
static getMigratableEntries(): MigratableEntry[] {
|
||||||
const { entries } = MigrationManager.getState();
|
const { entries } = MigrationManager.getState();
|
||||||
|
|
||||||
return Object.values(entries).filter(
|
return Object.values(entries).filter(
|
||||||
(entry): entry is MigratableEntry =>
|
(entry): entry is MigratableEntry =>
|
||||||
entry.status === MigrationEntryStatus.SEARCH_COMPLETE &&
|
[MigrationEntryStatus.SEARCH_COMPLETE, MigrationEntryStatus.MIGRATING].includes(entry.status) &&
|
||||||
!entry.isExcluded &&
|
!entry.isExcluded &&
|
||||||
entry.selectedMatchMangaId != null &&
|
entry.selectedMatchMangaId != null &&
|
||||||
entry.selectedMatchSourceId != null,
|
entry.selectedMatchSourceId != null,
|
||||||
@@ -418,22 +418,7 @@ export class MigrationManager {
|
|||||||
draft.groupExpandState = MIGRATE_EXECUTE_ENTRY_GROUP_EXPAND_DEFAULT_STATE;
|
draft.groupExpandState = MIGRATE_EXECUTE_ENTRY_GROUP_EXPAND_DEFAULT_STATE;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
await MigrationManager.migrate(migratableEntries, options);
|
||||||
await MigrationManager.migrate(migratableEntries, options);
|
|
||||||
} finally {
|
|
||||||
const { migrationProgress } = MigrationManager.getState();
|
|
||||||
|
|
||||||
if (migrationProgress.completed === migrationProgress.total) {
|
|
||||||
MigrationManager.updateState((draft) => {
|
|
||||||
draft.groupExpandState = {
|
|
||||||
...MIGRATE_SEARCH_ENTRY_GROUP_EXPAND_DEFAULT_STATE,
|
|
||||||
[MigrationEntryStatus.MIGRATING]: false,
|
|
||||||
[MigrationEntryStatus.MIGRATION_FAILED]: !!migrationProgress.failed,
|
|
||||||
[MigrationEntryStatus.MIGRATION_COMPLETE]: !migrationProgress.failed,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async migrate(
|
private static async migrate(
|
||||||
@@ -456,7 +441,23 @@ export class MigrationManager {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
await Promise.allSettled(migrationPromises);
|
|
||||||
|
try {
|
||||||
|
await Promise.allSettled(migrationPromises);
|
||||||
|
} finally {
|
||||||
|
const { migrationProgress } = MigrationManager.getState();
|
||||||
|
|
||||||
|
if (migrationProgress.completed === migrationProgress.total) {
|
||||||
|
MigrationManager.updateState((draft) => {
|
||||||
|
draft.groupExpandState = {
|
||||||
|
...MIGRATE_SEARCH_ENTRY_GROUP_EXPAND_DEFAULT_STATE,
|
||||||
|
[MigrationEntryStatus.MIGRATING]: false,
|
||||||
|
[MigrationEntryStatus.MIGRATION_FAILED]: !!migrationProgress.failed,
|
||||||
|
[MigrationEntryStatus.MIGRATION_COMPLETE]: !migrationProgress.failed,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!signal.aborted) {
|
if (!signal.aborted) {
|
||||||
MigrationManager.updateState((draft) => {
|
MigrationManager.updateState((draft) => {
|
||||||
@@ -493,15 +494,27 @@ export class MigrationManager {
|
|||||||
|
|
||||||
const migratableEntries = MigrationManager.getMigratableEntries();
|
const migratableEntries = MigrationManager.getMigratableEntries();
|
||||||
|
|
||||||
|
MigrationManager.updateState((draft) => {
|
||||||
|
migratableEntries.forEach((entry) => {
|
||||||
|
draft.entries[entry.mangaId].status = MigrationEntryStatus.SEARCH_COMPLETE;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
await MigrationManager.migrate(migratableEntries, state.migrateOptions);
|
await MigrationManager.migrate(migratableEntries, state.migrateOptions);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pendingEntries = Object.values(state.entries).filter(
|
const pendingEntries = Object.values(state.entries).filter((entry) =>
|
||||||
(entry) => entry.status === MigrationEntryStatus.PENDING,
|
[MigrationEntryStatus.PENDING, MigrationEntryStatus.SEARCHING].includes(entry.status),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
MigrationManager.updateState((draft) => {
|
||||||
|
pendingEntries.forEach((entry) => {
|
||||||
|
draft.entries[entry.mangaId].status = MigrationEntryStatus.PENDING;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
await MigrationManager.search(pendingEntries);
|
await MigrationManager.search(pendingEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,7 +587,11 @@ export class MigrationManager {
|
|||||||
|
|
||||||
static isActive(): boolean {
|
static isActive(): boolean {
|
||||||
const { phase } = migrationStore.getState();
|
const { phase } = migrationStore.getState();
|
||||||
return phase === MigrationPhase.SEARCHING || phase === MigrationPhase.MIGRATING;
|
|
||||||
|
return (
|
||||||
|
!!MigrationManager.abortController &&
|
||||||
|
(phase === MigrationPhase.SEARCHING || phase === MigrationPhase.MIGRATING)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static hasPausedMigration(): boolean {
|
static hasPausedMigration(): boolean {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const MigrationExecute = () => {
|
|||||||
const migratingEntries = useMemo(
|
const migratingEntries = useMemo(
|
||||||
() =>
|
() =>
|
||||||
entryList.filter((entry) =>
|
entryList.filter((entry) =>
|
||||||
[MigrationEntryStatus.PENDING, MigrationEntryStatus.MIGRATING].includes(entry.status),
|
[MigrationEntryStatus.SEARCH_COMPLETE, MigrationEntryStatus.MIGRATING].includes(entry.status),
|
||||||
),
|
),
|
||||||
[entryList],
|
[entryList],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user