diff --git a/index.js b/index.js index 79d90a3..36ea844 100644 --- a/index.js +++ b/index.js @@ -17,6 +17,7 @@ const constants = require('./src/constants') const ChannelDB = require("./src/dao/channel-db"); const FillerDB = require("./src/dao/filler-db"); const TVGuideService = require("./src/tv-guide-service"); +const onShutdown = require("node-graceful-shutdown").onShutdown; console.log( ` \\ @@ -209,3 +210,11 @@ function initDB(db, channelDB) { } } + +onShutdown("log" , [], async() => { + console.log("Received exit signal, attempting graceful shutdonw..."); +}); +onShutdown("xmltv-writer" , [], async() => { + await xmltv.shutdown(); +} ); + diff --git a/package.json b/package.json index 22d7a59..a5498d0 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "angular": "^1.7.9", "angular-router-browserify": "0.0.2", "angular-vs-repeat": "2.0.13", + "random-js" : "2.1.0", "axios": "^0.19.2", "body-parser": "^1.19.0", "diskdb": "^0.1.17", @@ -26,6 +27,7 @@ "node-ssdp": "^4.0.0", "request": "^2.88.2", "uuid": "^8.0.0", + "node-graceful-shutdown" : "1.1.0", "xml-writer": "^1.7.0" }, "bin": "dist/index.js", diff --git a/src/helperFuncs.js b/src/helperFuncs.js index aaffd4c..37f3efe 100644 --- a/src/helperFuncs.js +++ b/src/helperFuncs.js @@ -6,6 +6,9 @@ module.exports = { let channelCache = require('./channel-cache'); const SLACK = require('./constants').SLACK; +const randomJS = require("random-js"); +const Random = randomJS.Random; +const random = new Random( randomJS.MersenneTwister19937.autoSeed() ); function getCurrentProgramAndTimeElapsed(date, channel) { let channelStartTime = (new Date(channel.startTime)).getTime(); @@ -102,7 +105,7 @@ function createLineup(obj, channel, fillers, isFirst) { //it's boring and odd to tune into a channel and it's always //the start of a commercial. let more = Math.max(0, filler.duration - fillerstart - 15000 - SLACK); - fillerstart += Math.floor(more * Math.random() ); + fillerstart += random.integer(0, more); } lineup.push({ // just add the video, starting at 0, playing the entire duration type: 'commercial', @@ -152,12 +155,7 @@ function createLineup(obj, channel, fillers, isFirst) { } function weighedPick(a, total) { - if (a==total) { - return true; - } else { - let ran = Math.random(); - return ran * total < a; - } + return random.bool(a, total); } function pickRandomWithMaxDuration(channel, fillers, maxDuration) { diff --git a/src/plexTranscoder.js b/src/plexTranscoder.js index 00663a1..11f3def 100644 --- a/src/plexTranscoder.js +++ b/src/plexTranscoder.js @@ -182,7 +182,7 @@ lang=en` try { return this.getVideoStats().videoDecision === "copy"; } catch (e) { - console.log("Error at decision:" + e); + console.log("Error at decision:", e); return false; } } @@ -199,7 +199,7 @@ lang=en` try { return this.getVideoStats().videoDecision === "copy" && this.getVideoStats().audioDecision === "copy"; } catch (e) { - console.log("Error at decision:" + e); + console.log("Error at decision:" , e); return false; } } @@ -245,7 +245,7 @@ lang=en` } }.bind(this) ) } catch (e) { - console.log("Error at decision:" + e); + console.log("Error at decision:" , e); } this.log("Current video stats:") @@ -313,7 +313,7 @@ lang=en` async getDecision(directPlay) { try { - this.getDecisionUnmanaged(directPlay); + await this.getDecisionUnmanaged(directPlay); } catch (err) { console.error(err); } diff --git a/src/xmltv.js b/src/xmltv.js index d1596be..6d738b2 100644 --- a/src/xmltv.js +++ b/src/xmltv.js @@ -1,11 +1,29 @@ const XMLWriter = require('xml-writer') const fs = require('fs') -const helperFuncs = require('./helperFuncs') -const constants = require('./constants') -module.exports = { WriteXMLTV: WriteXMLTV } +module.exports = { WriteXMLTV: WriteXMLTV, shutdown: shutdown } -function WriteXMLTV(json, xmlSettings, throttle ) { +let isShutdown = false; +let isWorking = false; + +async function WriteXMLTV(json, xmlSettings, throttle ) { + if (isShutdown) { + return; + } + if (isWorking) { + console.log("Concurrent xmltv write attempt detected, skipping"); + return; + } + isWorking = true; + try { + await writePromise(json, xmlSettings, throttle); + } catch (err) { + console.error("Error writing xmltv", err); + } + isWorking = false; +} + +function writePromise(json, xmlSettings, throttle) { return new Promise((resolve, reject) => { let ws = fs.createWriteStream(xmlSettings.file) let xw = new XMLWriter(true, (str, enc) => ws.write(str, enc)) @@ -59,7 +77,9 @@ function _writeChannels(xw, channels) { async function _writePrograms(xw, channel, programs, throttle) { for (let i = 0; i < programs.length; i++) { - await throttle(); + if (! isShutdown) { + await throttle(); + } await _writeProgramme(channel, programs[i], xw); } } @@ -117,8 +137,25 @@ async function _writeProgramme(channel, program, xw) { function _createXMLTVDate(d) { return d.substring(0,19).replace(/[-T:]/g,"") + " +0000"; } -function _throttle() { +function wait(x) { return new Promise((resolve) => { - setTimeout(resolve, 0); + setTimeout(resolve, x); }); } + +async function shutdown() { + isShutdown = true; + console.log("Shutting down xmltv writer."); + if (isWorking) { + let s = "Wait for xmltv writer..."; + while (isWorking) { + console.log(s); + await wait(100); + s = "Still waiting for xmltv writer..."; + } + console.log("Write finished."); + } else { + console.log("xmltv writer had no pending jobs."); + } +} +