fix(front): resolve initialization race condition

Part-of: <https://dev.funkwhale.audio/funkwhale/funkwhale/-/merge_requests/2534>
This commit is contained in:
Kasper Seweryn 2023-07-25 14:28:35 +02:00 committed by Marge
parent 4525d083af
commit 93bf644d2c
2 changed files with 32 additions and 13 deletions

View File

@ -0,0 +1,2 @@
Resolve race condition regarding axios when initializing the frontend
Prevent sending same language setting to backend multiple times

View File

@ -1,4 +1,4 @@
import type { InitModule } from '~/types' import type { InitModule, InitModuleContext } from '~/types'
import store, { key } from '~/store' import store, { key } from '~/store'
import router from '~/router' import router from '~/router'
@ -22,6 +22,7 @@ const app = createApp({
data: () => ({ ready: false }), data: () => ({ ready: false }),
mounted () { mounted () {
this.ready = true this.ready = true
logger.info('Everything loaded!')
}, },
render () { render () {
if (this.ready) { if (this.ready) {
@ -35,19 +36,35 @@ const app = createApp({
app.use(router) app.use(router)
app.use(store, key) app.use(store, key)
const modules: Array<void | Promise<void>> = [] const modules: Record<string | 'axios', { install?: InitModule }> = import.meta.glob('./init/*.ts', { eager: true })
for (const module of Object.values(import.meta.glob('./init/*.ts', { eager: true })) as { install?: InitModule }[]) { const moduleContext: InitModuleContext = {
modules.push(module.install?.({ app,
app, router,
router, store
store
}))
} }
// Wait for all modules to load // NOTE: Other modules may depend on network requests and we need to ensure
Promise.all(modules).finally(() => { // that all axios interceptors are set before any requests are made
app.mount('#app') // and that the instance url is set before any requests are made
logger.info('Everything loaded!') const IMPORTANT_MODULES_QUEUE = ['axios', 'instance']
}) const waitForImportantModules = async () => {
for (const moduleName of IMPORTANT_MODULES_QUEUE) {
const path = `./init/${moduleName}.ts`
if (!(path in modules)) {
logger.error(`Failed to load important module: ${path}`)
continue
}
await modules[path].install?.(moduleContext)
delete modules[path]
}
}
waitForImportantModules()
// NOTE: We load the modules in parallel
.then(() => Promise.all(Object.values(modules).map(module => module.install?.(moduleContext))))
.catch(error => logger.error('Failed to load modules:', error))
// NOTE: We need to mount the app after all modules are loaded
.finally(() => app.mount('#app'))
// TODO (wvffle): Rename filters from useSharedLabels to filters from backend // TODO (wvffle): Rename filters from useSharedLabels to filters from backend