Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Sep 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions src/plugins/webSocketClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,21 @@ 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
if (data.error?.message !== 'Klippy Disconnected') {
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 (
Expand All @@ -68,8 +70,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 }
Expand Down Expand Up @@ -158,7 +163,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,
Expand All @@ -168,6 +173,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
Expand Down Expand Up @@ -228,6 +261,8 @@ export interface Wait {
action?: string | null
actionPayload?: any
loading?: string | null
resolve?: (value: any) => void
reject?: (reason: any) => void
}

interface Params {
Expand Down
40 changes: 19 additions & 21 deletions src/store/server/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' })
Expand All @@ -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 })
Expand Down
Loading