diff --git a/src/Foundation.hs b/src/Foundation.hs index b74db1f..d9ca31b 100644 --- a/src/Foundation.hs +++ b/src/Foundation.hs @@ -22,6 +22,7 @@ import qualified Yesod.Core.Unsafe as Unsafe import Package import Entry.Kind ( EntryKind, allEntryKinds, pluralise ) +import Model.Cache ( getCached ) import Data.Aeson ( encode, object ) import qualified Text.Blaze.Internal as B @@ -177,7 +178,7 @@ instance YesodBreadcrumbs App where breadcrumb (AuthR _) = return ("log in", Just HomeR) breadcrumb (EntriesR kind) = return (pluralise kind, Just HomeR) breadcrumb (EntryR kind entryId) = do - entry <- runDB . get404 $ entryId + (Entity _ entry) <- getCached entryId return (entryName entry, Just $ EntriesR kind) breadcrumb (EntryWithSlugR kind entryId _) = breadcrumb $ EntryR kind entryId breadcrumb _ = return ("home", Nothing) diff --git a/src/Handler/Entries.hs b/src/Handler/Entries.hs index 49dba54..30820c2 100644 --- a/src/Handler/Entries.hs +++ b/src/Handler/Entries.hs @@ -9,6 +9,7 @@ import Yesod.AtomFeed ( atomLink ) import qualified Data.Text as T import qualified Entry.Kind as K +import Model.Cache ( getCached ) import Widget.Entry ( entryR, hEntry ) import Widget.Feed ( hFeed ) @@ -22,13 +23,13 @@ getEntriesR kind = do $(widgetFile "entries") getEntryR :: a -> EntryId -> Handler Html -getEntryR _ entryId = getEntry <=< fmap (Entity entryId) . runDB . get404 $ entryId +getEntryR _ = renderEntry <=< getCached getEntryWithSlugR :: a -> EntryId -> b -> Handler Html getEntryWithSlugR kind = const . getEntryR kind -getEntry :: (Entity Entry) -> Handler Html -getEntry entry = do +renderEntry :: (Entity Entry) -> Handler Html +renderEntry entry = do let correctRoute = entryR entry actualRoute <- getCurrentRoute when (actualRoute /= Just correctRoute) $ diff --git a/src/Model/Cache.hs b/src/Model/Cache.hs new file mode 100644 index 0000000..c4c48fb --- /dev/null +++ b/src/Model/Cache.hs @@ -0,0 +1,23 @@ +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE TypeFamilies #-} +module Model.Cache ( getCached ) where + +import Data.Typeable ( Typeable ) +import Database.Persist ( Entity (..), Key (..), PersistStore, PersistRecordBackend, keyToValues ) +import Yesod ( MonadHandler, HandlerSite, YesodPersist, YesodPersistBackend, cachedBy, get404, liftHandlerT, runDB ) + +import qualified Data.ByteString.Char8 as C + +newtype CachedEntity t = CachedEntity { unCachedEntity :: Entity t } deriving Typeable + +getCached :: ( MonadHandler m + , YesodPersist (HandlerSite m) + , PersistStore (YesodPersistBackend (HandlerSite m)) + , PersistRecordBackend entity (YesodPersistBackend (HandlerSite m)) + , Typeable entity + ) => Key entity -> m (Entity entity) +getCached entId = liftHandlerT . cached . runDB . withId . get404 $ entId + where key = C.pack . show . keyToValues $ entId + withId = fmap $ Entity entId + cached = fmap unCachedEntity . cachedBy key . fmap CachedEntity