diff --git a/server/managers/ShareManager.js b/server/managers/ShareManager.js index 4e5a96cbaf..07c57a45a2 100644 --- a/server/managers/ShareManager.js +++ b/server/managers/ShareManager.js @@ -1,12 +1,14 @@ const Database = require('../Database') const Logger = require('../Logger') const SocketAuthority = require('../SocketAuthority') +const LongTimeout = require('../utils/longTimeout') +const { elapsedPretty } = require('../utils/index') /** * @typedef OpenMediaItemShareObject * @property {string} id * @property {import('../models/MediaItemShare').MediaItemShareObject} mediaItemShare - * @property {NodeJS.Timeout} timeout + * @property {LongTimeout} timeout */ class ShareManager { @@ -118,13 +120,13 @@ class ShareManager { this.destroyMediaItemShare(mediaItemShare.id) return } - - const timeout = setTimeout(() => { + const timeout = new LongTimeout() + timeout.set(() => { Logger.info(`[ShareManager] Removing expired media item share "${mediaItemShare.id}"`) this.removeMediaItemShare(mediaItemShare.id) }, expiresAtDuration) this.openMediaItemShares.push({ id: mediaItemShare.id, mediaItemShare: mediaItemShare.toJSON(), timeout }) - Logger.info(`[ShareManager] Scheduled media item share "${mediaItemShare.id}" to expire in ${expiresAtDuration}ms`) + Logger.info(`[ShareManager] Scheduled media item share "${mediaItemShare.id}" to expire in ${elapsedPretty(expiresAtDuration / 1000)}`) } /** @@ -149,7 +151,7 @@ class ShareManager { if (!mediaItemShare) return if (mediaItemShare.timeout) { - clearTimeout(mediaItemShare.timeout) + mediaItemShare.timeout.clear() } this.openMediaItemShares = this.openMediaItemShares.filter((s) => s.id !== mediaItemShareId) diff --git a/server/utils/index.js b/server/utils/index.js index 14f297c13d..2d52bcd084 100644 --- a/server/utils/index.js +++ b/server/utils/index.js @@ -66,6 +66,11 @@ module.exports.getId = (prepend = '') => { return _id } +/** + * + * @param {number} seconds + * @returns {string} + */ function elapsedPretty(seconds) { if (seconds > 0 && seconds < 1) { return `${Math.floor(seconds * 1000)} ms` @@ -73,16 +78,27 @@ function elapsedPretty(seconds) { if (seconds < 60) { return `${Math.floor(seconds)} sec` } - var minutes = Math.floor(seconds / 60) + let minutes = Math.floor(seconds / 60) if (minutes < 70) { return `${minutes} min` } - var hours = Math.floor(minutes / 60) + let hours = Math.floor(minutes / 60) minutes -= hours * 60 - if (!minutes) { - return `${hours} hr` + + let days = Math.floor(hours / 24) + hours -= days * 24 + + const timeParts = [] + if (days) { + timeParts.push(`${days} d`) + } + if (hours || (days && minutes)) { + timeParts.push(`${hours} hr`) + } + if (minutes) { + timeParts.push(`${minutes} min`) } - return `${hours} hr ${minutes} min` + return timeParts.join(' ') } module.exports.elapsedPretty = elapsedPretty diff --git a/server/utils/longTimeout.js b/server/utils/longTimeout.js new file mode 100644 index 0000000000..6ea05a657c --- /dev/null +++ b/server/utils/longTimeout.js @@ -0,0 +1,36 @@ +/** + * Handle timeouts greater than 32-bit signed integer + */ +class LongTimeout { + constructor() { + this.timeout = 0 + this.timer = null + } + + clear() { + clearTimeout(this.timer) + } + + /** + * + * @param {Function} fn + * @param {number} timeout + */ + set(fn, timeout) { + const maxValue = 2147483647 + + const handleTimeout = () => { + if (this.timeout > 0) { + let delay = Math.min(this.timeout, maxValue) + this.timeout = this.timeout - delay + this.timer = setTimeout(handleTimeout, delay) + return + } + fn() + } + + this.timeout = timeout + handleTimeout() + } +} +module.exports = LongTimeout