feat: sync engine with server, handle errors (WIP)

This commit is contained in:
Settel 2022-08-02 23:34:30 +02:00
parent c05c3cd2d6
commit af19fd33fc
8 changed files with 83 additions and 15 deletions

View File

@ -15,6 +15,7 @@
"sass-loader": "^13.0.2" "sass-loader": "^13.0.2"
}, },
"dependencies": { "dependencies": {
"@pinia/nuxt": "^0.3.1" "@pinia/nuxt": "^0.3.1",
"build-url": "^6.0.1"
} }
} }

View File

@ -0,0 +1,14 @@
import buildUrl from 'build-url'
export type QueryParams = {
[name: string]: string
}
export async function callApi(path: string, queryParams: QueryParams) {
const url = buildUrl('/', {
path,
queryParams,
})
return await $fetch(url)
}

View File

@ -1,3 +1,45 @@
export function fetchUpdate() { import { useUserinfoStore } from "@/stores/UserinfoStore"
console.log('fetchUpdate() called')
export async function fetchUpdate() {
if (this.shouldStop || !this.isActive) {
this.isActive = false
this.shouldStop = false
console.debug('engine stopped')
return
}
let delay = 0
try {
console.log(`sync[${this.version}]`)
const userInfoStore = useUserinfoStore()
const response = await this.callApi('/api/sync', {
v: this.version + 1,
g: userInfoStore.gameId,
})
if (!Number.isInteger(response.version)) {
throw Error('unexpected response for sync, property version not found.')
}
// TODO: parse answer
this.version = parseInt(response.version)
} catch (e) {
if (!e.response) {
// request aborted or other causes
return
}
const { status, statusText } = e.response
if (status == 200) {
delay = 1000
} else {
console.warn(`HTTP ${status} ${statusText}`)
delay = 5000
this.version = -1
}
}
window.setTimeout(() => {
this.fetchUpdate()
}, delay)
} }

View File

@ -1,7 +1,7 @@
import { useUserinfoStore } from "@/stores/UserinfoStore" import { useUserinfoStore } from "@/stores/UserinfoStore"
export function start(): void { export function start(): void {
if (this.isActive.value && !this.shouldStop.value) { if (this.isActive && !this.shouldStop) {
console.warn('attempt to start already running engine!') console.warn('attempt to start already running engine!')
return return
} }
@ -10,16 +10,16 @@ export function start(): void {
return return
} }
this.isActive.value = true this.isActive = true
this.shouldStop.value = false this.shouldStop = false
this.fetchUpdate() this.fetchUpdate()
console.log('start engine') console.log('start engine')
} }
export function stop(): void { export function stop(): void {
if (this.isActive.value) { if (this.isActive) {
this.shouldStop.value = true this.shouldStop = true
console.log('shut down engine') console.log('shut down engine')
} }
} }

View File

@ -1,12 +1,13 @@
import { useState } from '#app' import { callApi, QueryParams } from '@/composables/engine/callApi'
import { Ref } from 'vue'
import { start, stop } from '@/composables/engine/startStop' import { start, stop } from '@/composables/engine/startStop'
import { fetchUpdate } from '@/composables/engine/fetchUpdate' import { fetchUpdate } from '@/composables/engine/fetchUpdate'
interface EngineContext { interface EngineContext {
isActive: Ref<boolean> isActive: boolean
shouldStop: Ref<boolean> shouldStop: boolean
version: number
fetchUpdate: () => void fetchUpdate: () => void
callApi: (url: string, queryParams?: QueryParams) => Promise<unknown>
} }
export interface useEngine { export interface useEngine {
@ -17,8 +18,10 @@ export interface useEngine {
export default (): useEngine => { export default (): useEngine => {
const context: EngineContext = { const context: EngineContext = {
isActive: useState('engine__is-active', () => false), isActive: false,
shouldStop: useState('engine__should-stop', () => false), shouldStop: false,
version: -1,
callApi,
fetchUpdate, fetchUpdate,
} }

View File

@ -13,6 +13,9 @@ export const useUserinfoStore = defineStore('UserinfoStore', {
isGamemaster(): boolean { isGamemaster(): boolean {
return this.userInfo && ( this.userInfo.role === 'gamemaster' || this.userInfo.role === 'admin' ) return this.userInfo && ( this.userInfo.role === 'gamemaster' || this.userInfo.role === 'admin' )
}, },
gameId(): string | null {
return this.userInfo?.game
},
}, },
actions: { actions: {
setUserInfo(userInfo: unknown): void { setUserInfo(userInfo: unknown): void {

View File

@ -1023,6 +1023,11 @@ buffer@^5.5.0:
base64-js "^1.3.1" base64-js "^1.3.1"
ieee754 "^1.1.13" ieee754 "^1.1.13"
build-url@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/build-url/-/build-url-6.0.1.tgz#b16505136248e24b1b6d7ccab99c7ee73cd962a7"
integrity sha512-FEmyP+3hCVoBBxGZEfC8WCTvqASZb+QOvTznddKCBgdxZFqTww1+7vtZP0TUIL0/8sup0m0QpKaOaj/V4Mol0w==
builtin-modules@^3.0.0: builtin-modules@^3.0.0:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"

View File

@ -1 +1 @@
{"authcode":"123456","name":"Harry","role":"player","game":"663576f0-1378-496b-a970-578bdcb222af","created":1650831122,"lastLoggedIn":1651556261} {"authcode":"123456","name":"Harry","role":"player","game":"663576f0-1378-496b-a970-578bdcb222af","created":1650831122,"lastLoggedIn":1659475977}