From 012ea1a7301eb8e73653191a4a401216ede871f3 Mon Sep 17 00:00:00 2001 From: Alexis Tyler Date: Sat, 31 Aug 2019 13:51:29 +0930 Subject: [PATCH] remove websocket from clients when socket closes and switch info subscription to basic handler for now Signed-off-by: Alexis Tyler --- app/graphql/index.js | 5 +++ app/graphql/schema/resolvers.js | 65 +++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/app/graphql/index.js b/app/graphql/index.js index 6c39dd48d..7f95c087e 100644 --- a/app/graphql/index.js +++ b/app/graphql/index.js @@ -302,6 +302,11 @@ module.exports = function ( onDisconnect: webSocket => { const user = clients.get(webSocket); log.debug(` ${user.name} disconnected.`); + + // If we don't wait a tick `user` becomes undefined. + process.nextTick(() => { + clients.delete(webSocket); + }); } }, context: ({ req, connection }) => { diff --git a/app/graphql/schema/resolvers.js b/app/graphql/schema/resolvers.js index de5766b8a..f9637c3ca 100644 --- a/app/graphql/schema/resolvers.js +++ b/app/graphql/schema/resolvers.js @@ -3,7 +3,7 @@ * Written by: Alexis Tyler */ -module.exports = function ($injector, GraphQLJSON, GraphQLLong, GraphQLUUID, pubsub, setIntervalAsync, PluginManager, log) { +module.exports = function ($injector, GraphQLJSON, GraphQLLong, GraphQLUUID, pubsub, setIntervalAsync, PluginManager, log, fromEntries, asyncMap, delay) { const publish = (channel, mutation, { node = undefined, moduleToRun = undefined, @@ -137,12 +137,63 @@ module.exports = function ($injector, GraphQLJSON, GraphQLLong, GraphQLUUID, pub ...createBasicSubscription('docker/networks', 'docker/get-networks') }, info: { - apps: createBasicSubscription('info/apps', 'info/get-apps'), - cpu: createBasicSubscription('info/cpu', 'info/get-cpu'), - devices: createBasicSubscription('info/devices', 'info/get-devices'), - display: createBasicSubscription('info/display', 'info/get-display'), - os: createBasicSubscription('info/os', 'info/get-os'), - versions: createBasicSubscription('info/versions', 'info/get-versions') + subscribe: () => pubsub.asyncIterator('info'), + close() { + console.debug('Clearing info subscription timers'); + + // Clear all info subscription timers + Object.entries($injector._graph).filter(([ name ]) => { + return name.startsWith('timer:info'); + }).map(([name, timer]) => { + console.debug(`Clearing ${name} subscription timer`); + clearInterval(timer); + }); + } + // subscribe: async () => { + // const infoFields = [ + // 'apps', + // 'cpu', + // 'devices', + // 'display', + // 'os', + // 'versions' + // ]; + + // const infoModules = infoFields.map(field => [field, $injector.resolveModule(`module:info/get-${field}`)]); + // let run = 0; + + // return { + // async next() { + // // Await each field to get new value + // const values = fromEntries(await asyncMap(infoModules, async ([field, _module]) => { + // return [field, await _module.then(result => result.json)]; + // })); + + // const result = { + // value: { + // info: { + // mutation: 'UPDATED', + // node: { + // ...values + // } + // } + // }, + // done: false + // }; + + // run = run + 1; + // console.log(`Run ${run}, ${Object.keys(values)}`); + // // Kill after 10 + // if (run >= 10) { + // return { value: null, done: true }; + // } + // return result; + // }, + // [Symbol.asyncIterator]() { + // return this; + // } + // }; + // } }, me: { subscribe: withFilter(() => pubsub.asyncIterator('user'), (payload, _, context) => payload.user.node.id === context.user.id),