chore(websocket): add function to send and wait for response (#2004)

This commit is contained in:
Stefan Dej 2024-09-16 00:45:12 +02:00 committed by GitHub
parent 3b4de5fc25
commit de697da87b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 62 additions and 29 deletions

View File

@ -30,6 +30,13 @@ export class WebSocketClient {
handleMessage(data: any) {
const wait = this.getWaitById(data.id)
// reject promise if it exists
if ('error' in data && wait?.reject) {
wait.reject(data.error)
this.removeWaitById(wait.id)
return
}
// report error messages
if (data.error?.message) {
// only report errors, if not disconnected and no init component
@ -37,12 +44,7 @@ export class WebSocketClient {
window.console.error(`Response Error: ${data.error.message} (${wait?.action ?? 'no action'})`)
}
if (data.error.message === 'Unauthorized' && wait?.action === 'server/setConnectionId') {
this.close()
this.store?.dispatch('socket/setConnectionFailed', data.error.message)
}
if (wait?.id) {
if (wait) {
const modulename = wait.action?.split('/')[1] ?? null
if (
@ -69,8 +71,11 @@ export class WebSocketClient {
return
}
// resolve promise if it exists
if (wait?.resolve) wait.resolve(data.result ?? {})
// pass result to action
if (wait?.action) {
if (wait.action) {
let result = data.result
if (result === 'ok') result = { result: result }
if (typeof result === 'string') result = { result: result }
@ -164,7 +169,7 @@ export class WebSocketClient {
if (options.loading) this.store?.dispatch('socket/addLoading', { name: options.loading })
this.instance.send(
this.instance?.send(
JSON.stringify({
jsonrpc: '2.0',
method,
@ -174,6 +179,34 @@ export class WebSocketClient {
)
}
async emitAndWait(method: string, params: Params, options: emitOptions = {}): Promise<any> {
return new Promise((resolve, reject) => {
if (this.instance?.readyState !== WebSocket.OPEN) reject()
const id = this.messageId++
this.waits.push({
id: id,
params: params,
action: options.action ?? null,
actionPayload: options.actionPayload ?? {},
loading: options.loading ?? null,
resolve,
reject,
})
if (options.loading) this.store?.dispatch('socket/addLoading', { name: options.loading })
this.instance?.send(
JSON.stringify({
jsonrpc: '2.0',
method,
params,
id,
})
)
})
}
emitBatch(messages: BatchMessage[]): void {
if (messages.length === 0) return
if (this.instance?.readyState !== WebSocket.OPEN) return
@ -245,6 +278,8 @@ export interface Wait {
action?: string | null
actionPayload?: any
loading?: string | null
resolve?: (value: any) => void
reject?: (reason: any) => void
}
interface Params {

View File

@ -16,16 +16,33 @@ export const actions: ActionTree<ServerState, RootState> = {
dispatch('updateManager/reset')
},
async init({ dispatch }) {
async init({ commit, dispatch, rootState }) {
window.console.debug('init Server')
// identify client
try {
const connection = await Vue.$socket.emitAndWait('server.connection.identify', {
client_name: 'mainsail',
version: rootState.packageVersion,
type: 'web',
url: 'https://github.com/mainsail-crew/mainsail',
})
commit('setConnectionId', connection.connection_id)
} catch (e: any) {
if (e.message === 'Unauthorized') {
this.dispatch('socket/setConnectionFailed', e.message)
}
window.console.error('Error while identifying client: ' + e.message)
return
}
dispatch('socket/addInitModule', 'server/info', { root: true })
dispatch('socket/addInitModule', 'server/config', { root: true })
dispatch('socket/addInitModule', 'server/systemInfo', { root: true })
dispatch('socket/addInitModule', 'server/procStats', { root: true })
dispatch('socket/addInitModule', 'server/databaseList', { root: true })
dispatch('identify')
Vue.$socket.emit('server.info', {}, { action: 'server/initServerInfo' })
Vue.$socket.emit('server.config', {}, { action: 'server/initServerConfig' })
Vue.$socket.emit('machine.system_info', {}, { action: 'server/initSystemInfo' })
@ -35,25 +52,6 @@ export const actions: ActionTree<ServerState, RootState> = {
await dispatch('socket/removeInitModule', 'server', { root: true })
},
identify({ dispatch, rootState }): void {
dispatch('socket/addInitModule', 'server/identify', { root: true })
Vue.$socket.emit(
'server.connection.identify',
{
client_name: 'mainsail',
version: rootState.packageVersion,
type: 'web',
url: 'https://github.com/mainsail-crew/mainsail',
},
{ action: 'server/setConnectionId' }
)
},
setConnectionId({ commit, dispatch }, payload) {
commit('setConnectionId', payload.connection_id)
dispatch('socket/removeInitModule', 'server/identify', { root: true })
},
checkDatabases({ dispatch, commit }, payload) {
if (payload.namespaces?.includes('mainsail')) {
dispatch('socket/addInitModule', 'gui/init', { root: true })