packages feed

cached-io 1.3.1.0 → 1.3.2.0

raw patch · 3 files changed

+55/−8 lines, 3 filesnew-uploaderPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Control.Concurrent.CachedIO: Config :: (UTCTime -> Timestamped a -> Bool) -> (Maybe (Timestamped a) -> m a) -> Config (m :: Type -> Type) a
+ Control.Concurrent.CachedIO: [isFresh] :: Config (m :: Type -> Type) a -> UTCTime -> Timestamped a -> Bool
+ Control.Concurrent.CachedIO: [refreshAction] :: Config (m :: Type -> Type) a -> Maybe (Timestamped a) -> m a
+ Control.Concurrent.CachedIO: cachedIOFromConfig :: forall m (t :: Type -> Type) a. (MonadIO m, MonadIO t, MonadCatch t) => Config t a -> m (Cached t a)
+ Control.Concurrent.CachedIO: cachedSTMFromConfig :: forall (m :: Type -> Type) a. (MonadIO m, MonadCatch m) => Config m a -> STM (Cached m a)
+ Control.Concurrent.CachedIO: data Config (m :: Type -> Type) a
+ Control.Concurrent.CachedIO: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Concurrent.CachedIO.Cached m)
+ Control.Concurrent.CachedIO: type Timestamped a = (UTCTime, a)

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for cached-io +## 1.3.2.0++- Add `Functor` instance for `Cached`.+ ## 1.3.1.0  - Add `cachedSTM` versions of all bindings.
cached-io.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.2 name:            cached-io-version:         1.3.1.0+version:         1.3.2.0 synopsis:        A simple library to cache IO actions description:   Provides functions that convert an IO action into a cached one by storing the
src/Control/Concurrent/CachedIO.hs view
@@ -1,3 +1,6 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DerivingStrategies #-}+ -- | Example usage: -- -- > -- Downloads a large payload from an external data store.@@ -16,12 +19,15 @@ --   it. In that case, the stored value will be returned in the meantime. module Control.Concurrent.CachedIO   ( Cached (..),+    Config (..),+    Timestamped,      -- * IO     cachedIO,     cachedIOWith,     cachedIO',     cachedIOWith',+    cachedIOFromConfig,      -- * STM     -- $stm@@ -29,6 +35,7 @@     cachedSTMWith,     cachedSTM',     cachedSTMWith',+    cachedSTMFromConfig,   ) where @@ -49,9 +56,22 @@ -- -- Note that using 'Control.Monad.join' when the cached action and the outer monad are the same will ignore caching. newtype Cached m a = Cached {runCached :: m a}+  deriving stock (Functor)  data State a = Uninitialized | Initializing | Updating a | Fresh UTCTime a +-- | A cached value and when it was cached.+type Timestamped a = (UTCTime, a)++data Config m a = Config+  { -- | @isFresh now (timestamp, value)@ should return 'False' if @value@ is+    -- considered to have expired, 'True' otherwise.+    isFresh :: UTCTime -> Timestamped a -> Bool,+    -- | Produces a new value. The currently-cached value is supplied if it is+    -- available.+    refreshAction :: Maybe (Timestamped a) -> m a+  }+ -- | Cache an IO action, producing a version of this IO action that is cached -- for 'interval' seconds. The cache begins uninitialized. --@@ -105,16 +125,27 @@ cachedIOWith' ::   (MonadIO m, MonadIO t, MonadCatch t) =>   -- | Test function:-  -- If 'isCacheStillFresh' 'lastUpdated' 'now' returns 'True'+  -- If @isCacheStillFresh lastUpdated now@ returns 'True'   -- the cache is considered still fresh and returns the cached IO action   (UTCTime -> UTCTime -> Bool) ->   -- | Action to cache. The stale value and its refresh date   -- are passed so that the action can perform external staleness checks   (Maybe (UTCTime, a) -> t a) ->   m (Cached t a)-cachedIOWith' isCacheStillFresh refreshAction =-  liftIO . atomically $ cachedSTMWith' isCacheStillFresh refreshAction+cachedIOWith' isFresh' refreshAction' =+  cachedIOFromConfig+    Config+      { isFresh = \now (lastUpdated, _) -> isFresh' lastUpdated now,+        refreshAction = refreshAction'+      } +-- | Cache an IO action; the cache begins uninitialized.+--+-- The outer IO is responsible for setting up the cache. Use the inner one to+-- either get the cached value or refresh+cachedIOFromConfig :: (MonadIO m, MonadIO t, MonadCatch t) => Config t a -> m (Cached t a)+cachedIOFromConfig = liftIO . atomically . cachedSTMFromConfig+ -- $stm -- -- The following actions are the exactly same as the 'cachedIO' versions, except@@ -159,14 +190,26 @@ cachedSTMWith' ::   (MonadIO m, MonadCatch m) =>   -- | Test function:-  -- If @'isCacheStillFresh' lastUpdated now@ returns 'True'+  -- If @isCacheStillFresh lastUpdated now@ returns 'True'   -- the cache is considered still fresh and returns the cached IO action   (UTCTime -> UTCTime -> Bool) ->   -- | Action to cache. The stale value and its refresh date   -- are passed so that the action can perform external staleness checks   (Maybe (UTCTime, a) -> m a) ->   STM (Cached m a)-cachedSTMWith' isCacheStillFresh refreshAction = do+cachedSTMWith' isFresh' refreshAction' =+  cachedSTMFromConfig+    Config+      { isFresh = \now (lastUpdated, _) -> isFresh' lastUpdated now,+        refreshAction = refreshAction'+      }++-- | Set up a cached IO action in a transaction; the cache begins uninitialized.+cachedSTMFromConfig ::+  (MonadIO m, MonadCatch m) =>+  Config m a ->+  STM (Cached m a)+cachedSTMFromConfig config = do   cachedT <- newTVar Uninitialized   pure . Cached $ do     now <- liftIO getCurrentTime@@ -175,7 +218,7 @@       case cached of         previousState@(Fresh lastUpdated value)           -- There's data in the cache and it's recent. Just return.-          | isCacheStillFresh lastUpdated now -> pure (pure value)+          | isFresh config now (lastUpdated, value) -> pure (pure value)           -- There's data in the cache, but it's stale. Update the cache state           -- to prevent a second thread from also executing the action. The second           -- thread will get the stale data instead.@@ -198,7 +241,7 @@             Fresh lastUpdated value -> Just (lastUpdated, value)             _ -> Nothing       newValue <--        refreshAction previous+        refreshAction config previous           `onException` liftIO (atomically (writeTVar cachedT previousState))       liftIO $ do         now <- getCurrentTime