4
0
mirror of https://github.com/AzuraCast/AzuraCast.git synced 2024-06-14 21:26:37 +00:00

Make auto-refreshing async calls a common function that stops intervals on an exception.

This commit is contained in:
Buster Neece 2023-12-29 11:28:59 -06:00
parent 5de23588f5
commit dd13a5a91e
No known key found for this signature in database
8 changed files with 109 additions and 60 deletions

View File

@ -228,7 +228,7 @@
<script setup lang="ts">
import {ref} from "vue";
import useHasDatatable, {DataTableTemplateRef} from "~/functions/useHasDatatable";
import DataTable, { DataTableField } from "~/components/Common/DataTable.vue";
import DataTable, {DataTableField} from "~/components/Common/DataTable.vue";
import {useTranslate} from "~/vendor/gettext";
import CardPage from "~/components/Common/CardPage.vue";
import {useLuxon} from "~/vendor/luxon";
@ -237,12 +237,12 @@ import {useAxios} from "~/vendor/axios";
import {useNotify} from "~/functions/useNotify";
import Tabs from "~/components/Common/Tabs.vue";
import Tab from "~/components/Common/Tab.vue";
import {useIntervalFn} from "@vueuse/core";
import {getApiUrl} from "~/router.ts";
import useRefreshableAsyncState from "~/functions/useRefreshableAsyncState.ts";
import Loading from "~/components/Common/Loading.vue";
import {IconRefresh} from "~/components/Common/icons.ts";
import Icon from "~/components/Common/Icon.vue";
import useAutoRefreshingAsyncState from "~/functions/useAutoRefreshingAsyncState.ts";
const listSyncTasksUrl = getApiUrl('/admin/debug/sync-tasks');
const listQueueTotalsUrl = getApiUrl('/admin/debug/queues');
@ -252,14 +252,20 @@ const clearQueuesUrl = getApiUrl('/admin/debug/clear-queue');
const {axios} = useAxios();
const {state: syncTasks, isLoading: syncTasksLoading, execute: resetSyncTasks} = useRefreshableAsyncState(
const {state: syncTasks, isLoading: syncTasksLoading, execute: resetSyncTasks} = useAutoRefreshingAsyncState(
() => axios.get(listSyncTasksUrl.value).then(r => r.data),
[],
{
timeout: 60000
}
);
const {state: queueTotals, isLoading: queueTotalsLoading, execute: resetQueueTotals} = useRefreshableAsyncState(
const {state: queueTotals, isLoading: queueTotalsLoading, execute: resetQueueTotals} = useAutoRefreshingAsyncState(
() => axios.get(listQueueTotalsUrl.value).then(r => r.data),
[],
{
timeout: 60000
}
);
const {state: stations, isLoading: stationsLoading} = useRefreshableAsyncState(
@ -267,14 +273,6 @@ const {state: stations, isLoading: stationsLoading} = useRefreshableAsyncState(
[],
);
useIntervalFn(
() => {
resetSyncTasks();
resetQueueTotals();
},
60000
);
const {$gettext} = useTranslate();
const {timestampToRelative} = useLuxon();

View File

@ -93,7 +93,6 @@
<script setup lang="ts">
import Icon from '~/components/Common/Icon.vue';
import {computed} from "vue";
import {useAxios} from "~/vendor/axios";
import {getApiUrl} from "~/router";
import {useAdminMenu} from "~/components/Admin/menu";
@ -102,9 +101,8 @@ import MemoryStatsPanel from "~/components/Admin/Index/MemoryStatsPanel.vue";
import DiskUsagePanel from "~/components/Admin/Index/DiskUsagePanel.vue";
import ServicesPanel from "~/components/Admin/Index/ServicesPanel.vue";
import NetworkStatsPanel from "~/components/Admin/Index/NetworkStatsPanel.vue";
import useRefreshableAsyncState from "~/functions/useRefreshableAsyncState.ts";
import {useIntervalFn} from "@vueuse/core";
import Loading from "~/components/Common/Loading.vue";
import useAutoRefreshingAsyncState from "~/functions/useAutoRefreshingAsyncState.ts";
const statsUrl = getApiUrl('/admin/server/stats');
@ -112,7 +110,7 @@ const menuItems = useAdminMenu();
const {axiosSilent} = useAxios();
const {state: stats, isLoading, execute: reloadStats} = useRefreshableAsyncState(
const {state: stats, isLoading} = useAutoRefreshingAsyncState(
() => axiosSilent.get(statsUrl.value).then(r => r.data),
{
cpu: {
@ -154,14 +152,8 @@ const {state: stats, isLoading, execute: reloadStats} = useRefreshableAsyncState
network: []
},
{
shallow: true
shallow: true,
timeout: 5000
}
);
useIntervalFn(
() => {
reloadStats()
},
computed(() => (!document.hidden) ? 5000 : 10000)
);
</script>

View File

@ -51,30 +51,22 @@ import RunningBadge from "~/components/Common/Badges/RunningBadge.vue";
import {getApiUrl} from "~/router.ts";
import {useAxios} from "~/vendor/axios.ts";
import {useNotify} from "~/functions/useNotify";
import useRefreshableAsyncState from "~/functions/useRefreshableAsyncState.ts";
import {useIntervalFn} from "@vueuse/core";
import {computed} from "vue";
import Loading from "~/components/Common/Loading.vue";
import useAutoRefreshingAsyncState from "~/functions/useAutoRefreshingAsyncState.ts";
const servicesUrl = getApiUrl('/admin/services');
const {axios, axiosSilent} = useAxios();
const {state: services, isLoading, execute: reloadServices} = useRefreshableAsyncState(
const {state: services, isLoading} = useAutoRefreshingAsyncState(
() => axiosSilent.get(servicesUrl.value).then(r => r.data),
[],
{
timeout: 5000,
shallow: true
}
);
useIntervalFn(
() => {
reloadServices()
},
computed(() => (!document.hidden) ? 5000 : 15000)
);
const {notifySuccess} = useNotify();
const doRestart = (serviceUrl) => {

View File

@ -276,9 +276,8 @@ import Icon from '~/components/Common/Icon.vue';
import PlayButton from "~/components/Common/PlayButton.vue";
import AlbumArt from "~/components/Common/AlbumArt.vue";
import {useAxios} from "~/vendor/axios";
import {useAsyncState, useIntervalFn} from "@vueuse/core";
import {useAsyncState} from "@vueuse/core";
import {computed, ref} from "vue";
import useRefreshableAsyncState from "~/functions/useRefreshableAsyncState";
import DashboardCharts from "~/components/DashboardCharts.vue";
import {useTranslate} from "~/vendor/gettext";
import Loading from "~/components/Common/Loading.vue";
@ -290,6 +289,7 @@ import useOptionalStorage from "~/functions/useOptionalStorage";
import {IconAccountCircle, IconHeadphones, IconInfo, IconSettings, IconWarning} from "~/components/Common/icons";
import UserInfoPanel from "~/components/Account/UserInfoPanel.vue";
import {getApiUrl} from "~/router.ts";
import useAutoRefreshingAsyncState from "~/functions/useAutoRefreshingAsyncState.ts";
const props = defineProps({
profileUrl: {
@ -339,14 +339,12 @@ const {state: notifications, isLoading: notificationsLoading} = useAsyncState(
[]
);
const {state: stations, isLoading: stationsLoading, execute: reloadStations} = useRefreshableAsyncState(
const {state: stations, isLoading: stationsLoading} = useAutoRefreshingAsyncState(
() => axiosSilent.get(stationsUrl.value).then((r) => r.data),
[],
);
useIntervalFn(
reloadStations,
computed(() => (!document.hidden) ? 15000 : 30000)
{
timeout: 15000
}
);
const $lightbox = ref<LightboxTemplateRef>(null);

View File

@ -90,11 +90,10 @@ import publicPagesPanelProps from "./publicPagesPanelProps";
import requestsPanelProps from "./requestsPanelProps";
import streamersPanelProps from "./streamersPanelProps";
import {pickProps} from "~/functions/pickProps";
import useRefreshableAsyncState from "~/functions/useRefreshableAsyncState";
import {useIntervalFn} from "@vueuse/core";
import {useSweetAlert} from "~/vendor/sweetalert";
import {useNotify} from "~/functions/useNotify";
import {useTranslate} from "~/vendor/gettext";
import useAutoRefreshingAsyncState from "~/functions/useAutoRefreshingAsyncState.ts";
const props = defineProps({
...backendPanelProps,
@ -129,7 +128,7 @@ const hasActiveBackend = computed(() => {
const {axios, axiosSilent} = useAxios();
const {state: profileInfo, execute: reloadProfile} = useRefreshableAsyncState(
const {state: profileInfo} = useAutoRefreshingAsyncState(
() => axiosSilent.get(props.profileApiUri).then((r) => r.data),
{
station: {
@ -142,14 +141,12 @@ const {state: profileInfo, execute: reloadProfile} = useRefreshableAsyncState(
needs_restart: false
},
schedule: []
},
{
timeout: 15000
}
);
useIntervalFn(
reloadProfile,
computed(() => (!document.hidden) ? 15000 : 30000)
);
const {showAlert} = useSweetAlert();
const {notify} = useNotify();
const {$gettext} = useTranslate();

View File

@ -153,7 +153,7 @@
style="line-height: 1;"
>
{{ np.playing_next.song.title }}<br>
<small>{{ np.playing_next.song.artist }}</small>
<small class="text-muted">{{ np.playing_next.song.artist }}</small>
</h6>
</div>
<div v-else>

View File

@ -0,0 +1,63 @@
import useRefreshableAsyncState from "~/functions/useRefreshableAsyncState.ts";
import {Pausable, UseAsyncStateOptions, UseAsyncStateReturn, useIntervalFn} from "@vueuse/core";
import {computed} from "vue";
interface AutoRefreshingAsyncStateOptions<Shallow extends boolean, D = any>
extends UseAsyncStateOptions<Shallow, D> {
timeout?: number
}
interface AutoRefreshingAsyncStateReturn<Data, Params extends any[], Shallow extends boolean>
extends UseAsyncStateReturn<Data, Params, Shallow>, Pausable {
}
export default function useAutoRefreshingAsyncState<Data, Params extends any[] = [], Shallow extends boolean = true>(
promise: Promise<Data> | ((...args: Params) => Promise<Data>),
initialState: Data,
options: AutoRefreshingAsyncStateOptions<Shallow, Data> = {}
): AutoRefreshingAsyncStateReturn<Data, Params, Shallow> {
const {
timeout = 15000
} = options ?? {}
const {
state,
isReady,
isLoading,
error,
execute
} = useRefreshableAsyncState(
promise,
initialState,
{
throwError: true,
...options
}
);
const intervalDelay = computed(() =>
(!document.hidden) ? timeout : (timeout * 2)
);
const {isActive, pause, resume} = useIntervalFn(
async () => {
try {
await execute();
} catch (e) {
pause();
}
},
intervalDelay
);
return {
state,
isReady,
isLoading,
error,
execute,
isActive,
pause,
resume
};
}

View File

@ -1,5 +1,6 @@
import {useAsyncState} from "@vueuse/core";
import {useAsyncState, UseAsyncStateOptions, UseAsyncStateReturn} from "@vueuse/core";
import syncOnce from "~/functions/syncOnce";
import {Ref} from "vue";
/**
* Just like useAsyncState, except with settings changed:
@ -8,12 +9,18 @@ import syncOnce from "~/functions/syncOnce";
*
* @see useAsyncState
*/
export default function useRefreshableAsyncState(
promise,
initialState,
options = {}
) {
const {state, isLoading: allIsLoading, execute} = useAsyncState(
export default function useRefreshableAsyncState<Data, Params extends any[] = [], Shallow extends boolean = true>(
promise: Promise<Data> | ((...args: Params) => Promise<Data>),
initialState: Data,
options: UseAsyncStateOptions<Shallow, Data> = {}
): UseAsyncStateReturn<Data, Params, Shallow> {
const {
state,
isReady,
isLoading: allIsLoading,
error,
execute
} = useAsyncState(
promise,
initialState,
{
@ -22,11 +29,13 @@ export default function useRefreshableAsyncState(
}
);
const isLoading = syncOnce(allIsLoading);
const isLoading: Ref<boolean> = syncOnce(allIsLoading);
return {
state,
isReady,
isLoading,
error,
execute
};
}