Library for handling internal memory state (concurrently, etc.).
Add following into paket.references
Alma.State
module Example =
open Alma.State.ConcurrentStorage
let doSomething () =
//
// init state storage
//
let storage = create<string, string>()
let set = setState storage
let get = getState storage
let concatStateValue _key oldValue newValue = oldValue + newValue
let upsert = addOrUpdateState storage concatStateValue
//
// working with state
//
let keyJohn = Key "John"
let keyPeter = Key "Peter"
let keyMary = Key "Mary"
set keyJohn "Snow"
set keyPeter "Snow"
keyJohn
|> get
|> Option.map (printfn "State for John is %s")
|> ignore // Option.map returns `union option` which must be ignored explicitly
// prints: "State for John is Snow"
keyPeter
|> get
|> Option.map (printfn "State for Peter is %s")
|> ignore
// prints: "State for Peter is Parker"
keyMary
|> get
|> Option.map (printfn "State for Mary is %s")
|> ignore
// wont print anything
// Change/update
upsert keyMary "Jane Watson"
upsert keyPeter " (Spider-Man)"
set keyJohn "Knows nothing"
keyMary
|> get
|> Option.map (printfn "State for Mary is %s")
|> ignore
// prints: "State for Mary is Jane Watson"
keyPeter
|> get
|> Option.map (printfn "State for Peter is %s")
|> ignore
// prints: "State for Peter is Parker (Spider-Man)"
keyJohn
|> get
|> Option.map (printfn "State for John is %s")
|> ignore
// prints: "State for John is Knows nothing"let private searchFreshData api = asyncResult {
return! api |> executeSearch
}
let loadData api =
TemporaryCache.Millisecond.ofMinutes 5
|> TemporaryCache.debounceLoad "api.data" (fun () -> searchFreshData api)
let example () =
asyncResult {
let api = "..."
let! data = loadData api // fresh data loaded and cached for 5 minutes
let! data = loadData api // data loaded from cache and cache is debounce for another 5 minutes
do! Async.Sleep(4 * 60 * 1000) // wait for 4 minutes
let! data = loadData api // data loaded from cache and cache is debounce for another 5 minutes
do! Async.Sleep(4 * 60 * 1000) // wait for 4 minutes
let! data = loadData api // data loaded from cache and cache is debounce for another 5 minutes
return data // data old for 8 minutes now
}let private searchFreshData api = asyncResult {
return! api |> executeSearch
}
let loadData api =
TemporaryCache.Millisecond.ofMinutes 5
|> TemporaryCache.load "api.data" (fun () -> searchFreshData api)
let example () =
asyncResult {
let api = "..."
let! data = loadData api // fresh data loaded and cached for 5 minutes
let! data = loadData api // data loaded from cache
do! Async.Sleep(4 * 60 * 1000) // wait for 4 minutes
let! data = loadData api // data loaded from cache
do! Async.Sleep(4 * 60 * 1000) // wait for 4 minutes
let! data = loadData api // fresh data loaded and cached for 5 minutes
return data // data old for just a few milliseconds
}let getOAuthToken () = asyncResult {
return {|
Token = "token"
Expires = 84000
|}
}
let loadToken () =
TemporaryCache.loadWithTTL "oauth.token" (fun () -> asyncResult {
let! tokenInfo = getOAuthToken()
return {
Data = tokenInfo.Token
CacheFor = System.TimeSpan.FromSeconds(float tokenInfo.Expires)
}
})
let example () =
asyncResult {
// first call loads fresh token and caches it for tokenInfo.Expires seconds
let! token1 = loadToken ()
printfn "Got token: %s" token1
// subsequent call (within TTL) returns cached token
let! token2 = loadToken ()
printfn "Got token again: %s" token2
return token2
}- Increment version in
State.fsproj - Update
CHANGELOG.md - Commit new version and tag it
./build.sh build./build.sh -t tests