calions-app / jsonapi-http-retry / Http.CmdRetry

Tries to perform a Task and retry it upon failure, allowing you to execute other Cmds between each failure.

The following example executes a request with a retry policy when the request fails and executes a port before each new retry:

type Msg
    = OnRetry (Http.CmdRetry.RetryContext Msg Entity)
    | OnEntityRetrieved (RemoteData.RemoteData Http.Error.RequestError Entity)

type alias Model =
    { entity : RemoteData.RemoteData Http.Error.RequestError Entity }

init : ( Model, Cmd Msg )
init =
    ( { entity = RemoteData.Loading }
    , getEntity
        |> Http.CmdRetry.with
            [ Http.Retry.maxDuration 7000
            , Http.Retry.exponentialBackoff { interval = 500, maxInterval = 3000 }
            ]
            [ Http.Retry.onUnauthenticatedStatus ]
            OnRetry
    )

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        OnRetry retryContext ->
            ( model
            , Http.CmdRetry.newAttempt
                executePort
                OnEntityRetrieved
                retryContext
            )

        OnEntityRetrieved entity ->
            ( { model | entity = entity }, Cmd.none )

getEntity : Task Never (RemoteData.RemoteData Http.Error.RequestError Entity)
getEntity =
    Request.request
        { url = "<http://endpoint">
        , headers = []
        , body = Json.Encode.object []
        , documentDecoder = JsonApi.Decode.resources "resource-type" entityDecoder
        }

Retry

with : List (Http.Internal.Policy Http.Error.RequestError) -> List Http.Internal.FailureCondition -> (RetryContext msg data -> msg) -> Task Basics.Never (RemoteData Http.Error.RequestError data) -> Platform.Cmd.Cmd msg

Tries to execute the given task. You will receive a message with the retry context. From there you will call newAttempt which will handle your request retry, allowing you to execute a Cmd before the next retry.

originalTask
    |> Http.CmdRetry.with
        [ Http.Retry.maxDuration 7000
        , Http.Retry.exponentialBackoff { interval = 500, maxInterval = 3000 }
        ]
        [ Http.Retry.onUnauthenticatedStatus ]
        OnRetry

newAttempt : (Http.Error.RequestError -> Platform.Cmd.Cmd msg) -> (RemoteData Http.Error.RequestError data -> msg) -> RetryContext msg data -> Platform.Cmd.Cmd msg

Attempt a new retry from your update function with the RetryContext you received. The first parameter allows you to execute a Cmd just before the next retry. The second parameter is the message you want to send when the request finally succeeded or failed (after all configured retries)

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        OnRetry retryContext ->
            ( model
            , Http.CmdRetry.newAttempt
                (\lastError ->
                    doSomethingWithLastError lastError
                )
                OnRequestDone
                retryContext
            )

Types


type RetryContext msg data

Type used by the module to keep the context of the retry process. You will never handle it directly

msg is your Msg type and data is the data you you to receive from your request.