fix(front): resolve initialization race condition

Part-of: <https://dev.funkwhale.audio/funkwhale/funkwhale/-/merge_requests/2534>
environments/review-front-wvff-mk2g74/deployments/18198
Kasper Seweryn 2023-07-25 14:28:35 +02:00 zatwierdzone przez Marge
rodzic 4525d083af
commit 93bf644d2c
2 zmienionych plików z 32 dodań i 13 usunięć

Wyświetl plik

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

Wyświetl plik

@ -1,4 +1,4 @@
import type { InitModule } from '~/types'
import type { InitModule, InitModuleContext } from '~/types'
import store, { key } from '~/store'
import router from '~/router'
@ -22,6 +22,7 @@ const app = createApp({
data: () => ({ ready: false }),
mounted () {
this.ready = true
logger.info('Everything loaded!')
},
render () {
if (this.ready) {
@ -35,19 +36,35 @@ const app = createApp({
app.use(router)
app.use(store, key)
const modules: Array<void | Promise<void>> = []
for (const module of Object.values(import.meta.glob('./init/*.ts', { eager: true })) as { install?: InitModule }[]) {
modules.push(module.install?.({
app,
router,
store
}))
const modules: Record<string | 'axios', { install?: InitModule }> = import.meta.glob('./init/*.ts', { eager: true })
const moduleContext: InitModuleContext = {
app,
router,
store
}
// Wait for all modules to load
Promise.all(modules).finally(() => {
app.mount('#app')
logger.info('Everything loaded!')
})
// NOTE: Other modules may depend on network requests and we need to ensure
// that all axios interceptors are set before any requests are made
// and that the instance url is set before any requests are made
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