chore(web): cleanup promise handling (#7382)

* no-misused-promises

* no-floating-promises

* format

* revert for now

* remove load function

* require-await

* revert a few no-floating-promises changes that would cause no-misused-promises failures

* format

* fix a few more

* fix most remaining errors

* executor-queue

* executor-queue.spec

* remove duplicate comments by grouping rules

* upgrade sveltekit and enforce rules

* oops. move await

* try this

* just ignore for now since it's only a test

* run in parallel

* Update web/src/routes/admin/jobs-status/+page.svelte

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>

* remove Promise.resolve call

* rename function

* remove unnecessary warning silencing

* make handleError sync

* fix new errors from recently merged PR to main

* extract method

* use handlePromiseError

---------

Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Ben McCann
2024-02-27 08:37:37 -08:00
committed by GitHub
parent 57f25855d3
commit 907a95a746
70 changed files with 312 additions and 282 deletions
+3 -3
View File
@@ -196,7 +196,7 @@
const handleCreateAlbum = async () => {
const newAlbum = await createAlbum();
if (newAlbum) {
goto(`${AppRoute.ALBUMS}/${newAlbum.id}`);
await goto(`${AppRoute.ALBUMS}/${newAlbum.id}`);
}
};
@@ -204,8 +204,8 @@
return new Date(dateString).toLocaleDateString($locale, dateFormats.album);
};
onMount(() => {
removeAlbumsIfEmpty();
onMount(async () => {
await removeAlbumsIfEmpty();
});
const removeAlbumsIfEmpty = async () => {
@@ -220,12 +220,11 @@
onMount(async () => {
if (album.sharedUsers.length > 0) {
getFavorite();
getNumberOfComments();
await Promise.all([getFavorite(), getNumberOfComments()]);
}
});
const handleKeypress = async (event: KeyboardEvent) => {
const handleKeypress = (event: KeyboardEvent) => {
if (event.target !== textArea) {
return;
}
@@ -242,12 +241,12 @@
const handleStartSlideshow = async () => {
const asset = $slideshowShuffle ? await assetStore.getRandomAsset() : assetStore.assets[0];
if (asset) {
setAssetId(asset.id);
await setAssetId(asset.id);
$slideshowState = SlideshowState.PlaySlideshow;
}
};
const handleEscape = () => {
const handleEscape = async () => {
if (viewMode === ViewMode.SELECT_USERS) {
viewMode = ViewMode.VIEW;
return;
@@ -275,7 +274,7 @@
assetInteractionStore.clearMultiselect();
return;
}
goto(backUrl);
await goto(backUrl);
return;
};
@@ -371,7 +370,7 @@
const handleRemoveUser = async (userId: string) => {
if (userId == 'me' || userId === $user.id) {
goto(backUrl);
await goto(backUrl);
return;
}
@@ -390,7 +389,7 @@
const handleRemoveAlbum = async () => {
try {
await deleteAlbum({ id: album.id });
goto(backUrl);
await goto(backUrl);
} catch (error) {
handleError(error, 'Unable to delete album');
} finally {
@@ -2,7 +2,7 @@ import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params }) => {
export const load: PageLoad = ({ params }) => {
const albumId = params.albumId;
if (albumId) {
+4 -7
View File
@@ -1,5 +1,6 @@
import type { OnShowContextMenuDetail } from '$lib/components/album-page/album-card';
import { notificationController, NotificationType } from '$lib/components/shared-components/notification/notification';
import { asyncTimeout } from '$lib/utils';
import { handleError } from '$lib/utils/handle-error';
import { createAlbum, deleteAlbum, getAllAlbums, type AlbumResponseDto } from '@immich/sdk';
import { derived, get, writable } from 'svelte/store';
@@ -20,9 +21,8 @@ export const useAlbums = (properties: AlbumsProperties) => {
// Delete album that has no photos and is named ''
for (const album of data) {
if (album.albumName === '' && album.assetCount === 0) {
setTimeout(async () => {
await handleDeleteAlbum(album);
}, 500);
await asyncTimeout(500);
await handleDeleteAlbum(album);
}
}
} catch {
@@ -46,10 +46,7 @@ export const useAlbums = (properties: AlbumsProperties) => {
albums.set(get(albums).filter(({ id }) => id !== albumToDelete.id));
}
async function showAlbumContextMenu(
contextMenuDetail: OnShowContextMenuDetail,
album: AlbumResponseDto,
): Promise<void> {
function showAlbumContextMenu(contextMenuDetail: OnShowContextMenuDetail, album: AlbumResponseDto): void {
contextMenuTargetAlbum.set(album);
contextMenuPosition.set({
@@ -2,6 +2,6 @@ import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load: PageLoad = async () => {
export const load: PageLoad = () => {
redirect(302, AppRoute.ARCHIVE);
};
@@ -2,6 +2,6 @@ import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load: PageLoad = async () => {
export const load: PageLoad = () => {
redirect(302, AppRoute.FAVORITES);
};
+10 -9
View File
@@ -15,6 +15,7 @@
import { DateTime, Duration } from 'luxon';
import { onDestroy, onMount } from 'svelte';
import type { PageData } from './$types';
import { handlePromiseError } from '$lib/utils';
export let data: PageData;
@@ -26,8 +27,8 @@
let viewingAssetCursor = 0;
let showSettingsModal = false;
onMount(() => {
loadMapMarkers().then((data) => (mapMarkers = data));
onMount(async () => {
mapMarkers = await loadMapMarkers();
});
onDestroy(() => {
@@ -35,7 +36,7 @@
assetViewingStore.showAssetViewer(false);
});
$: $featureFlags.map || goto(AppRoute.PHOTOS);
$: $featureFlags.map || handlePromiseError(goto(AppRoute.PHOTOS));
const omit = (obj: MapSettings, key: string) => {
return Object.fromEntries(Object.entries(obj).filter(([k]) => k !== key));
};
@@ -85,21 +86,21 @@
}
}
function onViewAssets(assetIds: string[]) {
assetViewingStore.setAssetId(assetIds[0]);
async function onViewAssets(assetIds: string[]) {
await assetViewingStore.setAssetId(assetIds[0]);
viewingAssets = assetIds;
viewingAssetCursor = 0;
}
function navigateNext() {
async function navigateNext() {
if (viewingAssetCursor < viewingAssets.length - 1) {
assetViewingStore.setAssetId(viewingAssets[++viewingAssetCursor]);
await assetViewingStore.setAssetId(viewingAssets[++viewingAssetCursor]);
}
}
function navigatePrevious() {
async function navigatePrevious() {
if (viewingAssetCursor > 0) {
assetViewingStore.setAssetId(viewingAssets[--viewingAssetCursor]);
await assetViewingStore.setAssetId(viewingAssets[--viewingAssetCursor]);
}
}
</script>
@@ -2,6 +2,6 @@ import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async () => {
export const load = (() => {
redirect(302, AppRoute.PHOTOS);
}) satisfies PageLoad;
+10 -10
View File
@@ -81,12 +81,12 @@
const onKeyboardPress = (event: KeyboardEvent) => handleKeyboardPress(event);
onMount(() => {
onMount(async () => {
document.addEventListener('keydown', onKeyboardPress);
const getSearchedPeople = $page.url.searchParams.get(QueryParameter.SEARCHED_PEOPLE);
if (getSearchedPeople) {
searchName = getSearchedPeople;
handleSearchPeople(true);
await handleSearchPeople(true);
}
});
@@ -108,10 +108,10 @@
}
};
const handleSearch = (force: boolean) => {
const handleSearch = async (force: boolean) => {
$page.url.searchParams.set(QueryParameter.SEARCHED_PEOPLE, searchName);
goto($page.url);
handleSearchPeople(force);
await goto($page.url);
await handleSearchPeople(force);
};
const handleCloseClick = () => {
@@ -293,8 +293,8 @@
}
};
const handleMergePeople = (detail: PersonResponseDto) => {
goto(
const handleMergePeople = async (detail: PersonResponseDto) => {
await goto(
`${AppRoute.PEOPLE}/${detail.id}?${QueryParameter.ACTION}=${ActionQueryParameterValue.MERGE}&${QueryParameter.PREVIOUS_ROUTE}=${AppRoute.PEOPLE}`,
);
};
@@ -303,7 +303,7 @@
if (searchName === '') {
if ($page.url.searchParams.has(QueryParameter.SEARCHED_PEOPLE)) {
$page.url.searchParams.delete(QueryParameter.SEARCHED_PEOPLE);
goto($page.url);
await goto($page.url);
}
return;
}
@@ -331,7 +331,7 @@
return;
}
if (personName === '') {
changeName();
await changeName();
return;
}
const data = await searchPerson({ name: personName, withHidden: true });
@@ -359,7 +359,7 @@
.slice(0, 3);
return;
}
changeName();
await changeName();
};
const submitBirthDateChange = async (value: string) => {
@@ -185,7 +185,7 @@
}
};
const handleEscape = () => {
const handleEscape = async () => {
if ($showAssetViewer || viewMode === ViewMode.SUGGEST_MERGE) {
return;
}
@@ -193,7 +193,7 @@
assetInteractionStore.clearMultiselect();
return;
} else {
goto(previousRoute);
await goto(previousRoute);
return;
}
};
@@ -235,7 +235,7 @@
type: NotificationType.Info,
});
goto(previousRoute, { replaceState: true });
await goto(previousRoute, { replaceState: true });
} catch (error) {
handleError(error, 'Unable to hide person');
}
@@ -244,7 +244,7 @@
const handleMerge = async (person: PersonResponseDto) => {
const { assets } = await getPersonStatistics({ id: person.id });
numberOfAssets = assets;
handleGoBack();
await handleGoBack();
data.person = person;
@@ -292,7 +292,7 @@
refreshAssetGrid = !refreshAssetGrid;
return;
}
goto(`${AppRoute.PEOPLE}/${personToBeMergedIn.id}`, { replaceState: true });
await goto(`${AppRoute.PEOPLE}/${personToBeMergedIn.id}`, { replaceState: true });
} catch (error) {
handleError(error, 'Unable to save name');
}
@@ -341,7 +341,7 @@
return;
}
if (name === '') {
changeName();
await changeName();
return;
}
@@ -366,7 +366,7 @@
viewMode = ViewMode.SUGGEST_MERGE;
return;
}
changeName();
await changeName();
};
const handleSetBirthDate = async (birthDate: string) => {
@@ -392,11 +392,11 @@
}
};
const handleGoBack = () => {
const handleGoBack = async () => {
viewMode = ViewMode.VIEW_ASSETS;
if ($page.url.searchParams.has(QueryParameter.ACTION)) {
$page.url.searchParams.delete(QueryParameter.ACTION);
goto($page.url);
await goto($page.url);
}
};
</script>
@@ -2,6 +2,6 @@ import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async ({ params }) => {
export const load = (({ params }) => {
redirect(302, `${AppRoute.PEOPLE}/${params.personId}`);
}) satisfies PageLoad;
@@ -2,6 +2,6 @@ import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async () => {
export const load = (() => {
redirect(302, AppRoute.PHOTOS);
}) satisfies PageLoad;
+5 -4
View File
@@ -35,6 +35,7 @@
import type { Viewport } from '$lib/stores/assets.store';
import { locale } from '$lib/stores/preferences.store';
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
import { handlePromiseError } from '$lib/utils';
import { parseUtcDate } from '$lib/utils/date-time';
const MAX_ASSET_COUNT = 5000;
@@ -53,7 +54,7 @@
const onKeyboardPress = (event: KeyboardEvent) => handleKeyboardPress(event);
const handleKeyboardPress = (event: KeyboardEvent) => {
const handleKeyboardPress = async (event: KeyboardEvent) => {
if (shouldIgnoreShortcut(event)) {
return;
}
@@ -65,7 +66,7 @@
return;
}
if (!$preventRaceConditionSearchBar) {
goto(previousRoute);
await goto(previousRoute);
}
$preventRaceConditionSearchBar = false;
return;
@@ -108,13 +109,13 @@
return searchQuery ? JSON.parse(searchQuery) : {};
})();
$: terms, onSearchQueryUpdate();
$: terms, handlePromiseError(onSearchQueryUpdate());
async function onSearchQueryUpdate() {
nextPage = 1;
searchResultAssets = [];
searchResultAlbums = [];
loadNextPage();
await loadNextPage();
}
export const loadNextPage = async () => {
@@ -2,6 +2,6 @@ import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async () => {
export const load = (() => {
redirect(302, AppRoute.SEARCH);
}) satisfies PageLoad;
+1 -1
View File
@@ -19,7 +19,7 @@
const createSharedAlbum = async () => {
try {
const newAlbum = await createAlbum({ createAlbumDto: { albumName: '' } });
goto(`${AppRoute.ALBUMS}/${newAlbum.id}`);
await goto(`${AppRoute.ALBUMS}/${newAlbum.id}`);
} catch (error) {
handleError(error, 'Unable to create album');
}
@@ -40,7 +40,7 @@
deleteLinkId = null;
await refresh();
} catch (error) {
await handleError(error, 'Unable to delete shared link');
handleError(error, 'Unable to delete shared link');
}
};
+2 -1
View File
@@ -24,10 +24,11 @@
import { emptyTrash, restoreTrash } from '@immich/sdk';
import { mdiDeleteOutline, mdiHistory } from '@mdi/js';
import type { PageData } from './$types';
import { handlePromiseError } from '$lib/utils';
export let data: PageData;
$: $featureFlags.trash || goto(AppRoute.PHOTOS);
$featureFlags.trash || handlePromiseError(goto(AppRoute.PHOTOS));
const assetStore = new AssetStore({ isTrashed: true });
const assetInteractionStore = createAssetInteractionStore();
@@ -2,6 +2,6 @@ import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async () => {
export const load = (() => {
redirect(302, AppRoute.TRASH);
}) satisfies PageLoad;
+1 -1
View File
@@ -3,7 +3,7 @@ import type { LayoutLoad } from './$types';
export const ssr = false;
export const csr = true;
export const load = (async () => {
export const load = (() => {
return {
meta: {
title: 'Immich',
+1 -1
View File
@@ -2,6 +2,6 @@ import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async () => {
export const load = (() => {
redirect(302, AppRoute.ADMIN_USER_MANAGEMENT);
}) satisfies PageLoad;
@@ -4,6 +4,7 @@
import Icon from '$lib/components/elements/icon.svelte';
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
import { AppRoute } from '$lib/constants';
import { asyncTimeout } from '$lib/utils';
import { getAllJobsStatus, type AllJobStatusResponseDto } from '@immich/sdk';
import { mdiCog } from '@mdi/js';
import { onDestroy, onMount } from 'svelte';
@@ -11,21 +12,19 @@
export let data: PageData;
let timer: ReturnType<typeof setInterval>;
let jobs: AllJobStatusResponseDto;
const load = async () => {
jobs = await getAllJobsStatus();
};
let running = true;
onMount(async () => {
await load();
timer = setInterval(load, 5000);
while (running) {
jobs = await getAllJobsStatus();
await asyncTimeout(5000);
}
});
onDestroy(() => {
clearInterval(timer);
running = false;
});
</script>
@@ -4,19 +4,21 @@
import { getServerStatistics } from '@immich/sdk';
import { onDestroy, onMount } from 'svelte';
import type { PageData } from './$types';
import { asyncTimeout } from '$lib/utils';
export let data: PageData;
let setIntervalHandler: ReturnType<typeof setInterval>;
let running = true;
onMount(async () => {
setIntervalHandler = setInterval(async () => {
while (running) {
data.stats = await getServerStatistics();
}, 5000);
await asyncTimeout(5000);
}
});
onDestroy(() => {
clearInterval(setIntervalHandler);
running = false;
});
</script>
@@ -51,7 +51,7 @@
shouldShowCreateUserForm = false;
};
const editUserHandler = async (user: UserResponseDto) => {
const editUserHandler = (user: UserResponseDto) => {
selectedUser = user;
shouldShowEditUserForm = true;
};
@@ -67,7 +67,7 @@
shouldShowInfoPanel = true;
};
const deleteUserHandler = async (user: UserResponseDto) => {
const deleteUserHandler = (user: UserResponseDto) => {
selectedUser = user;
shouldShowDeleteConfirmDialog = true;
};
@@ -82,7 +82,7 @@
shouldShowDeleteConfirmDialog = false;
};
const restoreUserHandler = async (user: UserResponseDto) => {
const restoreUserHandler = (user: UserResponseDto) => {
selectedUser = user;
shouldShowRestoreDialog = true;
};
@@ -3,10 +3,17 @@
import ChangePasswordForm from '$lib/components/forms/change-password-form.svelte';
import FullscreenContainer from '$lib/components/shared-components/fullscreen-container.svelte';
import { AppRoute } from '$lib/constants';
import { user } from '$lib/stores/user.store';
import { resetSavedUser, user } from '$lib/stores/user.store';
import { logout } from '@immich/sdk';
import type { PageData } from './$types';
export let data: PageData;
const onSuccess = async () => {
await goto(AppRoute.AUTH_LOGIN);
resetSavedUser();
await logout();
};
</script>
<FullscreenContainer title={data.meta.title}>
@@ -18,5 +25,5 @@
enter the new password below.
</p>
<ChangePasswordForm user={$user} on:success={() => goto(AppRoute.AUTH_LOGIN)} />
<ChangePasswordForm user={$user} on:success={onSuccess} />
</FullscreenContainer>
+1 -10
View File
@@ -1,21 +1,12 @@
<script lang="ts">
import { afterNavigate, goto } from '$app/navigation';
import { goto } from '$app/navigation';
import LoginForm from '$lib/components/forms/login-form.svelte';
import FullscreenContainer from '$lib/components/shared-components/fullscreen-container.svelte';
import { AppRoute } from '$lib/constants';
import { featureFlags, serverConfig } from '$lib/stores/server-config.store';
import { resetSavedUser } from '$lib/stores/user.store';
import { logout } from '@immich/sdk';
import type { PageData } from './$types';
export let data: PageData;
afterNavigate(async ({ from }) => {
if (from?.url?.pathname === AppRoute.AUTH_CHANGE_PASSWORD) {
resetSavedUser();
await logout();
}
});
</script>
{#if $featureFlags.loaded}
+4 -4
View File
@@ -29,17 +29,17 @@
const handleDoneClicked = async () => {
if (index >= onboardingSteps.length - 1) {
await setAdminOnboarding();
goto(AppRoute.PHOTOS);
await goto(AppRoute.PHOTOS);
} else {
index++;
goto(`${AppRoute.AUTH_ONBOARDING}?${QueryParameter.ONBOARDING_STEP}=${onboardingSteps[index].name}`);
await goto(`${AppRoute.AUTH_ONBOARDING}?${QueryParameter.ONBOARDING_STEP}=${onboardingSteps[index].name}`);
}
};
const handlePrevious = () => {
const handlePrevious = async () => {
if (index >= 1) {
index--;
goto(`${AppRoute.AUTH_ONBOARDING}?${QueryParameter.ONBOARDING_STEP}=${onboardingSteps[index].name}`);
await goto(`${AppRoute.AUTH_ONBOARDING}?${QueryParameter.ONBOARDING_STEP}=${onboardingSteps[index].name}`);
}
};
</script>