-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor to exceptions #31
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ import Prelude hiding ((++)) | |
import Blaze.ByteString.Builder | ||
import Configuration.Dotenv (loadFile) | ||
import Control.Concurrent.MVar | ||
import Control.Exception (throw) | ||
import Control.Lens hiding ((.=)) | ||
import Control.Monad (mplus, void, when) | ||
import Control.Monad.State (StateT, evalStateT) | ||
|
@@ -116,6 +117,7 @@ tplLibrary = | |
,(["custom-endpoint-object"], parse "<wpCustom endpoint=\"wp/v2/taxonomies\"><wpCategory><wpRestBase /></wpCategory></wpCustom>") | ||
,(["custom-endpoint-array"], parse "<wpCustom endpoint=\"wp/v2/posts\"><wpDate /></wpCustom>") | ||
,(["custom-endpoint-enter-the-matrix"], parse "<wpCustom endpoint=\"wp/v2/posts\"><wpCustom endpoint=\"wp/v2/posts/${wpId}\"><wpDate /></wpCustom></wpCustom>") | ||
,(["custom-endpoint-404"], parse "<wpCustom endpoint=\"doesnt/exist\"></wpCustom>") | ||
] | ||
|
||
renderLarceny :: Ctxt -> | ||
|
@@ -129,34 +131,34 @@ renderLarceny ctxt name = | |
return $ Just rendered | ||
_ -> return Nothing | ||
|
||
fauxRequester :: Maybe (MVar [Text]) -> Text -> [(Text, Text)] -> IO (Either StatusCode Text) | ||
fauxRequester :: Maybe (MVar [Text]) -> Text -> [(Text, Text)] -> IO Text | ||
fauxRequester _ "/wp/v2/tags" [("slug", "home-featured")] = | ||
return $ Right $ enc [object [ "id" .= (177 :: Int) | ||
return $ enc [object [ "id" .= (177 :: Int) | ||
, "slug" .= ("home-featured" :: Text) | ||
]] | ||
fauxRequester _ "/wp/v2/tags" [("slug", "featured-global")] = | ||
return $ Right $ enc [object [ "id" .= (160 :: Int) | ||
return $ enc [object [ "id" .= (160 :: Int) | ||
, "slug" .= ("featured-global" :: Text) | ||
]] | ||
fauxRequester _ "/wp/v2/categories" [("slug", "bookmarx")] = | ||
return $ Right $ enc [object [ "id" .= (159 :: Int) | ||
return $ enc [object [ "id" .= (159 :: Int) | ||
, "slug" .= ("bookmarx" :: Text) | ||
, "meta" .= object ["links" .= object ["self" .= ("/159" :: Text)]] | ||
] ] | ||
fauxRequester _ "/jacobin/featured-content/editors-picks" [] = | ||
return $ Right $ enc [object [ "post_date" .= ("2013-04-26 10:11:52" :: Text) | ||
return $ enc [object [ "post_date" .= ("2013-04-26 10:11:52" :: Text) | ||
, "date" .= ("2014-04-26 10:11:52" :: Text) | ||
, "post_date_gmt" .= ("2015-04-26 15:11:52" :: Text) | ||
]] | ||
fauxRequester _ "/wp/v2/pages" [("slug", "a-first-page")] = | ||
return $ Right $ enc [page1] | ||
return $ enc [page1] | ||
fauxRequester _ "/dev/null" [] = | ||
return $ Right $ enc [object ["this_is_null" .= Null]] | ||
return $ enc [object ["this_is_null" .= Null]] | ||
fauxRequester mRecord rqPath rqParams = do | ||
case mRecord of | ||
Just record -> modifyMVar_ record $ return . (<> [mkUrlUnescape rqPath rqParams]) | ||
Nothing -> return () | ||
return $ Right $ enc [article1] | ||
return $ enc [article1] | ||
where mkUrlUnescape url params = | ||
url <> "?" | ||
<> T.intercalate "&" (map (\(k, v) -> k <> "=" <> v) params) | ||
|
@@ -179,7 +181,7 @@ initFauxRequestNoCache = | |
initializer (Right $ Requester (fauxRequester Nothing)) NoCache "" | ||
|
||
initNoRequestWithCache = | ||
initializer (Right $ Requester (\_ _ -> return (Right "") )) (CacheSeconds 60) "" | ||
initializer (Right $ Requester (\_ _ -> return "")) (CacheSeconds 60) "" | ||
|
||
---------------------------------------------------------- | ||
-- Section 2: Test suite against application. -- | ||
|
@@ -204,7 +206,7 @@ clearRedisCache ctxt = R.runRedis (_redis ctxt) (rdelstar "wordpress:*") | |
|
||
unobj :: Value -> Object | ||
unobj (Object x) = x | ||
unobj _ = error "Not an object" | ||
unobj _ = throw NotAnObject | ||
|
||
toTpl tpl = parse (TL.fromStrict tpl) | ||
|
||
|
@@ -426,6 +428,7 @@ shouldRenderContaining :: (TemplateName, Ctxt) -> Text -> Expectation | |
shouldRenderContaining (template, ctxt) match = do | ||
rendered <- renderLarceny ctxt template | ||
let rendered' = fromMaybe "" rendered | ||
liftIO $ print rendered' | ||
(match `T.isInfixOf` rendered') `shouldBe` True | ||
|
||
shouldNotRenderContaining :: (TemplateName, Ctxt) -> Text -> Expectation | ||
|
@@ -484,12 +487,14 @@ liveTests = | |
it "should be able to query custom taxonomies" $ do | ||
("department", ctxt) `shouldRenderContaining` "A sports post" | ||
("department", ctxt) `shouldNotRenderContaining` "A first post" | ||
it "should be able to query custom endpoints" $ do | ||
it "should be able to query custom endpoints (as object)" $ do | ||
("custom-endpoint-object", ctxt) `shouldRenderContaining` "categories" | ||
("custom-endpoint-object", ctxt) `shouldNotRenderContaining` "departments" | ||
it "should be able to query custom endpoints" $ do | ||
it "should be able to query custom endpoints (as array)" $ do | ||
("custom-endpoint-array", ctxt) `shouldRenderContaining` "2014-10-01" | ||
("custom-endpoint-array", ctxt) `shouldRenderContaining` "2014-10-02" | ||
("custom-endpoint-array", ctxt) `shouldRenderContaining` "2014-10-15" | ||
it "should be able to reference fields from the custom endpoint in another custom endpoint query" $ do | ||
("custom-endpoint-array", ctxt) `rendersSameAs` "custom-endpoint-enter-the-matrix" | ||
it "should handle 404s without blowing up" $ | ||
("custom-endpoint-404", ctxt) `shouldRenderContaining` "404" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This works, but the wreq/http-client exception has a LOT of information that doesn't belong in the HTML debugging comment. Right now all the information about the request is in there. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,20 @@ | ||
{-# LANGUAGE OverloadedStrings #-} | ||
{-# LANGUAGE RankNTypes #-} | ||
{-# LANGUAGE RecordWildCards #-} | ||
{-# LANGUAGE DataKinds #-} | ||
{-# LANGUAGE OverloadedStrings #-} | ||
{-# LANGUAGE RankNTypes #-} | ||
{-# LANGUAGE RecordWildCards #-} | ||
{-# LANGUAGE ScopedTypeVariables #-} | ||
|
||
module Web.Offset.Cache where | ||
|
||
import Control.Concurrent as CC | ||
import qualified Control.Concurrent.Async as CC | ||
import Control.Concurrent.MVar | ||
import Control.Exception (Handler (..), catch, catches, handle, | ||
onException, throw, try) | ||
import Control.Monad (void) | ||
import Data.Map (Map) | ||
import qualified Data.Map as Map | ||
import Data.Maybe (fromMaybe) | ||
import Data.Monoid ((<>)) | ||
import qualified Data.Set as Set | ||
import Data.Text (Text) | ||
|
@@ -36,50 +41,33 @@ stopReqMutexInt :: MVar (Map WPKey UTCTime) -> WPKey -> IO () | |
stopReqMutexInt activeMV wpKey = | ||
modifyMVar_ activeMV $ return . Map.delete wpKey | ||
|
||
cachingGetRetryInt :: WordpressInt b -> WPKey -> IO (Either StatusCode Text) | ||
cachingGetRetryInt :: WordpressInt b -> WPKey -> IO Text | ||
cachingGetRetryInt wp = retryUnless . cachingGetInt wp | ||
|
||
cachingGetErrorInt :: WordpressInt b -> WPKey -> IO (Either StatusCode Text) | ||
cachingGetErrorInt wp wpKey = errorUnless msg (cachingGetInt wp wpKey) | ||
where msg = "Could not retrieve " <> tshow wpKey | ||
|
||
retryUnless :: IO (CacheResult a) -> IO (Either StatusCode a) | ||
retryUnless :: IO a -> IO a | ||
retryUnless action = | ||
do ma <- action | ||
case ma of | ||
Successful r -> return $ Right r | ||
Abort code -> return $ Left code | ||
Retry -> do CC.threadDelay 100000 | ||
retryUnless action | ||
|
||
errorUnless :: Text -> IO (CacheResult a) -> IO (Either StatusCode a) | ||
catch action (\(e :: CacheInProgress) -> CC.threadDelay 100000 >> retryUnless action) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So here I'm caching this (There are no tests that exercise this stuff!) |
||
errorUnless :: Text -> IO a -> IO (Either StatusCode a) | ||
errorUnless msg action = | ||
do ma <- action | ||
case ma of | ||
Successful a -> return $ Right a | ||
Abort code -> return $ Left code | ||
Retry -> return $ Left 500 | ||
(Right <$> action) `catches` | ||
[ Handler (\(e :: StatusCodeException) -> return $ Left (code e)) | ||
, Handler (\(e :: CacheInProgress) -> return $ Left 500) ] | ||
|
||
cachingGetInt :: WordpressInt b | ||
-> WPKey | ||
-> IO (CacheResult Text) | ||
cachingGetInt WordpressInt{..} wpKey = | ||
do mCached <- wpCacheGet wpKey | ||
case mCached of | ||
Just cached -> return $ Successful cached | ||
Nothing -> | ||
do running <- startReqMutex wpKey | ||
if running | ||
then return Retry | ||
else | ||
do o <- wpRequest wpKey | ||
case o of | ||
Left errorCode -> | ||
return $ Abort errorCode | ||
Right jsonBlob -> do | ||
wpCacheSet wpKey jsonBlob | ||
stopReqMutex wpKey | ||
return $ Successful jsonBlob | ||
-> IO Text | ||
cachingGetInt WordpressInt{..} wpKey = do | ||
mCached <- wpCacheGet wpKey | ||
fromMaybe getAndCache (return <$> mCached) | ||
where getAndCache = do jsonBlob <- wpRequest wpKey | ||
wpCacheSet wpKey jsonBlob | ||
stopReqMutex wpKey | ||
return jsonBlob | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is so much easier to look at! yay! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 👍 |
||
|
||
wpCacheGetInt :: RunRedis -> CacheBehavior -> WPKey -> IO (Maybe Text) | ||
wpCacheGetInt runRedis b = runRedis . cacheGet b . formatKey | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is silly, should've just stayed an error (it's only for testing)