cnd
cnd

Reputation: 33784

How to retry http request on timeout?

I often have got timeouts in my download method, I want to add some retries here:

withSocketsDo $ do
    irequest  ← liftIO $ parseUrl url
    fileExist ← doesFileExist fname
    when fileExist $ do
        putStrLn " -> Removing old version"
        removeFile fname
    withManager $ \manager → do
        let request = irequest
             { method = methodGet
             , responseTimeout = Just 10000000 }
        response ← http request manager
        responseBody response C.$$+- sinkFile fname

I've found method with ScopedTypeVariables

retryOnTimeout ∷ IO a → IO a
retryOnTimeout action = catch action $ \ (_ :: HttpException) → do
    putStrLn "Timed out. Trying again."
    threadDelay 5000000
    action

Adding try count is not big problem but seems like I can't just use something alike

response ← retryOnTimeout ( http request manager )

Because it cause strange type conflicts

Couldn't match type `IO'
              with `resourcet-1.1.3.3:Control.Monad.Trans.Resource.Internal.ResourceT
                      IO'
Expected type: resourcet-1.1.3.3:Control.Monad.Trans.Resource.Internal.ResourceT
                 IO
                 (Network.HTTP.Conduit.Response
                    (C.ResumableSource IO Data.ByteString.Internal.ByteString))
  Actual type: IO
                 (Network.HTTP.Conduit.Response
                    (C.ResumableSource IO Data.ByteString.Internal.ByteString))

How can I implement retry on Timeout for HTTP get method?

Upvotes: 1

Views: 666

Answers (1)

Michael Snoyman
Michael Snoyman

Reputation: 31345

The error message is telling you that your code expects a IO a, but in fact is being given a ResourceT IO a. The easiest thing to do is:

  • Change your type signature to match
  • Use catch from Control.Exception.Lifted (in the lifted-base package) instead of from Control.Exception

Upvotes: 1

Related Questions