Saurabh Nanda
Saurabh Nanda

Reputation: 6793

How to catch and recover from temporary socket errors in Haskell?

I'm running a massive scrape job over HTTP APIs and have already used Control.Monad.Retry to allow my to retry the HTTP call if a temporary HTTP errors, such as, ConnectionTimeout, ProxyConnectException, ConnectionFailure).

However, if a socket-level error is raised due to a blip in the network, such as...

Network.Socket.recvBuf: resource vanished (Connection reset by peer)

...the entire process halts because there is no Handler in place for whatever this exception is.

I've tried looking at what kind of exceptions the socket library uses, and I think the function at play is throwSocketErrorCode, which internally uses Foreign.C.Error.errnoToIOError.

throwSocketErrorCode loc errno =
    ioError (errnoToIOError loc (Errno errno) Nothing Nothing)

So, it seems like an IOError (type synonym for IOException is being raised), which contains an error number inside it as well. I'm assuming that the error number will tell me something about the type of exception on the basis of which I will be able to decide whether to retry or abort. However, I couldn't find a way to get the errorNo out of an IOException.

So, how do I catch such network errors and decide whether to retry or abort?

Upvotes: 3

Views: 509

Answers (1)

kirelagin
kirelagin

Reputation: 13616

There is no “standard” way of doing this, because the IOException type is opaque in the standard. However, luckily, its constructor and fields are exported from GHC.IO.Exception, so you will be able to analyse its IOErrorType and errno nevertheless.

Upvotes: 1

Related Questions