2015-11-11 3 views
7

Я пытаюсь использовать функцию cached, чтобы предотвратить несколько запросов в БД различных виджетов и обработчиков:Как использовать кэширование Yesod для каждого запроса?

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 

И в виджете где:

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

компилируется, но запрос, чтобы получить ID все еще работает несколько раз.

Что я делаю неправильно? Или есть лучший способ только получить bob один раз и использовать его в каждом обработчике и виджетах?

+0

Не действительно прочитал код внутри вопроса (так как у меня была проблема с 'cached' тоже). Кто-то получит очень легкие 200 очков. – Cthulhu

ответ

3

Я довольно новый для Йесода, но я думаю, что вам просто нужно настроить getBob

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

Проблема заключается в том, что текущая getBob функция начинает do блока с a <- getBob'. Помните, что блок-последовательность выполняет монадические действия, так что вы на самом деле в конечном итоге вызываете getBob' первое, каждый раз, когда вызывается getBob. В ироническом твисте, после того, как вы это сделали, вы создаете кэшированную версию обработчика, которая возвращает то, что вы только что получили от getBob', но в конечном итоге запрашивает эту кешированную версию ровно один раз (сразу после c <- cached b), тогда она просто выпадает объема, и сборщик мусора получает его.

В решении, представленном выше, вы обертываете все, что getBob' дает вам CachedBobId. Затем вы передаете этот обработчик CachedBobId <$> getBob' :: Handler (CachedBobId BobId), до cached, который возвращает вам еще один обработчик cached (CachedBobId <$> getBob') того же типа, но с кешированием. Наконец, вы извлекаете все, что кэшированный обработчик дает вам вернуть Handler BobId.

Смежные вопросы