packages feed

cached-io 1.2.0.0 → 1.3.0.0

raw patch · 4 files changed

+43/−17 lines, 4 filesdep ~basedep ~timenew-uploaderPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, time

API changes (from Hackage documentation)

+ Control.Concurrent.CachedIO: Cached :: m a -> Cached m a
+ Control.Concurrent.CachedIO: [runCached] :: Cached m a -> m a
+ Control.Concurrent.CachedIO: newtype Cached m a
- Control.Concurrent.CachedIO: cachedIO :: (MonadIO m, MonadIO t, MonadCatch t) => NominalDiffTime -> t a -> m (t a)
+ Control.Concurrent.CachedIO: cachedIO :: (MonadIO m, MonadIO t, MonadCatch t) => NominalDiffTime -> t a -> m (Cached t a)
- Control.Concurrent.CachedIO: cachedIO' :: (MonadIO m, MonadIO t, MonadCatch t) => NominalDiffTime -> (Maybe (UTCTime, a) -> t a) -> m (t a)
+ Control.Concurrent.CachedIO: cachedIO' :: (MonadIO m, MonadIO t, MonadCatch t) => NominalDiffTime -> (Maybe (UTCTime, a) -> t a) -> m (Cached t a)
- Control.Concurrent.CachedIO: cachedIOWith :: (MonadIO m, MonadIO t, MonadCatch t) => (UTCTime -> UTCTime -> Bool) -> t a -> m (t a)
+ Control.Concurrent.CachedIO: cachedIOWith :: (MonadIO m, MonadIO t, MonadCatch t) => (UTCTime -> UTCTime -> Bool) -> t a -> m (Cached t a)
- Control.Concurrent.CachedIO: cachedIOWith' :: (MonadIO m, MonadIO t, MonadCatch t) => (UTCTime -> UTCTime -> Bool) -> (Maybe (UTCTime, a) -> t a) -> m (t a)
+ Control.Concurrent.CachedIO: cachedIOWith' :: (MonadIO m, MonadIO t, MonadCatch t) => (UTCTime -> UTCTime -> Bool) -> (Maybe (UTCTime, a) -> t a) -> m (Cached t a)

Files

CHANGELOG.md view
@@ -1,5 +1,25 @@ # Revision history for cached-io +## 1.3.0.0++- **Breaking** Caching functions previously returned `m (t a)`, but it was easy to accidentally use `join` when `m` and `t` were the same monad (eg. `IO (IO a)`), and not get any caching at all. These functions now use a `Cached` newtype for `t a` to make it more difficult to misuse.++### Migrating from <=1.2.0.0 to 1.3.0.0++```haskell+-- Previous versions+f :: IO ()+f = do+  cachedAction <- cachedIO action :: IO (IO a)+  cachedResult <- cachedAction++-- New version+f :: IO ()+f = do+  cachedAction <- cachedIO action :: IO (Cached IO a)+  cachedResult <- runCached cachedAction+```+ ## 1.2.0.0  Thank you [glasserc](https://github.com/glasserc) for your work on previous versions, and a special thanks to
cached-io.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               cached-io-version:            1.2.0.0+version:            1.3.0.0 synopsis:           A simple library to cache IO actions description:   Provides functions that convert an IO action into a cached one by storing the@@ -12,8 +12,8 @@ maintainer:         Bellroy Tech Team <haskell@bellroy.com> category:           Development build-type:         Simple-tested-with:        GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.1-extra-source-files:+tested-with:        GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.4 || ==9.4.5 || ==9.6.2 || ==9.8.1+extra-doc-files:   CHANGELOG.md   README.md @@ -22,7 +22,7 @@   location: https://github.com/bellroy/haskell-cached-io.git  common deps-  build-depends: base >=4.13.0.0 && <4.18+  build-depends: base >=4.13.0.0 && <4.20  library   import:           deps@@ -30,7 +30,7 @@   build-depends:     , exceptions    >=0.10.4  && <0.11     , stm           >=2.5     && <2.6-    , time          >=1.9.3   && <1.13+    , time          >=1.9.3   && <1.15     , transformers  >=0.5.6.2 && <0.7    hs-source-dirs:   src/
src/Control/Concurrent/CachedIO.hs view
@@ -3,7 +3,7 @@ -- > -- Downloads a large payload from an external data store. -- > downloadData :: IO ByteString -- >--- > cachedDownloadData :: IO ByteString+-- > cachedDownloadData :: IO (Cached IO ByteString) -- > cachedDownloadData = cachedIO (secondsToNominalDiffTime 600) downloadData -- -- The first time @cachedDownloadData@ is called, it calls @downloadData@,@@ -14,6 +14,7 @@ -- result again. -- module Control.Concurrent.CachedIO (+    Cached(..),     cachedIO,     cachedIOWith,     cachedIO',@@ -26,6 +27,11 @@ import Control.Monad.IO.Class (liftIO, MonadIO) import Data.Time.Clock (NominalDiffTime, addUTCTime, getCurrentTime, UTCTime) +-- | A cached IO action in some monad @m@. Use 'runCached' to extract the action when you want to query it.+--+-- 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}+ data State a  = Uninitialized | Initializing | Updating a | Fresh UTCTime a  -- | Cache an IO action, producing a version of this IO action that is cached@@ -37,7 +43,7 @@ cachedIO :: (MonadIO m, MonadIO t, MonadCatch t)          => NominalDiffTime -- ^ Number of seconds before refreshing cache          -> t a             -- ^ IO action to cache-         -> m (t a)+         -> m (Cached t a) cachedIO interval = cachedIOWith (secondsPassed interval)  -- | Cache an IO action, producing a version of this IO action that is cached@@ -50,7 +56,7 @@           => NominalDiffTime -- ^ Number of seconds before refreshing cache           -> (Maybe (UTCTime, a) -> t a) -- ^ action to cache. The stale value and its refresh date           -- are passed so that the action can perform external staleness checks-          -> m (t a)+          -> m (Cached t a) cachedIO' interval = cachedIOWith' (secondsPassed interval)  -- | Check if @starting time@ + @seconds@ is after @end time@@@ -70,7 +76,7 @@     --   If 'isCacheStillFresh' 'lastUpdated' 'now' returns 'True'     --   the cache is considered still fresh and returns the cached IO action     -> t a -- ^ action to cache.-    -> m (t a)+    -> m (Cached t a) cachedIOWith f io = cachedIOWith' f (const io)  -- | Cache an IO action, The cache begins uninitialized.@@ -84,10 +90,10 @@     --   the cache is considered still fresh and returns the cached IO action     -> (Maybe (UTCTime, a) -> t a) -- ^ action to cache. The stale value and its refresh date     -- are passed so that the action can perform external staleness checks-    -> m (t a)+    -> m (Cached t a) cachedIOWith' isCacheStillFresh io = do   cachedT <- liftIO (atomically (newTVar Uninitialized))-  return $ do+  pure . Cached $ do     now <- liftIO getCurrentTime     join . liftIO . atomically $ do       cached <- readTVar cachedT@@ -100,12 +106,12 @@         -- thread will get the stale data instead.           | otherwise -> do             writeTVar cachedT (Updating value)-            return $ refreshCache previousState cachedT+            pure (refreshCache previousState cachedT)         -- Another thread is already updating the cache, just return the stale value-        Updating value -> return (return value)+        Updating value -> pure (pure value)         -- The cache is uninitialized. Mark the cache as initializing to block other         -- threads. Initialize and return.-        Uninitialized -> return $ refreshCache Uninitialized cachedT+        Uninitialized -> pure (refreshCache Uninitialized cachedT)         -- The cache is uninitialized and another thread is already attempting to         -- initialize it. Block.         Initializing -> retry
test/test-cachedIO.hs view
@@ -2,7 +2,7 @@     main     ) where -import Control.Concurrent.CachedIO (cachedIO)+import Control.Concurrent.CachedIO (cachedIO, Cached(..)) import Data.List (isInfixOf)  crawlTheInternet :: IO [String]@@ -13,9 +13,9 @@     return ["website about Haskell", "website about Ruby", "slashdot.org",             "The Monad.Reader", "haskellwiki"] -searchEngine :: String -> IO [String] -> IO [String]+searchEngine :: String -> Cached IO [String] -> IO [String] searchEngine query internet = do-    pages <- internet+    pages <- runCached internet     return $ filter (query `isInfixOf`) pages  main :: IO ()