mbr/elm-again/1.0.0

NOTE: the latest version is 1.0.1

Again.Remote

Keep track of a remote value and retry it when things go wrong.

Suppose your operation reports a Result through a message:

attempt : (Result String String -> msg) -> Cmd msg

You can track it in your model and schedule retries from update:

import Again.Policy as Policy
import Again.Remote as Remote
import Again.Schedule exposing (Schedule(..))
import Process
import Task


type alias Model =
    Remote.Remote String String


type Msg
    = Received (Result String String)
    | Retry


init : () -> ( Model, Cmd Msg )
init _ =
    ( Remote.init (Policy.unlimited (Periodic { delay = 1000 }))
    , attempt Received
    )


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Received (Ok value) ->
            ( Remote.succeed value model, Cmd.none )


        Received (Err error) ->
            let
                ( next, delay ) =
                    Remote.fail error model
            in
            ( next
            , case delay of
                Just milliseconds ->
                    Process.sleep milliseconds
                        |> Task.perform (always Retry)


                Nothing ->
                    Cmd.none
            )


        Retry ->
            ( Remote.beginRetry model, attempt Received )

A successful value can fail later. For example, a connection may close after it has opened.

type Remote error value

A remote value together with its retry policy and error classifier.

type State error value
= Attempting
| WaitingForRetry (RetryContext error)
| Retrying (RetryContext error)
| Successful value
| Failed error

See whether your value is available, still being attempted, or has failed.

type alias RetryContext error =
{ attempts : Int
, lastError : error
}

The number of completed attempts and the latest error in a retry sequence.

init : Policy -> Remote error value

Start tracking a value with its first attempt already under way. By default, all failures are retryable, subject to your policy.

withRetryable : (error -> Decision) -> Remote error value -> Remote error value

Choose which errors should be retried. Changing the classifier leaves your current value and retry progress alone.

state : Remote error value -> State error value

Look at the current state of your remote value.

stateToString : Remote error value -> String

Describe your remote value with a readable label, such as "waiting to retry (attempt 2/3)".

result : Remote error value -> Maybe (Result error value)

Get the successful value or the error that ended the retry sequence. You get Nothing while an attempt or retry is pending.

get : Remote error value -> Maybe value

Get the value if it is currently successful.

beginRetry : Remote error value -> Remote error value

Tell the Remote value that the wait time has elapsed. It will assume you are actually retrying afterwards.

This keeps your retry context, if any. Otherwise you start a fresh attempt, so any previous value or error is discarded.

succeed : value -> Remote error value -> Remote error value

Tell the Remote that an attempt succeeded. This keeps the value and clears its previous failures and attempt count.

fail : error -> Remote error value -> ( Remote error value, Maybe Float )

Tell the Remote that an attempt failed, or that a successful value was lost. The stored classifier and policy decide whether to retry.

You get a retry delay in milliseconds, or Nothing to give up. A failure after success discards the value and starts counting failures from one again.