packages feed

snap-app 0.3.0 → 0.3.1

raw patch · 2 files changed

+96/−2 lines, 2 filesdep +directorydep +filepath

Dependencies added: directory, filepath

Files

snap-app.cabal view
@@ -1,5 +1,5 @@ name:                snap-app-version:             0.3.0+version:             0.3.1 synopsis:            Simple modules for writing apps with Snap, abstracted from hpaste. homepage:            Simple modules for writing apps with Snap, abstracted from hpaste. license:             BSD3@@ -14,6 +14,7 @@   ghc-options:       -O2   hs-source-dirs:    src   exposed-modules:   Snap.App, Snap.App.Types, Snap.App.Controller, Snap.App.Model, Snap.App.Migrate,+                     Snap.App.Cache,                      Data.Pagination, Text.Blaze.Extra, Text.Blaze.Pagination,                      Control.Monad.Env, Data.Monoid.Operator,                      Network.URI.Params@@ -30,4 +31,6 @@                      bytestring,                      MonadCatchIO-transformers,                      cgi,-                     data-default+                     data-default,+                     filepath,+                     directory
+ src/Snap/App/Cache.hs view
@@ -0,0 +1,91 @@+{-# OPTIONS -Wall -fno-warn-name-shadowing #-}++-- | Caching of Blaze HTML pages caching.++module Snap.App.Cache+  (cache+  ,cacheIf+  ,resetCache+  ,clearCache+  ,resetCacheModel+  ,viewCached+  ,Key(..)+  ,CacheDir(..))+  where++import           Control.Monad.Reader+import           Data.Text.Lazy           (Text)+import qualified Data.Text.Lazy.IO as T+import           Snap.App+import           System.Directory+import           System.FilePath+import           Text.Blaze+import           Text.Blaze.Renderer.Text++-- | A key for the cache.+class Key key where+  keyToString :: key -> FilePath++-- | A config that can return a cache directory.+class CacheDir config where+  getCacheDir :: config -> FilePath++-- | Cache conditionally.+cacheIf :: (CacheDir c,Key key) => Bool -> key -> Controller c s (Maybe Html) -> Controller c s (Maybe Text)+cacheIf pred key generate =+  if pred+     then cache key generate+     else fmap (fmap renderHtml) generate++-- | Generate and save into the cache, or retrieve existing from the+-- | cache.+cache :: (CacheDir c,Key key) => key -> Controller c s (Maybe Html) -> Controller c s (Maybe Text)+cache key generate = do+  tmpdir <- asks (getCacheDir . controllerStateConfig)+  let cachePath = tmpdir ++ "/" ++ keyToString key+  exists <- io $ doesFileExist cachePath+  if exists+     then do text <- io $ T.readFile cachePath+     	     return (Just text)+     else do text <- fmap (fmap renderHtml) generate+     	     case text of+	       Just text' -> do io $ createDirectoryIfMissing True tmpdir+                                io $ T.writeFile cachePath text'+	       	    	        return text+               Nothing -> return text++-- | Clear the whole cache.+clearCache :: CacheDir c => c -> IO ()+clearCache config = do+  files <- getDirectoryContents dir+  forM_ (filter (not . all (=='.')) files) $ removeFile . (dir </>)++  where dir = getCacheDir config++-- | Reset an item in the cache.+resetCache :: (CacheDir c,Key key) => key -> Controller c s ()+resetCache key = do+  tmpdir <- asks (getCacheDir . controllerStateConfig)+  io $ do+   let cachePath = tmpdir ++ "/" ++ keyToString key+   exists <- io $ doesFileExist cachePath+   when exists $ removeFile cachePath++-- | Reset an item in the cache.+resetCacheModel :: (CacheDir c,Key key) => key -> Model c s ()+resetCacheModel key = do+  tmpdir <- asks (getCacheDir . modelStateConfig)+  io $ do+   let cachePath = tmpdir ++ "/" ++ keyToString key+   exists <- io $ doesFileExist cachePath+   when exists $ removeFile cachePath++-- | Because.+io :: MonadIO m => IO a -> m a+io = liftIO++-- | View some HTML generator cached.+viewCached :: (CacheDir c,Key key) => key -> Controller c s Html -> Controller c s ()+viewCached key generate = do+  text <- cache key (fmap Just generate)+  maybe (return ()) outputText text