diff --git a/packages/api/src/controllers/sessions.js b/packages/api/src/controllers/sessions.js index e42844214..8af656bac 100644 --- a/packages/api/src/controllers/sessions.js +++ b/packages/api/src/controllers/sessions.js @@ -103,6 +103,10 @@ module.exports = { if (handleProcessCommunication(message, subprocess)) return; this[`handle_${msgtype}`](sesid, message); }); + subprocess.on('exit', () => { + this.opened = this.opened.filter(x => x.sesid != sesid); + }); + subprocess.send({ msgtype: 'connect', ...connection, database }); return _.pick(newOpened, ['conid', 'database', 'sesid']); }, @@ -165,6 +169,17 @@ module.exports = { return { state: 'ok' }; }, + ping_meta: true, + async ping({ sesid }) { + const session = this.opened.find(x => x.sesid == sesid); + if (!session) { + throw new Error('Invalid session'); + } + session.subprocess.send({ msgtype: 'ping' }); + + return { state: 'ok' }; + }, + // runCommand_meta: true, // async runCommand({ conid, database, sql }) { // console.log(`Running SQL command , conid=${conid}, database=${database}, sql=${sql}`); diff --git a/packages/api/src/proc/sessionProcess.js b/packages/api/src/proc/sessionProcess.js index 459e934f5..d61f08d4b 100644 --- a/packages/api/src/proc/sessionProcess.js +++ b/packages/api/src/proc/sessionProcess.js @@ -15,6 +15,7 @@ let systemConnection; let storedConnection; let afterConnectCallbacks = []; // let currentHandlers = []; +let lastPing = null; class TableWriter { constructor() { @@ -271,10 +272,15 @@ async function handleExecuteReader({ jslid, sql, fileName }) { }); } +function handlePing() { + lastPing = new Date().getTime(); +} + const messageHandlers = { connect: handleConnect, executeQuery: handleExecuteQuery, executeReader: handleExecuteReader, + ping: handlePing, // cancel: handleCancel, }; @@ -285,6 +291,15 @@ async function handleMessage({ msgtype, ...other }) { function start() { childProcessChecker(); + + setInterval(() => { + const time = new Date().getTime(); + if (time - lastPing > 30_000) { + console.log('Session not alive, exiting'); + process.exit(0); + } + }, 30_000); + process.on('message', async message => { if (handleProcessCommunication(message)) return; try { diff --git a/packages/web/src/tabs/QueryDesignTab.svelte b/packages/web/src/tabs/QueryDesignTab.svelte index 5a416d803..85f2e5d32 100644 --- a/packages/web/src/tabs/QueryDesignTab.svelte +++ b/packages/web/src/tabs/QueryDesignTab.svelte @@ -54,6 +54,7 @@ import ToolStripCommandButton from '../buttons/ToolStripCommandButton.svelte'; import ToolStripExportButton, { createQuickExportHandlerRef } from '../buttons/ToolStripExportButton.svelte'; import ToolStripSaveButton from '../buttons/ToolStripSaveButton.svelte'; + import { onDestroy, onMount } from 'svelte'; export let tabid; export let conid; @@ -102,6 +103,22 @@ $: generatePreview($modelState.value, engine); + let intervalId; + + onMount(() => { + intervalId = setInterval(() => { + if (sessionId) { + apiCall('sessions/ping', { + sesid: sessionId, + }); + } + }, 15_000); + }); + + onDestroy(() => { + clearInterval(intervalId); + }); + export function canKill() { return !!sessionId; } diff --git a/packages/web/src/tabs/QueryTab.svelte b/packages/web/src/tabs/QueryTab.svelte index 60958bb6a..be7bc87f3 100644 --- a/packages/web/src/tabs/QueryTab.svelte +++ b/packages/web/src/tabs/QueryTab.svelte @@ -50,7 +50,7 @@