This is kind of diametrically opposed to the API that @1hko is interested in
I think this generalization is an improvement! I’m suggesting rename of retryHelp
to onError
as I think it makes the complete module read nicer. Hmm
Given your two implementations above:
retry : Config -> Task x a -> Task x a
onError : Config -> Task x a -> x -> Task x a
We can rewrite Retry.sendWith
sendWith : Config -> (Result Http.Error a -> msg) -> Http.Request a -> Cmd msg
sendWith config resultToMessage req =
let
task =
Http.toTask req
in
task
|> Task.onError (onError config task)
|> Task.attempt resultToMessage
Now we have a more generic Retry
module that can retry tasks. And in a more specialized case, it can retry Http requests. We can expose
the generic too
Revision 3
@ericgj simplifies the retry
abstraction and builds a more generic api, making the entire module more useful.
-- module Retry
default : Config
retry : Task x a -> Task x a
retryWith : Config -> Task x a -> Task x a
send : (Result Http.Error a -> msg) -> Http.Request a -> Cmd msg
sendWith : Config -> (Result Http.Error a -> msg) -> Http.Request a -> Cmd msg
Implementation
-- revision 3
module Retry exposing (Config, default, retry, retryWith, send, sendWith)
import Http
import Process
import Task exposing (Task)
import Time exposing (Time)
type alias Config =
{ retries : Int
, interval : Time
}
default : Config
default =
{ retries = 5
, interval = 1 * Time.second
}
retry : Task x a -> Task x a
retry =
retryWith default
retryWith : Config -> Task x a -> Task x a
retryWith config task =
task |> Task.onError (onError config task)
send : (Result Http.Error a -> msg) -> Http.Request a -> Cmd msg
send =
sendWith default
sendWith : Config -> (Result Http.Error a -> msg) -> Http.Request a -> Cmd msg
sendWith config resultToMessage req =
let
task =
Http.toTask req
in
task
|> Task.onError (onError config task)
|> Task.attempt resultToMessage
onError : Config -> Task x a -> x -> Task x a
onError config task error =
if config.retries == 0 then
let
_ =
Debug.log "failed retrying" error
in
Task.fail error
else
let
_ =
Debug.log ("retrying " ++ (toString config.retries)) error
next =
task
|> Task.onError (onError { config | retries = config.retries - 1 } task)
in
Process.sleep config.interval
|> Task.andThen (always next)
Probably time to learn how to publish packages…