-
-
Save DAddYE/5a5b688e75fab806009b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Based on a @tenderlove slide | |
require 'thread' | |
require 'rack' | |
require 'thin' # --pre version! | |
class Latch | |
attr_reader :count | |
def initialize | |
@released = false | |
@lock = Mutex.new | |
@condition = ConditionVariable.new | |
end | |
def callback(&block) | |
block.call | |
end | |
def release | |
@lock.synchronize do | |
@released = true | |
@condition.broadcast | |
end | |
end | |
def wait | |
@lock.synchronize do | |
@condition.wait(@lock) while not @released | |
end | |
end | |
end | |
class Response | |
attr_reader :code, :header | |
def initialize | |
@_written = Latch.new | |
@_queue = Queue.new | |
@code = 200 | |
@header = {} | |
end | |
def wait | |
@_written.wait | |
end | |
def write_header(code, header) | |
@code = code | |
@header = header | |
@_written.release | |
end | |
def chunk(string) | |
@_queue.push string | |
@_written.release | |
end | |
def end(string) | |
@_queue.push string | |
@_queue.push nil | |
@_written.release | |
end | |
def each(&block) | |
while chunk = @_queue.pop | |
block[chunk] | |
end | |
end | |
end | |
class Node | |
attr_reader :block | |
def initialize(&block) | |
@block = block | |
end | |
def call(env) | |
resp = Response.new | |
Thread.new { block[env, resp] } | |
resp.wait | |
[resp.code, resp.header, resp] | |
end | |
def self.create_server(&block) | |
app = Rack::Builder.new do | |
use Rack::ContentLength | |
use Rack::Chunked | |
run Node.new(&block) | |
end | |
Server.new(app) | |
end | |
end | |
class Server | |
attr_reader :backend | |
def initialize(app) | |
@backend = Thin::Server.new { app } | |
end | |
def listen(port=nil) | |
backend.listen(port) | |
backend.start | |
end | |
alias listen! listen | |
end | |
return unless $0 == __FILE__ | |
ENV['RACK_ENV'] = 'production' | |
Node.create_server do |env, resp| | |
resp.write_header(200, {'Content-Type' => 'text/plain'}) | |
# 10.times do | |
# resp.chunk "pimp\n"; sleep 0.5 | |
# end | |
resp.end("Hello World\n") | |
end.listen(3000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is this going to be implemented I would like to help to build this because I've used nodejs for a project only because I needed an async feature but honestly javascript is a ugly language so I would like to bring this feature to the ruby world in an elegant way, I have checked goliath and angelo but they work on top of eventmachine and reel and I didn't like their style.