From 3533bd2722f5e739d44d9f897ce668f81ab23987 Mon Sep 17 00:00:00 2001 From: mervyn Date: Fri, 24 Jun 2022 10:42:30 +0800 Subject: [PATCH 1/3] #30 add adr doc --- docs/adr/0003-how-to-remove-killed-process.md | 22 +++++++++++++++++++ docs/adr/README.md | 1 + 2 files changed, 23 insertions(+) create mode 100644 docs/adr/0003-how-to-remove-killed-process.md diff --git a/docs/adr/0003-how-to-remove-killed-process.md b/docs/adr/0003-how-to-remove-killed-process.md new file mode 100644 index 0000000..1ba7490 --- /dev/null +++ b/docs/adr/0003-how-to-remove-killed-process.md @@ -0,0 +1,22 @@ +# 3. how to remove killed process + +Date: 2022-06-24 + +## Status + +2022-06-24 proposed + +## Context + +[0002-auto-remove-process](./0002-auto-remove-process-id-menu-item-when-it-does-not-meet-the-threshold.md) + +The process cannot be removed when the status changes from draining to killed. + +## Decision + +Adding a timer to the `monitor` class for checking the time interval and when the cached draining process is long time not updated during slibing window size, +it would send a `remove` signal to the main process. + +## Consequences + +Consequences here... diff --git a/docs/adr/README.md b/docs/adr/README.md index 5d2f81a..4af0dd8 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -2,3 +2,4 @@ * [1. package-tool](0001-package-tool.md) * [2. auto-remove-process-id-menu-item-when-it-does-not-meet-the-threshold](0002-auto-remove-process-id-menu-item-when-it-does-not-meet-the-threshold.md) +* [3. how-to-remove-killed-process](0003-how-to-remove-killed-process.md) From 7f564d70f1eaf3df1805e3ee15622c24ffa9939f Mon Sep 17 00:00:00 2001 From: mervyn Date: Fri, 24 Jun 2022 10:43:25 +0800 Subject: [PATCH 2/3] #30 auto remove killed process --- main.js | 4 ++-- monitor.js | 48 ++++++++++++++++++++++++++++++++++++++------ test/monitor.test.js | 33 +++++++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 9 deletions(-) diff --git a/main.js b/main.js index f57abf1..9f1998f 100644 --- a/main.js +++ b/main.js @@ -36,8 +36,8 @@ changedActions[CHANGED_TYPES.ADD] = ({ pid, stat }) => { menuTray.setContextMenu(Menu.buildFromTemplate(cachedMenus)) } -changedActions[CHANGED_TYPES.REMOVE] = ({ pid, stat }) => { - logger.warn(`command: ${stat.command} pid: ${pid} becomes normal`) +changedActions[CHANGED_TYPES.REMOVE] = ({ pid }) => { + logger.warn(`pid: ${pid} becomes normal`) const statusItem = cachedMenus.find(item => item.id === STATUS_ID) cachedMenus = cachedMenus.filter(item => item.id !== pid) const hasPid = cachedMenus.some(item => item.isPid) diff --git a/monitor.js b/monitor.js index cf4e593..12d51a2 100644 --- a/monitor.js +++ b/monitor.js @@ -16,7 +16,8 @@ class Monitor { this.intervalMs = intervalMs this.running = false this.changedCallback = changedCallback - this.cachedPid = new Map() + this.overThresholdPidCache = new Map() + this.windowSize = windowSize this.stats = new Statistics({ windowSize, slidingCallback: ({ pid, stat }) => { @@ -25,20 +26,30 @@ class Monitor { const ret = { pid, stat, type: null } if (median < DEFAULT_THRESHOLD) { - if (!this.cachedPid.has(pid)) return + if (!this.overThresholdPidCache.has(pid)) return ret.type = CHANGED_TYPES.REMOVE - this.cachedPid.delete(pid) + this.overThresholdPidCache.delete(pid) } else { - if (this.cachedPid.has(pid)) return + if (this.overThresholdPidCache.has(pid)) { + this.overThresholdPidCache.set(pid, Date.now()) + return + } ret.type = CHANGED_TYPES.ADD - this.cachedPid.set(pid) + this.overThresholdPidCache.set(pid, Date.now()) } this.changedCallback(ret) } }) + this.checkTimer = new CheckTimer({ + intervalMs: this.windowSize * this.intervalMs, + cache: this.overThresholdPidCache, + cb: ({ pid }) => { + this.changedCallback({ pid, type: CHANGED_TYPES.REMOVE }) + } + }) } start () { @@ -60,10 +71,12 @@ class Monitor { } interval(this.intervalMs) + this.checkTimer.start() } async stop () { this.running = false + this.checkTimer.stop() } isRunning () { @@ -108,4 +121,27 @@ class Statistics { } } -module.exports = { Monitor, Statistics, CHANGED_TYPES } +class CheckTimer { + constructor ({ intervalMs, cache, cb }) { + this.intervalMs = intervalMs + this.cache = cache + this.cb = cb + } + + start () { + this.interval = setInterval(() => { + this.cache.forEach((v, k) => { + if (Date.now() - v < this.intervalMs) return + + this.cache.delete(k) + this.cb({ pid: k }) + }) + }, this.intervalMs) + } + + stop () { + clearInterval(this.interval) + } +} + +module.exports = { Monitor, Statistics, CheckTimer, CHANGED_TYPES } diff --git a/test/monitor.test.js b/test/monitor.test.js index ffdb5c8..53acc6d 100644 --- a/test/monitor.test.js +++ b/test/monitor.test.js @@ -5,7 +5,7 @@ const proxyquire = require('proxyquire') const cpus = [110, 120, 130, 50, 112, 130, 0, 0, 10] let i = 0 -const { Monitor, Statistics, CHANGED_TYPES } = proxyquire('../monitor', { +const { Monitor, Statistics, CheckTimer, CHANGED_TYPES } = proxyquire('../monitor', { pidtree: async () => [1], '@reply2future/pidusage': async () => ({ 1: { cpu: cpus[i++ % cpus.length], ppid: 1 } }) }) @@ -84,4 +84,35 @@ describe('monitor module', () => { s.addPidStat(1, { ...mockStat }) }) }) + + describe('checktimer', () => { + let clock + beforeEach(() => { + clock = sinon.useFakeTimers() + }) + afterEach(() => { + clock.restore() + }) + it('should invoke callback when time interval is bigger than settings', async () => { + const intervalMs = 3000 + const cache = new Map([ + ['expired', Date.now()], + ['not expired', Date.now() + intervalMs * 3] + ]) + let cbCount = 0 + const s = new CheckTimer({ + intervalMs, + cache, + cb: ({ pid }) => { + pid.should.equal('expired') + cbCount++ + } + }) + + s.start() + await clock.tickAsync(4000) + cbCount.should.equal(1) + s.stop() + }) + }) }) From e46cc544d209a322f8fad1e8b0cb6b5b62674336 Mon Sep 17 00:00:00 2001 From: mervyn Date: Fri, 24 Jun 2022 10:44:05 +0800 Subject: [PATCH 3/3] #30 update the status of adr doc --- docs/adr/0003-how-to-remove-killed-process.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/adr/0003-how-to-remove-killed-process.md b/docs/adr/0003-how-to-remove-killed-process.md index 1ba7490..ca6a3f9 100644 --- a/docs/adr/0003-how-to-remove-killed-process.md +++ b/docs/adr/0003-how-to-remove-killed-process.md @@ -6,6 +6,8 @@ Date: 2022-06-24 2022-06-24 proposed +2022-06-24 done + ## Context [0002-auto-remove-process](./0002-auto-remove-process-id-menu-item-when-it-does-not-meet-the-threshold.md)