node-imap icon indicating copy to clipboard operation
node-imap copied to clipboard

Child processes (fetchMsg, msg) do not throw any error when IMAP has error

Open Dsiddhesh opened this issue 5 years ago • 10 comments

We have been trying to handle a scenario in which we are fetching mail messages using IMAP. Whenever there is IMAP error, we retry by creating a new IMAP connection. Initially the IMAP is connected and the process has started. While the child process is on fetchMessage event, IMAP is been disconnected. Here, we were expecting an error to be thrown in the child process, but that doesn't happen. Instead the process is paused and when retry happens, we see that paused process is resumed which results in conflict with our retry.

Dsiddhesh avatar Sep 14 '20 10:09 Dsiddhesh

I'm not quite sure what kind of setup you have going on there, but on the imap connection object, you can listen for the 'error' event for errors and the 'close'/'end' event to know when the connection closes.

You can additionally set an explicit keepalive setting in your connection config object to change how dead connections are detected.

mscdex avatar Sep 14 '20 12:09 mscdex

@mscdex I tried simple code to fetch messages. I set keepalive as false in IMAP and now while code is fetching messages, I disconnected my network. I still that the process is waiting and when i connect network the fetch messages resumed. I want child process to abort/end when there is IMAP error.

Dsiddhesh avatar Sep 14 '20 13:09 Dsiddhesh

If you don't have any keepalive enabled, then a network disconnection won't be detected (as quickly as you expect) because of how TCP works and your OS's TCP connection settings. If keepalive is enabled, then the network disconnection will be detected and the appropriate error will be emitted.

mscdex avatar Sep 14 '20 14:09 mscdex

@mscdex to achieve my requirement is it ok to call 'destroy' on IMAP instance in 'error' event handler and recreate IMAP instance again once connection(network) issues are resolved ?

Dsiddhesh avatar Sep 14 '20 14:09 Dsiddhesh

It shouldn't hurt anything, but you shouldn't need to explicitly destroy since any 'error' event typically indicates a fatal (connection) error which should cause the closing of the underlying socket.

mscdex avatar Sep 14 '20 15:09 mscdex

Thanks, but currently even after getting error when we retry for connection, previously paused operations resumes and then there is race condition to return response that causes error 'Cant set header's after they are sent' . Let me try adding explicit destroy call and see if it works.

Dsiddhesh avatar Sep 14 '20 16:09 Dsiddhesh

@mscdex calling destroy explicitly is not working out. Does the library retries automatically when there is IMAP error and when keepalive is true? if yes then how many times does it retries ?

Dsiddhesh avatar Sep 15 '20 10:09 Dsiddhesh

It does not.

mscdex avatar Sep 15 '20 12:09 mscdex

@mscdex let me brief you what we are doing in our application

  1. We are fetching emails (with/without filter) and now we have batch flows kept running as part of testing
  2. In our application we have rule to retry for 5 time when there is error like ETIMEDOUT, ECONRESET etc and when connection retry is success we execute the main business logic again i.e. process messages.
  3. When there is IMAP error while emails messages are getting fetched, control goes to IMAP error event and message processing is paused. In this IMAP error event method if we get error like ETIMEDOUT or ECONRESET , we again try to connect . This time when connection happens successfully previously paused message processing resumes and since we retry connection, the processing of messages starts again. This causes cant set header error as the response is sent 2 time to calling application. We don't want this to happen. When there is IMAP error, message processing should stop as we will be retrying the message processing again when IMAP gets connected in retry operation.

Dsiddhesh avatar Sep 15 '20 14:09 Dsiddhesh

My only guess is that there is some kind of bug in your code. If the socket disconnects, there is no way for imap to magically continue. Are you reusing the same connection object when reconnecting or creating a new connection object (new Imap(..)) on each try (this would be preferrable)?

mscdex avatar Sep 15 '20 15:09 mscdex