Refactor event source and storage from useSchedule
Split up useSchedule into a useEventSource composable and a schedules store for keeping track of the schedule updates.
This commit is contained in:
parent
68f731f094
commit
cf90de1aae
3 changed files with 221 additions and 71 deletions
92
stores/schedules.ts
Normal file
92
stores/schedules.ts
Normal file
|
@ -0,0 +1,92 @@
|
|||
import type { Schedule } from "~/shared/types/schedule";
|
||||
|
||||
interface SyncOperation {
|
||||
controller: AbortController,
|
||||
promise: Promise<Ref<Schedule>>,
|
||||
}
|
||||
|
||||
export const useSchedulesStore = defineStore("schedules", () => {
|
||||
const sessionStore = useSessionStore();
|
||||
|
||||
const state = {
|
||||
activeScheduleId: ref<number | undefined>(111),
|
||||
schedules: ref<Map<number, Ref<Schedule>>>(new Map()),
|
||||
pendingSyncs: ref<Map<number, SyncOperation>>(new Map()),
|
||||
};
|
||||
|
||||
const getters = {
|
||||
activeSchedule: computed(() => {
|
||||
if (state.activeScheduleId.value === undefined)
|
||||
throw Error("No active schedule");
|
||||
const schedule = state.schedules.value.get(state.activeScheduleId.value);
|
||||
if (!schedule)
|
||||
throw Error("Active schedule has not been fetched");
|
||||
return schedule;
|
||||
}),
|
||||
};
|
||||
|
||||
const actions = {
|
||||
async fetch(id: number) {
|
||||
if (id !== 111) { throw Error("invalid id"); }
|
||||
console.log("schedules store fetch", id);
|
||||
const schedule = state.schedules.value.get(id);
|
||||
if (schedule) {
|
||||
console.log("return cached");
|
||||
return schedule;
|
||||
}
|
||||
const pending = state.pendingSyncs.value.get(id);
|
||||
if (pending) {
|
||||
console.log("return pending");
|
||||
return pending.promise;
|
||||
}
|
||||
|
||||
console.log("return new fetch");
|
||||
const requestFetch = useRequestFetch();
|
||||
const controller = new AbortController();
|
||||
const promise = (async () => {
|
||||
try {
|
||||
const schedule = ref(await requestFetch("/api/schedule", { signal: controller.signal }));
|
||||
state.schedules.value.set(id, schedule);
|
||||
state.pendingSyncs.value.delete(id);
|
||||
return schedule;
|
||||
} catch (err: any) {
|
||||
if (err.name !== "AbortError")
|
||||
state.pendingSyncs.value.delete(id);
|
||||
throw err;
|
||||
}
|
||||
})();
|
||||
state.pendingSyncs.value.set(id, {
|
||||
controller,
|
||||
promise,
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
async resync(id: number) {
|
||||
if (id !== 111) { throw Error("invalid id"); }
|
||||
const pending = state.pendingSyncs.value.get(id);
|
||||
if (pending) {
|
||||
pending.controller.abort();
|
||||
}
|
||||
state.schedules.value.delete(id);
|
||||
state.pendingSyncs.value.delete(id);
|
||||
await actions.fetch(id);
|
||||
},
|
||||
}
|
||||
|
||||
watch(() => sessionStore.id, (id, oldId) => {
|
||||
for (const [scheduleId, pending] of state.pendingSyncs.value) {
|
||||
console.log("Aborting pending schedule sync", scheduleId, "due session.id change from", oldId, "to", id);
|
||||
pending.controller.abort();
|
||||
state.pendingSyncs.value.delete(scheduleId);
|
||||
}
|
||||
})
|
||||
|
||||
appEventSource?.addEventListener("update", (event) => {
|
||||
const schedule = state.schedules.value.get(111);
|
||||
if (schedule) {
|
||||
schedule.value = event.data;
|
||||
}
|
||||
});
|
||||
|
||||
return { ...state, ...getters, ...actions };
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue