[web-devel] Upgrading to warp 2

Bardur Arantsson spam at scientician.net
Tue Feb 25 19:43:15 UTC 2014


On 2014-02-25 05:49, Michael Snoyman wrote:
> On Mon, Feb 24, 2014 at 11:00 PM, Bardur Arantsson <spam at scientician.net>wrote:

(I've taken the liberty of CC'ing the list.)

> 
>> Hi all,
>>
[--snip--]
>> When I try this I get:
>>
>>   src/Handlers.hs:96:54:
>>     No instance for (MonadResource IO)
>>       arising from a use of `sourceFileRange'
>>     Possible fix: add an instance declaration for (MonadResource IO)
>>     In the second argument of `($)', namely
>>       `sourceFileRange sfp (Just l') (Just n)'
>>     In the expression:
>>       mapOutput (Chunk . fromByteString)
>>       $ sourceFileRange sfp (Just l') (Just n)
>>     In an equation for `src':
>>         src
>>           = mapOutput (Chunk . fromByteString)
>>             $ sourceFileRange sfp (Just l') (Just n)
>>
>> ... which I guess kinda makes sense -- you'd need a ResourceT (or
>> similar) in the monad stack. I'm just not sure how or where to introduce
>> the ResourceT to get this working.
>>
>> If I introduce an explicit type signature for "src",
>>
>>    src :: forall m . MonadResource m => Source m (Flush Builder)
>>
>> then that line compiles, but I get the equivalent error at the usage
>> site of "src" in the third argument to "responseSource" (which again
>> also makes sense).
>>
>> Anyone got any pointers?
>>
>> Regards,
>>
>>
> Firstly, why aren't you just using responseFile[1]? That will be more
> efficient than using a Source directly, since Warp is able to use the
> sendfile system call, not to mention all of Kazu's fancy fd-caching logic.
> Even on a non-Warp backend, the functionality can simply degrade to being
> the same as using a Source. Also, not sure if it's relevant, but Warp can
> automatically handle range requests for you, so if you simply return a
> responseFile and the user requests part of the file, Warp will
> automatically generate the 206 response.
> 

ResponseFile is broken for some clients (with Linux host at least),
specifically my type of client, a PlayStation 3 (UPnP media player).
There was a Thread of Doom(TM) about it on haskell-cafe, but it caused
FD leaks, though we never found out quite *why* it was broken that way.

(Things may have changed since this was in February 2010, but frankly I
don't even care to spend the time to find out -- I don't need the
performance anyway. I think I remember testing the WAI/Warp sendfile
equivalent in pre-2.0 WAI/Warp and finding that it still had the same
problem.)

> Anyway, the issue here is that in WAI 2.0, we removed ResourceT from the
> WAI stack for efficiency reasons.

Yup, I noticed that ;)

> That makes the cases where you *do* need
> to safely allocate scarce resources like a file handle a bit trickier. In
> this case, I wouldn't bother with ResourceT at all, but instead explicitly
> use the bracket pattern, via responseSourceBracket, openFile, and
> closeFile. This would look like:
> 
> serveFile :: Integer -> [(Maybe Integer, Maybe Integer)] -> IO Response
> serveFile fsz [(l,h)] = do
>   let l' = maybe 0 id l
>   let h' = maybe (fsz-1) id h
>   let n = (h' - l' + 1)
>   let src h = mapOutput (Chunk . fromByteString) $ sourceHandleRange h
> (Just l') (Just n)
>       sfp = "foo.hs"
>   responseSourceBracket
>     (IO.openFile sfp IO.ReadMode) (IO.hClose) $ \h ->
>         return (partialContent206, [], src h)
> 
> 
> [1]
> http://hackage.haskell.org/package/wai-2.0.0/docs/Network-Wai.html#v:responseFile
> 

Ah, yes, this works! I had noticed responseSourceBracket, but (stupidly)
didn't actually try it. Thank you very much.

Regards,



More information about the web-devel mailing list