Skip to content
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

Use resourcet for resource managment #675

Merged
merged 5 commits into from
Jan 19, 2017
Merged

Conversation

phadej
Copy link
Contributor

@phadej phadej commented Jan 18, 2017

No description provided.

@phadej phadej added this to the 0.10 milestone Jan 18, 2017
r <- runDelayed rawApplication env request cleanupRef
go r request respond `finally` runCleanup cleanupRef
r <- runDelayed rawApplication env request
go r request respond
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait, here I guess I'll run cleanups too early. Wouldn't it?

@@ -264,18 +303,17 @@ passToServer Delayed{..} x =
runDelayed :: Delayed env a
-> env
-> Request
-> CleanupRef
-> IO (RouteResult a)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so should this return ResourceT IO (RouteResult a)?

Copy link
Member

@jkarni jkarni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small comments, but overall this looks great!

@@ -65,7 +63,7 @@ steps:

# A common setting is the number of columns (parts of) code will be wrapped
# to. Different steps take this into account. Default: 80.
columns: 80
columns: 120
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to change this here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really, except with current style the import lists are almost always spanning multiple lines, which I find annoying. There's a bit of settings in newest stylish-haskell so if the line is too long, imports could be aligned as

import           Data.List (foldl')
import qualified VeryLongNamespace.Data.Foo.Bar
                 (foo, bar, quux, longMethodName, anotherLongMethodName, Foobar,
                 MonadEveryhing, zyxxy)

or at least I remember making some such configuration possible.

I'll revert this change and investigate more (subjectively) pleasant (yet diff friendly) formatting style.

instance MonadThrow m => MonadThrow (RouteResultT m) where
throwM = lift . throwM

-- instance MonadCatch m => MonadCatch (RouteResultT m) where
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these.

newtype RouteResultT m a = RouteResultT { runRouteResultT :: m (RouteResult a) }
deriving (Functor)

-- As we write these instances, we get instances for `DelayedIO` with GND.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the comment is necessary. Instances are always good in my opinion.

pure = return
(<*>) = ap
returnRouteResult :: RouteResult a -> DelayedIO a
returnRouteResult x = DelayedIO $ lift . lift $ RouteResultT . return $ x
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about the name, but can't think of anything better (maybe delayRouteResult?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's about liftRouteResult ?

it "writes and cleanups resources" $ do
request "GET" "foobar" [] "" `shouldRespondWith` "foobar"
liftIO $ do
cleanUpDone <- isJust <$> readIORef delayedTestRef
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test can in theory pass if check in line 67 were never run. Can we maybe write something other than Nothing (the initial ref state) to be sure the value is coming from deallocation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make a IORef three way, None | InUse a | Cleared.


-------------------------------------------------------------------------------
-- Spec
-------------------------------------------------------------------------------
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely don't insist on it, but it perhaps would be nice to have a test where the combinator allocating the resource forks a thread, and that thread waits on an MVar (with readMVar). Then the test checks (a) that before it putMVars, the resource is not yet deallocated, and (b) after it putMVars, the resource is deallocated.

What I have in mind is forking jobs that are longer running, which I imagine would be commonly used in conjunction with resources, especially if we make Handler a MonadResource.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not understand, could you write an example, assuming that Handler is MonadResource?

runDelayedIO
(do c <- capturesD env
methodD
a <- authD
b <- bodyD
DelayedIO $ \ r _cleanup -> return (serverD c a b r)
r <- ask
returnRouteResult (serverD c a b r)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that Handler is abstract, and that this is being added, I feel like it makes sense to make Handler a MonadResource so that handlers can also register, allocate, and release. That said, that can just as well be a separate PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handler cannot, it's just ExceptT ServerErr IO a. Then we'll need to add ResourceT there too. I'm neutral about that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(There's no technical problem adding it, the runHandler is inside runResourceT anyway).

@phadej phadej merged commit 8c32913 into haskell-servant:master Jan 19, 2017
@phadej phadej deleted the resourcet branch January 19, 2017 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants