Module: Rainbows::Revactor
- Includes:
- Base
- Defined in:
- lib/rainbows/revactor.rb
Overview
Enables use of the Actor model through Revactor under Ruby 1.9.
Revactor dormant upstream, so the use of this is NOT recommended for new applications.
It spawns one long-lived Actor for every listen socket in the process and spawns a new Actor for every client connection accept()-ed. worker_connections
will limit the number of client Actors we have running at any one time.
Applications using this model are required to be reentrant, but do not have to worry about race conditions unless they use threads internally. Rainbows! does not spawn threads under this model. Multiple instances of the same app may run in the same address space sequentially (but at interleaved points). Any network dependencies in the application using this model should be implemented using the Revactor library as well, to take advantage of the networking concurrency features this model provides.
RubyGem Requirements
-
revactor 0.1.5 or later
Instance Method Summary collapse
-
#revactorize_listeners ⇒ Object
:nodoc:.
-
#worker_loop(worker) ⇒ Object
runs inside each forked worker, this sits around and waits for connections and doesn’t die until the parent dies (or is given a INT, QUIT, or TERM signal).
Methods included from Base
included, #init_worker_process, #process_client, #reopen_worker_logs, #sig_receiver
Instance Method Details
#revactorize_listeners ⇒ Object
:nodoc:
82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/rainbows/revactor.rb', line 82 def revactorize_listeners #:nodoc: LISTENERS.map do |s| case s when TCPServer l = Revactor::TCP.listen(s, nil) [ l, T[:tcp_closed, Revactor::TCP::Socket], T[:tcp_connection, l, Revactor::TCP::Socket] ] when UNIXServer l = Revactor::UNIX.listen(s) [ l, T[:unix_closed, Revactor::UNIX::Socket ], T[:unix_connection, l, Revactor::UNIX::Socket] ] end end end |
#worker_loop(worker) ⇒ Object
runs inside each forked worker, this sits around and waits for connections and doesn’t die until the parent dies (or is given a INT, QUIT, or TERM signal)
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/rainbows/revactor.rb', line 36 def worker_loop(worker) #:nodoc: Client.setup init_worker_process(worker) nr = 0 limit = worker_connections actor_exit = Case[:exit, Actor, Object] revactorize_listeners.each do |l,close,accept| Actor.spawn do Actor.current.trap_exit = true l.controller = l.instance_variable_set(:@receiver, Actor.current) begin while nr >= limit l.disable if l.enabled? logger.info "busy: clients=#{nr} >= limit=#{limit}" Actor.receive do |f| f.when(close) {} f.when(actor_exit) { nr -= 1 } f.after(0.01) {} # another listener could've gotten an exit end end l.enable unless l.enabled? Actor.receive do |f| f.when(close) {} f.when(actor_exit) { nr -= 1 } f.when(accept) do |_, _, s| nr += 1 Actor.spawn_link(s) { |c| Client.new(c).process_loop } end end rescue => e Rainbows::Error.listen_loop(e) end while Rainbows.alive Actor.receive do |f| f.when(close) {} f.when(actor_exit) { nr -= 1 } end while nr > 0 end end Actor.sleep 1 while Rainbows.tick || nr > 0 rescue Errno::EMFILE # ignore, let another worker process take it end |