billstclair/elm-dynamodb/2.4.0

NOTE: the latest version is 2.5.0

DynamoDB.AppState

Support for storing application state in DynamoDB.

Call initialLoad when your application starts, to get the saveCount and keyCounts from DynamoDB, and compare them to local versions, usually saved in LocalStorage.

Specify key/value pairs to save by calling save.

Once a second, call idle to make sure unstored changes get pushed to DynamoDB, at idlePeriod intervals.

Call update to pull changes from DynamoDB, at updatePeriod intervals.

Call isActive at updateActive intervals to make your app stop calling update, until the user does something to make it necessary.

Call goActive when the user does something that requires pulling changes from other browsers.

State

type alias AppState =
{ account : Account
, idlePeriod : Int
, updatePeriod : Int
, activePeriod : Int
, keyName : String
, valueAttributeName : String
, saveCountAttributeName : String
, saveCountKey : String
, keyCountsKey : String
, keyPrefix : Maybe String
, lastIdleTime : Int
, lastUpdateTime : Int
, saveCount : Int
, lastActiveTime : Int
, updates : Dict String (Maybe Value)
, keyCounts : Dict String Int
}

Track updates for DynamoDB persistence.

makeAppState : Account -> AppState

Make an AppState with good defaults.

Updating state

type alias Error =
{ appState : AppState
, error : Error
}

The Error in the result from executing the task returned by save and idle.

accountIncomplete : AppState -> Bool

Return True if an Account does not have all its field filled in.

Do NOT call save, idle, or update if this returns True. You'll get an error on attempting to connect to the DynamoDB server.

Int
-> String
-> Maybe Value
-> AppState
-> Maybe ( AppState, Task Error Int )

Add a new key/value pair to the DynamoDB store.

Don't actually push it to DynamoDB you've accumulated as many keys as can fit in one transaction. Call idle to force a push.

The task that saves to DynamoDB has as its value the number of keys that were saved. It does nothing and has a value of 0, if the save doesn't yet fill a transaction.

idle : Int -> AppState -> Maybe ( AppState, Task Error Int )

Push the saved changes to DynamoDB if the idle time has elapsed.

isIdleTime : Int -> AppState -> Bool

Is it time to query the database for updates from other apps?

Getting updates from other browsers.

type alias Updates =
{ saveCount : Int
, keyCounts : Dict String Int
, updates : Dict String (Maybe String)
}

The successful Result of update and initialLoad.

update : Int -> AppState -> Maybe ( AppState, Task Error (Maybe Updates) )

Probe the database for updates from other browsers.

Returns Nothing if it's not yet time for the update.

The Task's value will be Nothing if your state is up-to-date with the database. Otherwise, you'll need to update your copy of the AppState with the returned updates.saveCount & updates.keyCounts, and process the updates.updates, likely running appropriate JSON decoders on the values (which will be Nothing if the key was deleted in the database).

initialLoad : AppState -> Int -> Dict String Int -> Task Error (Maybe Updates)

Load the saveCount and keyCounts from DynamoDB.

Also load any key/value pairs that are more recent in the database than they are in the passed keyCounts:

initialLoad appState saveCount keyCounts

Stop calling update periodically.

isActive : Int -> AppState -> Bool

Check for activity. Return True if active.

goActive : Int -> AppState -> AppState

Go active, usually due to UI action that requires update from afar.

User Interface

renderAccount : (Account -> msg) -> Account -> Html msg

A UI for entering account information.

You can certainly do this yourself, if you want it to look different, but this gives you a good start.

The callback is called when a field changes.

You need to do OK and Cancel buttons yourself.

Internals

store : Int -> AppState -> Maybe ( AppState, Task Error Int )

Push all saved updates to DynamoDB.

mergeAccount : Account -> AppState -> AppState

Merge information from Account into AppState.