How to use Yesod caching for each request?

I am trying to use the cached function to prevent multiple db requests in different widgets and handlers:

 newtype CachedBobId key = CachedBobId { unCachedBobId :: key } deriving Typeable getBob' :: Handler BobId getBob' = do uncle <- runInputGet $ ireq textField "bobsuncle" (Entity bob _) <- runDB $ getBy404 $ UniqueBob uncle return bob getBob :: Handler BobId getBob = do a <- getBob' let b = return $ CachedBobId a c <- cached b return $ unCachedBobId c 

And in widgets somewhere:

 renderDerp :: Widget renderDerp = do --these are used in the shakespeare files lolBob <- handlerToWidget $ getBob nutherBob <- handlerToWidget $ getBob $(widgetFile "test") 

This compiles, but the ID request is still executed several times.

What am I doing wrong? Or is there a better way to only get bob once and use it in every handler and widget?

+7
caching haskell yesod
source share
1 answer

I'm new to Yesod, but I think you just need to configure getBob

 getBob :: Handler BobId getBob = unCachedBobId <$> cached (CachedBobId <$> getBob') 

The problem is that your current getBob function starts its do block with a <- getBob' . Remember that a do blocks sequences of monolithic actions, so you actually call getBob' first on every call to getBob . In an ironic twist, after you have done this, you create a cached version of the handler that returns what you just got from getBob' , but ultimately requests this cached version exactly once (right after c <- cached b ), then it just drops out of the volume and the garbage collector gets it.

In the solution presented above, you complete everything getBob' gives you CachedBobId . Then you pass this handler CachedBobId <$> getBob' :: Handler (CachedBobId BobId) to cached , which returns another cached (CachedBobId <$> getBob') handler cached (CachedBobId <$> getBob') the same type, but with caching. Finally, you extract everything the cached handler gives you to return the Handler BobId .

+3
source share

All Articles