diff --git a/app.js b/app.js index 6c9c01f70..241ccaebc 100644 --- a/app.js +++ b/app.js @@ -10,8 +10,6 @@ const FileStore = require('session-file-store')(session); const os = require('os'); const sessionSecret = require('./services/session_secret'); -require('./services/ping_job'); - const app = express(); // view engine setup diff --git a/public/javascripts/messaging.js b/public/javascripts/messaging.js index eca8aacd1..c393a45df 100644 --- a/public/javascripts/messaging.js +++ b/public/javascripts/messaging.js @@ -2,7 +2,6 @@ const messaging = (function() { const changesToPushCountEl = $("#changes-to-push-count"); - let ws = null; function logError(message) { console.log(now(), message); // needs to be separate from .trace() @@ -21,12 +20,15 @@ const messaging = (function() { if (message.type === 'sync') { lastPingTs = new Date().getTime(); - const syncData = message.data.filter(sync => sync.source_id !== glob.sourceId); - if (syncData.length > 0) { - console.log(now(), "Sync data: ", message); + if (message.data.length > 0) { + console.log(now(), "Sync data: ", message.data); + + lastSyncId = message.data[message.data.length - 1].id; } + const syncData = message.data.filter(sync => sync.source_id !== glob.sourceId); + if (syncData.some(sync => sync.entity_name === 'notes_tree')) { console.log(now(), "Reloading tree because of background changes"); @@ -59,17 +61,20 @@ const messaging = (function() { const protocol = document.location.protocol === 'https:' ? 'wss' : 'ws'; // use wss for secure messaging - ws = new WebSocket(protocol + "://" + location.host); + const ws = new WebSocket(protocol + "://" + location.host); ws.onopen = event => console.log(now(), "Connected to server with WebSocket"); ws.onmessage = messageHandler; ws.onclose = function(){ // Try to reconnect in 5 seconds setTimeout(() => connectWebSocket(), 5000); }; + + return ws; } - connectWebSocket(); + const ws = connectWebSocket(); + let lastSyncId = glob.maxSyncIdAtLoad; let lastPingTs = new Date().getTime(); let connectionBrokenNotification = null; @@ -92,7 +97,12 @@ const messaging = (function() { showMessage("Re-connected to server"); } - }, 3000); + + ws.send(JSON.stringify({ + type: 'ping', + lastSyncId: lastSyncId + })); + }, 1000); return { logError diff --git a/routes/index.js b/routes/index.js index ee326b404..a420ffc4b 100644 --- a/routes/index.js +++ b/routes/index.js @@ -4,10 +4,12 @@ const express = require('express'); const router = express.Router(); const auth = require('../services/auth'); const source_id = require('../services/source_id'); +const sql = require('../services/sql'); router.get('', auth.checkAuth, async (req, res, next) => { res.render('index', { - sourceId: await source_id.generateSourceId() + sourceId: await source_id.generateSourceId(), + maxSyncIdAtLoad: await sql.getSingleValue("SELECT MAX(id) FROM sync") }); }); diff --git a/services/consistency_checks.js b/services/consistency_checks.js index 5a74a727f..063bb36ab 100644 --- a/services/consistency_checks.js +++ b/services/consistency_checks.js @@ -47,7 +47,7 @@ async function runChecks() { await runSyncRowChecks("recent_notes", "note_tree_id", errorList); if (errorList.length > 0) { - messaging.sendMessage({type: 'consistency-checks-failed'}); + messaging.sendMessageToAllClients({type: 'consistency-checks-failed'}); } else { log.info("All consistency checks passed."); diff --git a/services/messaging.js b/services/messaging.js index c6e5842df..5773070a3 100644 --- a/services/messaging.js +++ b/services/messaging.js @@ -1,6 +1,9 @@ const WebSocket = require('ws'); const utils = require('./utils'); const log = require('./log'); +const sql = require('./sql'); +const options = require('./options'); +const sync_setup = require('./sync_setup'); let webSocketServer; @@ -29,6 +32,9 @@ function init(httpServer, sessionParser) { if (message.type === 'log-error') { log.error('JS Error: ' + message.error); } + else if (message.type === 'ping') { + sendPing(ws, message.lastSyncId); + } else { log.error('Unrecognized message: '); log.error(message); @@ -37,7 +43,15 @@ function init(httpServer, sessionParser) { }); } -async function sendMessage(message) { +async function sendMessage(client, message) { + const jsonStr = JSON.stringify(message); + + if (client.readyState === WebSocket.OPEN) { + client.send(jsonStr); + } +} + +async function sendMessageToAllClients(message) { const jsonStr = JSON.stringify(message); webSocketServer.clients.forEach(function each(client) { @@ -47,7 +61,21 @@ async function sendMessage(message) { }); } +async function sendPing(client, lastSentSyncId) { + const syncData = await sql.getResults("SELECT * FROM sync WHERE id > ?", [lastSentSyncId]); + + const lastSyncedPush = await options.getOption('last_synced_push'); + + const changesToPushCount = await sql.getSingleValue("SELECT COUNT(*) FROM sync WHERE id > ?", [lastSyncedPush]); + + await sendMessage(client, { + type: 'sync', + data: syncData, + changesToPushCount: sync_setup.isSyncSetup ? changesToPushCount : 0 + }); +} + module.exports = { init, - sendMessage + sendMessageToAllClients }; \ No newline at end of file diff --git a/services/ping_job.js b/services/ping_job.js deleted file mode 100644 index c9666ae77..000000000 --- a/services/ping_job.js +++ /dev/null @@ -1,30 +0,0 @@ -const sql = require('./sql'); -const messaging = require('./messaging'); -const options = require('./options'); -const sync_setup = require('./sync_setup'); - -let lastSentSyncId; - -async function sendPing() { - const syncData = await sql.getResults("SELECT * FROM sync WHERE id > ?", [lastSentSyncId]); - - const lastSyncedPush = await options.getOption('last_synced_push'); - - const changesToPushCount = await sql.getSingleValue("SELECT COUNT(*) FROM sync WHERE id > ?", [lastSyncedPush]); - - messaging.sendMessage({ - type: 'sync', - data: syncData, - changesToPushCount: sync_setup.isSyncSetup ? changesToPushCount : 0 - }); - - if (syncData.length > 0) { - lastSentSyncId = syncData[syncData.length - 1].id; - } -} - -sql.dbReady.then(async () => { - lastSentSyncId = await sql.getSingleValue("SELECT MAX(id) FROM sync"); - - setInterval(sendPing, 1000); -}); \ No newline at end of file diff --git a/services/sync.js b/services/sync.js index 1a1142c8f..505451ebe 100644 --- a/services/sync.js +++ b/services/sync.js @@ -267,7 +267,7 @@ async function checkContentHash(syncContext) { if (key !== 'recent_notes') { // let's not get alarmed about recent notes which get updated often and can cause failures in race conditions - await messaging.sendMessage({type: 'sync-hash-check-failed'}); + await messaging.sendMessageToAllClients({type: 'sync-hash-check-failed'}); } } } diff --git a/views/index.ejs b/views/index.ejs index c8e0d879f..3e7190345 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -301,7 +301,8 @@ const baseApiUrl = 'api/'; const glob = { activeDialog: null, - sourceId: '<%= sourceId %>' + sourceId: '<%= sourceId %>', + maxSyncIdAtLoad: <%= maxSyncIdAtLoad %> };