Hi Eric,
This is awesome! Thanks for coming up something like this, in a short period of time.
I hope this would be part of Rack, which would enable all Ruby Frameworks to work effortlessly with WebSockets.
BTW, I found a small fix is needed to get this work correctly with Google Chrome Beta. As described in Section 3.2 in IETF's "The Web Socket protocol" resource name(uri) needs to be appended when constructing the WebSocket URLs. This needs to be adhered in the WebSocket-Location value of the handshake header.
I have attached a patch which fulfills this requirement.
--
LakshanOn Mon, Dec 14, 2009 at 2:23 AM, Eric Wong <normal...@yhbt.net> wrote:
Eric Wong <normal...@yhbt.net> wrote:
> I've started getting Web Sockets going for Rainbows! (git version-only).I'm going to call it Sunshowers for now, the old name was too hard
>
> If people like it, maybe this can be put into Rack itself (and it'll
> have a better name and more exposure).
for other folks to remember.
I'm going to make a release of both Rainbows!+Sunshowers later
today, but the git versions should be ready to play with.
--
Eric Wong
<resource_name_fix.diff>
Quite right and the point I'm simply trying to make, is that there are APIs that can work with all concurrency models. Moreover, it is trivial to turn an asynchronous api into a synchronous api, by contrast it is almost impossible to do the reverse. This is why my planned changes to rack are so far from becoming a reality at this time - as I have to rewrite the entire stack. By contrast, supporting rack 1.0 protocoled apps from the vapour 2.0 api, whatever it is, is absolutely trivial.
>
> Of course stack-based concurrency models will always be slower on the
> machine than state machine + event-based models.
>
> Ruby will also always be slower than a lot of other
> less-pleasant-to-write languages out there. It's a tradeoff we make as
> Rubyists. I believe most developers find things like
> fibers/actors/threads easier to work with/maintain than
> events+callbacks, so Sunshowers got support for linear programming
> models first.
Agreed. I'm not saying "must", but I would like to request that if you're going to try and support asynchronous models, please do it for real, rather than hacking it in the way we're having to in rack / thin / flow / etc. The more hacks we end up with, the more people get the impression that this is "the right way". As it is, the lack of protocol - app layer separation in for example, eventmachine applications is appalling, and something from which the community may never recover. The same kind of history is about to repeat itself in the async + long running cycle web areas - if it hasn't already gone past the point of no return.
Of course, if it seems like too much work, please do just ignore my request, maybe I'm an ideologist, or maybe I need to formalise my thoughts on paper before they'll really have an impact, but I have experience that tells me that async apis needn't be ugly, or hard, or slower to write - indeed javascript and C programmers use them all the time, unwittingly. One part of the failure in ruby is the implicit temptation to "solve" these "problems" by just "slapping in a few blocks" or the like. Proper OO design does a much better job, and of late the favoured patterns are most definitely channels, queues, and closure-less callbacks - but most of this stuff is in real use in commercial code, as there is no high scale high efficiency open source application server in ruby at this time (that i know of). I do not believe this is due to language limitations, but simply lack of demand and developer time.
> With a env["rack.io"] that exposes an IO-ish object, then nothing
> prevents developers from using EM.attach or Rev::IO.new on it, either.
Depending of course, one whether or not that's even a useful thing to do...
request -> app -> attach | release is required here, otherwise the attach was useless
Contrary to a sync approach, this now means we're back in hack-town to push our state somewhere other than the stack, then release the reactor (in a reactor pattern) to actually complete any more IO.
Of course, if we passed a channel, with a correctly restricted API, all these issues go away. It's down to the server to schedule IO (big tick here), and the app just consumes a callback based API in a standard manner.
Synchronous apps can simply drain the channel in a synchronous (busy wait) manner, or have their callbacks implicitly and immediately scheduled. Implicit and immediate scheduling of callbacks is the simplest common approach, leaving only a call that might be considered slightly excess in a "pure synchronous" environment, but really ends up being akin to #read and such.
It is only through proper abstraction that you can make it easy to introduce or maintain concepts such as zero copy, wait free blocking, demand based scheduling, and so on and so forth. I do realise that examples of more complex scheduling and IO patterns are for the most part limited to kernels, academia and telecomms at present, but, funnily enough, I think this has a lot to do with the restrictive APIs that more common patterns expose - I've mentioned already that it's nearly impossible to retro-fit these things.
> If people like that, I'd be happy to include it EM and Rev-based
> concurrency models for Rainbows! and add support for it in Sunshowers.
Like I say, I could just be too much of an efficiency ideologist. If you don't have the demand / desire for it, then you may not have a good reason to put the effort in - certainly there's nothing else in the middle-ground space that you're filling presently, so I don't think you're "losing a significant market" by not doing so. As it is, I know of a couple of handfuls of apps either in production or close to production doing relatively high load async web work in ruby, and those folks seem to have done alright with the nasty hack that is the current async.callback and deferrable body apis. Bigger deterrents to this area actually exist outside of the web server domain itself, as the 1.2+ Thin api works just fine, by contrast, there's no ORM or process framework for doing async work well, and the closest thing there really is to a "nice" async api in ruby open source at present is the sequel monkey patches that Aman published iirc with em-mysql.
P.S. it's late, so i apologise if this is too wordy/vague.
I'm glad I'm not alone in feeling the current async add-ons in Rack
servers are very hacky. I'll leave async callback support out of
Sunshowers until we can have an async spec that's as elegant the
rest of Rack.
> Like I say, I could just be too much of an efficiency ideologist. If
> you don't have the demand / desire for it, then you may not have a
> good reason to put the effort in - certainly there's nothing else in
> the middle-ground space that you're filling presently, so I don't
> think you're "losing a significant market" by not doing so. As it is,
> I know of a couple of handfuls of apps either in production or close
> to production doing relatively high load async web work in ruby, and
> those folks seem to have done alright with the nasty hack that is the
> current async.callback and deferrable body apis. Bigger deterrents to
> this area actually exist outside of the web server domain itself, as
> the 1.2+ Thin api works just fine, by contrast, there's no ORM or
> process framework for doing async work well, and the closest thing
> there really is to a "nice" async api in ruby open source at present
> is the sequel monkey patches that Aman published iirc with em-mysql.
Heh, I don't know of a single public site using Rainbows! (in any form)
nor Sunshowers in production, yet. It's winter right now and probably
not the season for Rainbows! and Sunshowers :)
> P.S. it's late, so i apologise if this is too wordy/vague.
Nope, I pretty agree with everything you said and will look forward to a
Rack 2.0 spec that covers async nicely. Meanwhile, I'll keep the focus
on 1.9 Fibers since they're largely "good enough".
--
Eric Wong
> James Tucker <jftu...@gmail.com> wrote:
> <snip>
>> Agreed. I'm not saying "must", but I would like to request that if
>> you're going to try and support asynchronous models, please do it for
>> real, rather than hacking it in the way we're having to in rack / thin
>> / flow / etc. The more hacks we end up with, the more people get the
>> impression that this is "the right way". As it is, the lack of
>> protocol - app layer separation in for example, eventmachine
>> applications is appalling, and something from which the community may
>> never recover. The same kind of history is about to repeat itself in
>> the async + long running cycle web areas - if it hasn't already gone
>> past the point of no return.
>
> I'm glad I'm not alone in feeling the current async add-ons in Rack
> servers are very hacky. I'll leave async callback support out of
> Sunshowers until we can have an async spec that's as elegant the
> rest of Rack.
Yup, this is part of the reason I refused to release my Thin patches for such a long time. They're not graceful at all. Unfortunately, after some of the heavy lifters had been using it in production for a while, and it was becoming a core component of some of the nanite infrastructure, the amount of noise it was causing in my inbox overrode my desire to hold back the unfortunate API from the public as a whole. It's getting an increasing amount of attention, for better or worse at the moment.
>> Like I say, I could just be too much of an efficiency ideologist. If
>> you don't have the demand / desire for it, then you may not have a
>> good reason to put the effort in - certainly there's nothing else in
>> the middle-ground space that you're filling presently, so I don't
>> think you're "losing a significant market" by not doing so. As it is,
>> I know of a couple of handfuls of apps either in production or close
>> to production doing relatively high load async web work in ruby, and
>> those folks seem to have done alright with the nasty hack that is the
>> current async.callback and deferrable body apis. Bigger deterrents to
>> this area actually exist outside of the web server domain itself, as
>> the 1.2+ Thin api works just fine, by contrast, there's no ORM or
>> process framework for doing async work well, and the closest thing
>> there really is to a "nice" async api in ruby open source at present
>> is the sequel monkey patches that Aman published iirc with em-mysql.
>
> Heh, I don't know of a single public site using Rainbows! (in any form)
> nor Sunshowers in production, yet. It's winter right now and probably
> not the season for Rainbows! and Sunshowers :)
:D
I don't know if you follow the Thin mailinglist, but there's a discussion relating to some of this stuff going on over there that you might find useful to read through, just from the point of view of how general community members tend to approach the idea of async, and the common misconceptions etc. My really long term goal is to get the APIs down to something simple enough that these issues don't come up, but part of this is also the requirement for a new breed of framework that's not built around inherently synchronous ORM systems.
>> P.S. it's late, so i apologise if this is too wordy/vague.
>
> Nope, I pretty agree with everything you said and will look forward to a
> Rack 2.0 spec that covers async nicely. Meanwhile, I'll keep the focus
> on 1.9 Fibers since they're largely "good enough".
Absolutely, I know that oldmoe has had some great success using them in NeverBlock, and who knows, if ruby can be made to be more efficient at stack wrangling one day, then maybe they could defeat the async approach. Certainly for the foreseeable decades, that's not going to happen though :)
I'll be sure to include you in any future discussions on the APIs discussed.
>
> --
> Eric Wong