Skip to content

Instantly share code, notes, and snippets.

@DAddYE

DAddYE/node.rb Secret

Last active December 10, 2015 03:28
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DAddYE/5a5b688e75fab806009b to your computer and use it in GitHub Desktop.
Save DAddYE/5a5b688e75fab806009b to your computer and use it in GitHub Desktop.
# 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)
@mrkaspa
Copy link

mrkaspa commented Oct 30, 2014

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment