refresht: Environment Monad with automatic resource refreshment

[ bsd3, library, web ] [ Propose Tags ]

Please see README.md


[Skip to Readme]

Modules

[Index]

Downloads

Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.1.0.1, 0.1.1.0
Dependencies base (>=4.9.0.0 && <4.10), data-default (>=0.7.1.1 && <0.8), exceptions (>=0.8.3 && <0.9), lens (>=4.14 && <5), mtl (>=2.2.1 && <2.3), refresht (>=0.1.1.0 && <0.2) [details]
License BSD-3-Clause
Copyright 2015 (c) Hiromi ISHII
Author Hiromi ISHII
Maintainer konn.jinro _at_ gmail.com
Revised Revision 2 made by HiromiIshii at 2018-02-22T08:23:02Z
Category Web
Home page https://github.com/konn/refresht#readme
Source repo head: git clone https://github.com/konn/refresht
Uploaded by HiromiIshii at 2017-01-17T09:22:38Z
Distributions
Reverse Dependencies 1 direct, 0 indirect [details]
Executables example
Downloads 2213 total (9 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2017-01-17 [all 1 reports]

Readme for refresht-0.1.1.0

[back to package description]

RefreshT -- Environment Monad with automatic resource refreshment

Overview

refresht package provides similar interface as ReaderT-monad, but it comes with automatic refreshment mechanism. In other words, the RefreshT monad transformer provides the general way to maintain the freshness of the external environment, with respoec to the specified condition or exceptions.

The typical usage is to communicate with the server which requires periodic refreshment of access tokens, such as Google API.

Usage

The following pseudo-code illustrates the typical usage:

import Control.Monad.Refresh

import Network.Wreq               (getWith, defaults)
import Control.Lens               ((&), (.~), (^.))
import Data.Time                  (addUTCTime, getCurrentTime, UTCTime)
import Data.ByetString.Lazy.Char8 (unpack)
import Control.Exception          (fromException)

data User = User { expiration  :: UTCTime
                 , accessToken :: String
                 }

main :: IO ()
main = do
  time <- getCurrentTime
  evalRefreshT conf (User (3600 `addUTCTime` time) "initialtoken") $ do
    rsc <- withEnv $ \User{..} ->
      getWith (defaults & auth .~ oauth2Bearer accessToken)
              "https://example.com/api/resource"
    putStrLn $ print rsc

conf :: RefreshSetting User IO
conf = defaultRefreshSetting
     & refresher         .~ update
     & shouldRefresh     .~ checkExpr
     & isRefreshingError .~ isRefreshing
  where
    shouldRefresh usr = do -- checks expiration
      now <- getCurrentTime
      return $ now <= expiration usr
          
    update usr = do
      -- Refreshed token for the service
      bdy <- getWith
        (defaults & param "token" .~ [accessToken usr])
        "https://example.com/api/refresh_token"
      let token = unpack $ bdy ^. responseBody
          usr'  = usr { accessToken = token
                      , expiration = ...
                      }

      -- Save updates in local file, or db.
      writeFile "database" (show usr')
      return usr'

    -- 401 Unauthorized exception should cause refreshment
    isRefreshing e =
      case fromException e of
        Just Error401 -> True
        _ -> False