add a field in Delayed that lets us specify a clean up action that can use the result of bodyD to perform some IO clean up operation
This commit is contained in:
parent
cce0f59ec8
commit
124c6de1eb
2 changed files with 30 additions and 13 deletions
|
@ -400,7 +400,7 @@ instance HasServer Raw context where
|
|||
type ServerT Raw m = Application
|
||||
|
||||
route Proxy _ rawApplication = RawRouter $ \ env request respond -> do
|
||||
r <- runDelayed rawApplication env request
|
||||
(r, _) <- runDelayed rawApplication env request
|
||||
case r of
|
||||
Route app -> app request (respond . Route)
|
||||
Fail a -> respond $ Fail a
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
{-# LANGUAGE KindSignatures #-}
|
||||
{-# LANGUAGE RecordWildCards #-}
|
||||
{-# LANGUAGE StandaloneDeriving #-}
|
||||
{-# LANGUAGE TupleSections #-}
|
||||
module Servant.Server.Internal.RoutingApplication where
|
||||
|
||||
import Control.Monad (ap, liftM)
|
||||
import Control.Monad.Trans (MonadIO(..))
|
||||
import Control.Monad.Trans.Except (runExceptT)
|
||||
import Data.IORef (newIORef, readIORef, writeIORef)
|
||||
import Network.Wai (Application, Request,
|
||||
Response, ResponseReceived)
|
||||
import Prelude ()
|
||||
|
@ -103,6 +106,10 @@ data Delayed env c where
|
|||
, authD :: DelayedIO auth
|
||||
, bodyD :: DelayedIO body
|
||||
, serverD :: captures -> auth -> body -> Request -> RouteResult c
|
||||
, cleanupD :: body -> IO ()
|
||||
-- not in DelayedIO because:
|
||||
-- - most likely should not depend on the request
|
||||
-- - simpler
|
||||
} -> Delayed env c
|
||||
|
||||
instance Functor (Delayed env) where
|
||||
|
@ -142,7 +149,7 @@ instance MonadIO DelayedIO where
|
|||
-- | A 'Delayed' without any stored checks.
|
||||
emptyDelayed :: RouteResult a -> Delayed env a
|
||||
emptyDelayed result =
|
||||
Delayed (const r) r r r (\ _ _ _ _ -> result)
|
||||
Delayed (const r) r r r (\ _ _ _ _ -> result) (const $ return ())
|
||||
where
|
||||
r = return ()
|
||||
|
||||
|
@ -198,6 +205,7 @@ addBodyCheck Delayed{..} new =
|
|||
Delayed
|
||||
{ bodyD = (,) <$> bodyD <*> new
|
||||
, serverD = \ c a (z, v) req -> ($ v) <$> serverD c a z req
|
||||
, cleanupD = cleanupD . fst -- not sure that's right
|
||||
, ..
|
||||
} -- Note [Existential Record Update]
|
||||
|
||||
|
@ -240,13 +248,19 @@ passToServer Delayed{..} x =
|
|||
runDelayed :: Delayed env a
|
||||
-> env
|
||||
-> Request
|
||||
-> IO (RouteResult a)
|
||||
runDelayed Delayed{..} env = runDelayedIO $ do
|
||||
c <- capturesD env
|
||||
-> IO (RouteResult a, IO ())
|
||||
runDelayed Delayed{..} env req = do
|
||||
cleanupRef <- newIORef (return ())
|
||||
routeRes <- runDelayedIO
|
||||
(do c <- capturesD env
|
||||
methodD
|
||||
a <- authD
|
||||
b <- bodyD
|
||||
DelayedIO (\ req -> return $ serverD c a b req)
|
||||
liftIO (writeIORef cleanupRef $ cleanupD b)
|
||||
DelayedIO $ \ req -> return (serverD c a b req)
|
||||
)
|
||||
req
|
||||
fmap (routeRes,) $ readIORef cleanupRef
|
||||
|
||||
-- | Runs a delayed server and the resulting action.
|
||||
-- Takes a continuation that lets us send a response.
|
||||
|
@ -258,8 +272,11 @@ runAction :: Delayed env (Handler a)
|
|||
-> (RouteResult Response -> IO r)
|
||||
-> (a -> RouteResult Response)
|
||||
-> IO r
|
||||
runAction action env req respond k =
|
||||
runDelayed action env req >>= go >>= respond
|
||||
runAction action env req respond k = do
|
||||
(routeResult, cleanup) <- runDelayed action env req
|
||||
resp <- go routeResult
|
||||
cleanup
|
||||
respond resp
|
||||
where
|
||||
go (Fail e) = return $ Fail e
|
||||
go (FailFatal e) = return $ FailFatal e
|
||||
|
|
Loading…
Reference in a new issue