Comparing version 1.0.89 to 1.0.90
# CHANGELOG | ||
- 1.0.90 - 2022-04-04 | ||
- Added new configuration option `maxIdleTime` | ||
- 1.0.89 - 2022-04-04 | ||
@@ -4,0 +8,0 @@ |
@@ -5,110 +5,137 @@ 'use strict'; | ||
// Listes for changes in mailbox | ||
module.exports = async connection => { | ||
if (connection.state !== connection.states.SELECTED) { | ||
// nothing to do here | ||
return; | ||
} | ||
async function runIdle(connection) { | ||
let response; | ||
if (connection.capabilities.has('IDLE')) { | ||
let response; | ||
let preCheckWaitQueue = []; | ||
try { | ||
connection.idling = true; | ||
let preCheckWaitQueue = []; | ||
try { | ||
connection.idling = true; | ||
//let idleSent = false; | ||
let doneRequested = false; | ||
let doneSent = false; | ||
let canEnd = false; | ||
//let idleSent = false; | ||
let doneRequested = false; | ||
let doneSent = false; | ||
let canEnd = false; | ||
let preCheck = () => { | ||
doneRequested = true; | ||
if (canEnd && !doneSent) { | ||
connection.log.debug({ | ||
src: 'c', | ||
msg: `DONE`, | ||
comment: `breaking IDLE`, | ||
lockId: connection.currentLockId, | ||
path: connection.mailbox && connection.mailbox.path | ||
}); | ||
connection.write('DONE'); | ||
doneSent = true; | ||
let preCheck = () => { | ||
doneRequested = true; | ||
if (canEnd && !doneSent) { | ||
connection.log.debug({ | ||
src: 'c', | ||
msg: `DONE`, | ||
comment: `breaking IDLE`, | ||
lockId: connection.currentLockId, | ||
path: connection.mailbox && connection.mailbox.path | ||
}); | ||
connection.write('DONE'); | ||
doneSent = true; | ||
connection.idling = false; | ||
connection.preCheck = false; // unset itself | ||
connection.idling = false; | ||
connection.preCheck = false; // unset itself | ||
while (preCheckWaitQueue.length) { | ||
let { resolve } = preCheckWaitQueue.shift(); | ||
resolve(); | ||
} | ||
while (preCheckWaitQueue.length) { | ||
let { resolve } = preCheckWaitQueue.shift(); | ||
resolve(); | ||
} | ||
}; | ||
} | ||
}; | ||
connection.preCheck = () => { | ||
let handler = new Promise((resolve, reject) => { | ||
preCheckWaitQueue.push({ resolve, reject }); | ||
}); | ||
connection.preCheck = () => { | ||
let handler = new Promise((resolve, reject) => { | ||
preCheckWaitQueue.push({ resolve, reject }); | ||
}); | ||
connection.log.trace({ | ||
msg: 'Requesting IDLE break', | ||
lockId: connection.currentLockId, | ||
path: connection.mailbox && connection.mailbox.path, | ||
queued: preCheckWaitQueue.length, | ||
doneRequested, | ||
canEnd, | ||
doneSent | ||
}); | ||
connection.log.trace({ | ||
msg: 'Requesting IDLE break', | ||
lockId: connection.currentLockId, | ||
path: connection.mailbox && connection.mailbox.path, | ||
queued: preCheckWaitQueue.length, | ||
doneRequested, | ||
canEnd, | ||
doneSent | ||
}); | ||
preCheck(); | ||
preCheck(); | ||
return handler; | ||
}; | ||
return handler; | ||
}; | ||
response = await connection.exec('IDLE', false, { | ||
onPlusTag: async () => { | ||
connection.log.debug({ msg: `Initiated IDLE, waiting for server input`, doneRequested }); | ||
canEnd = true; | ||
if (doneRequested) { | ||
preCheck(); | ||
} | ||
}, | ||
onSend: () => { | ||
//idleSent = true; | ||
response = await connection.exec('IDLE', false, { | ||
onPlusTag: async () => { | ||
connection.log.debug({ msg: `Initiated IDLE, waiting for server input`, doneRequested }); | ||
canEnd = true; | ||
if (doneRequested) { | ||
preCheck(); | ||
} | ||
}); | ||
// unset before response.next() | ||
if (typeof connection.preCheck === 'function') { | ||
connection.log.trace({ | ||
msg: 'Clearing pre-check function', | ||
lockId: connection.currentLockId, | ||
path: connection.mailbox && connection.mailbox.path, | ||
queued: preCheckWaitQueue.length, | ||
doneRequested, | ||
canEnd, | ||
doneSent | ||
}); | ||
connection.preCheck = false; | ||
while (preCheckWaitQueue.length) { | ||
let { resolve } = preCheckWaitQueue.shift(); | ||
resolve(); | ||
} | ||
}, | ||
onSend: () => { | ||
//idleSent = true; | ||
} | ||
}); | ||
response.next(); | ||
return; | ||
} catch (err) { | ||
// unset before response.next() | ||
if (typeof connection.preCheck === 'function') { | ||
connection.log.trace({ | ||
msg: 'Clearing pre-check function', | ||
lockId: connection.currentLockId, | ||
path: connection.mailbox && connection.mailbox.path, | ||
queued: preCheckWaitQueue.length, | ||
doneRequested, | ||
canEnd, | ||
doneSent | ||
}); | ||
connection.preCheck = false; | ||
connection.idling = false; | ||
connection.log.warn({ err, cid: connection.id }); | ||
while (preCheckWaitQueue.length) { | ||
let { reject } = preCheckWaitQueue.shift(); | ||
reject(err); | ||
let { resolve } = preCheckWaitQueue.shift(); | ||
resolve(); | ||
} | ||
return false; | ||
} | ||
response.next(); | ||
return; | ||
} catch (err) { | ||
connection.preCheck = false; | ||
connection.idling = false; | ||
connection.log.warn({ err, cid: connection.id }); | ||
while (preCheckWaitQueue.length) { | ||
let { reject } = preCheckWaitQueue.shift(); | ||
reject(err); | ||
} | ||
return false; | ||
} | ||
} | ||
// Listes for changes in mailbox | ||
module.exports = async (connection, maxIdleTime) => { | ||
if (connection.state !== connection.states.SELECTED) { | ||
// nothing to do here | ||
return; | ||
} | ||
if (connection.capabilities.has('IDLE')) { | ||
let idleTimer; | ||
let stillIdling = false; | ||
let runIdleLoop = async () => { | ||
if (maxIdleTime) { | ||
idleTimer = setTimeout(() => { | ||
if (connection.idling) { | ||
if (typeof connection.preCheck === 'function') { | ||
stillIdling = true; | ||
// request IDLE break if IDLE has been running for allowed time | ||
connection.log.trace({ msg: 'Max allowed IDLE time reached', cid: connection.id }); | ||
connection.preCheck().catch(err => connection.log.warn({ err, cid: connection.id })); | ||
} | ||
} | ||
}, maxIdleTime); | ||
} | ||
let resp = await runIdle(connection); | ||
clearTimeout(idleTimer); | ||
if (stillIdling) { | ||
stillIdling = false; | ||
return runIdleLoop(); | ||
} | ||
return resp; | ||
}; | ||
return runIdleLoop(); | ||
} | ||
let idleTimer; | ||
@@ -131,2 +158,4 @@ | ||
let noopInterval = maxIdleTime ? Math.min(NOOP_INTERVAL, maxIdleTime) : NOOP_INTERVAL; | ||
let runLoop = () => { | ||
@@ -136,3 +165,3 @@ idleCheck() | ||
clearTimeout(idleTimer); | ||
idleTimer = setTimeout(runLoop, NOOP_INTERVAL); | ||
idleTimer = setTimeout(runLoop, noopInterval); | ||
}) | ||
@@ -139,0 +168,0 @@ .catch(err => { |
@@ -31,2 +31,3 @@ /// <reference types="node" /> | ||
* @param [options.qresync = false] - If true, then enables QRESYNC support. EXPUNGE notifications will include `uid` property instead of `seq` | ||
* @param [options.maxIdleTime] - If set, then breaks and restarts IDLE every maxIdleTime ms | ||
*/ | ||
@@ -58,2 +59,3 @@ class ImapFlow extends EventEmitter { | ||
qresync?: boolean; | ||
maxIdleTime?: number; | ||
}); | ||
@@ -60,0 +62,0 @@ /** |
{ | ||
"name": "imapflow", | ||
"version": "1.0.89", | ||
"version": "1.0.90", | ||
"description": "IMAP Client for Node", | ||
@@ -5,0 +5,0 @@ "main": "./lib/imap-flow.js", |
Sorry, the diff of this file is too big to display
508293
11444