Permalink
Browse files

Convert Spawn to class so it can be called from anywhere

* removed rails includes since it should work everywhere
* updated README
* renamed SpawnId to Spawn::Id
  • Loading branch information...
1 parent 4799e19 commit 889ca52229a105d3fa544cc4d12225db03e5d113 Tom Anderson committed Apr 1, 2013
Showing with 38 additions and 64 deletions.
  1. +17 −9 README.markdown
  2. +0 −5 init.rb
  3. +8 −8 lib/patches.rb
  4. +13 −42 lib/spawn.rb
View
@@ -1,3 +1,9 @@
+#News
+
+Now runs with ruby 1.9 (and later). Because ruby "stole" the name "spawn", this gem
+now has been redefined to use "Spawn.run(&block)" instead of "spawn(&block)". Other
+than that nothing has changed in the basic usage. Read below for detailed usage.
+
# Spawn
This gem provides a 'spawn' method to easily fork OR thread long-running sections of
@@ -10,9 +16,9 @@ threads (see lib/patches.rb).
## Installation
-If you want to live on the "edge" branch (note: currently the only branch that has the gem is "edge"), then
+If you want to live on the edge of the master branch,
- gem "spawn", :git => 'git://github.com/tra/spawn', :branch => "edge"
+ gem "spawn", :git => 'git://github.com/tra/spawn'
in your Gemfile and use bundler to manage it (bundle install, bundle update).
@@ -30,7 +36,7 @@ into your config/database.yml.
Here's a simple example of how to demonstrate the spawn plugin.
In one of your controllers, insert this code (after installing the plugin of course):
- spawn do
+ Spawn.run do
logger.info("I feel sleepy...")
sleep 11
logger.info("Time to wake up!")
@@ -40,16 +46,16 @@ If everything is working correctly, your controller should finish quickly then y
the last log message several seconds later.
If you need to wait for the spawned processes/threads, then pass the objects returned by
-spawn to Spawn::wait(), like this:
+spawn to Spawn.wait(), like this:
N.times do |i|
# spawn N blocks of code
- spawn_ids[i] = spawn do
+ spawn_ids[i] = Spawn.run do
something(i)
end
end
# wait for all N blocks of code to finish running
- wait(spawn_ids)
+ Spawn.wait(spawn_ids)
## Options
@@ -88,7 +94,7 @@ methods according to your needs.
If you want your forked child to run at a lower priority than the parent process, pass in
the :nice option like this:
- spawn(:nice => 7) do
+ Spawn.run(:nice => 7) do
do_something_nicely
end
@@ -99,7 +105,7 @@ do threading either by telling the spawn method when you call it or by configuri
environment.
For example, this is how you can tell spawn to use threading on the call,
- spawn(:method => :thread) do
+ Spawn.run(:method => :thread) do
something
end
@@ -128,7 +134,7 @@ listing the running processes (ps).
For example, if you do something like this,
3.times do |i|
- spawn(:argv => "spawn -#{i}-") do
+ Spawn.run(:argv => "spawn -#{i}-") do
something(i)
end
end
@@ -195,6 +201,8 @@ including:
- Jay Caines-Gooby, Eric Stewart (Unicorn fix)
+- Dan Sharp for the changes that allow it to work with Ruby 1.9 and later
+
- <your name here>
Copyright (c) 2007-present Tom Anderson (tom@squeat.com), see LICENSE
View
@@ -1,6 +1 @@
require 'spawn'
-require 'patches'
-
-ActiveRecord::Base.send :include, Spawn
-ActionController::Base.send :include, Spawn
-ActiveRecord::Observer.send :include, Spawn
View
@@ -2,7 +2,7 @@
# see activerecord/lib/active_record/connection_adaptors/abstract/connection_specification.rb
class ActiveRecord::Base
# reconnect without disconnecting
- if Spawn::RAILS_3_x || Spawn::RAILS_2_2
+ if ::Spawn::RAILS_3_x || ::Spawn::RAILS_2_2
def self.spawn_reconnect(klass=self)
# keep ancestors' connection_handlers around to avoid them being garbage collected in the forked child
@@ancestor_connection_handlers ||= []
@@ -24,7 +24,7 @@ def self.spawn_reconnect(klass=self)
end
# this patch not needed on Rails 2.x and later
- if Spawn::RAILS_1_x
+ if ::Spawn::RAILS_1_x
# monkey patch to fix threading problems,
# see: http://dev.rubyonrails.org/ticket/7579
def self.clear_reloadable_connections!
@@ -58,15 +58,15 @@ class Unicorn::HttpServer
REQ = Unicorn::HttpRequest::REQ
alias_method :orig_process_client, :process_client
def process_client(client)
- Spawn.resources_to_close(client, REQ)
+ ::Spawn.resources_to_close(client, REQ)
orig_process_client(client)
end
end
elsif defined? Unicorn::HttpServer
class Unicorn::HttpServer
alias_method :orig_process_client, :process_client
def process_client(client)
- Spawn.resources_to_close(client, @request)
+ ::Spawn.resources_to_close(client, @request)
orig_process_client(client)
end
end
@@ -81,7 +81,7 @@ class Mongrel::HttpServer
# the socket that is being used so Spawn can close it upon forking
alias_method :orig_process_client, :process_client
def process_client(client)
- Spawn.resources_to_close(client, @socket)
+ ::Spawn.resources_to_close(client, @socket)
orig_process_client(client)
end
end
@@ -101,7 +101,7 @@ def process_client(client)
class Passenger::Railz::RequestHandler
alias_method :orig_process_request, :process_request
def process_request(headers, input, output)
- Spawn.resources_to_close(input, output)
+ ::Spawn.resources_to_close(input, output)
orig_process_request(headers, input, output)
end
end
@@ -112,7 +112,7 @@ def process_request(headers, input, output)
class PhusionPassenger::Railz::RequestHandler
alias_method :orig_process_request, :process_request
def process_request(headers, input, output)
- Spawn.resources_to_close(input, output)
+ ::Spawn.resources_to_close(input, output)
orig_process_request(headers, input, output)
end
end
@@ -123,7 +123,7 @@ def process_request(headers, input, output)
class PhusionPassenger::Rack::RequestHandler
alias_method :orig_process_request, :process_request
def process_request(headers, input, output)
- Spawn.resources_to_close(input, output)
+ ::Spawn.resources_to_close(input, output)
orig_process_request(headers, input, output)
end
end
View
@@ -1,7 +1,7 @@
require 'logger'
-module Spawn
- if defined? Rails
+class Spawn
+ if defined? ::Rails
RAILS_1_x = (::Rails::VERSION::MAJOR == 1) unless defined?(RAILS_1_x)
RAILS_2_2 = ((::Rails::VERSION::MAJOR == 2 && ::Rails::VERSION::MINOR >= 2)) unless defined?(RAILS_2_2)
RAILS_3_x = (::Rails::VERSION::MAJOR > 2) unless defined?(RAILS_3_x)
@@ -11,8 +11,6 @@ module Spawn
RAILS_3_x = nil
end
- require 'patches' unless defined?(Spawn.spawn_reconnect) # For some reason, the init.rb wasn't including the patches.
-
@@default_options = {
# default to forking (unless windows or jruby)
:method => ((RUBY_PLATFORM =~ /(win32|mingw32|java)/) ? :thread : :fork),
@@ -27,13 +25,8 @@ module Spawn
# forked children to kill on exit
@@punks = []
- # Make sure we have a logger and require our patches when we're included
- def self.included(klazz)
- # in some environments, logger isn't defined
- @@logger = defined?(Rails) ? Rails.logger : Logger.new(STDERR)
- require 'patches'
- end
-
+ # in some environments, logger isn't defined
+ @@logger = defined?(::Rails) ? ::Rails.logger : ::Logger.new(STDERR)
# Set the options to use every time spawn is called unless specified
# otherwise. For example, in your environment, do something like
@@ -78,31 +71,6 @@ def self.alive?(pid)
def self.kill_punks
@@punks.each do |punk|
if alive?(punk)
- @@logger.info "spawn> parent(#{Process.pid}) killing child(#{punk})"
- begin
- Process.kill("TERM", punk)
- rescue
- end
- end
- end
- @@punks = []
- end
- # register to kill marked children when parent exits
- at_exit {kill_punks}
-
- def self.alive?(pid)
- begin
- Process::kill 0, pid
- # if the process is alive then kill won't throw an exception
- true
- rescue Errno::ESRCH
- false
- end
- end
-
- def self.kill_punks
- @@punks.each do |punk|
- if alive?(punk)
@@logger.info "spawn> parent(#{Process.pid}) killing child(#{punk})" if @@logger
begin
Process.kill("TERM", punk)
@@ -113,7 +81,7 @@ def self.kill_punks
@@punks = []
end
# register to kill marked children when parent exits
- at_exit {kill_punks}
+ at_exit { Spawn.kill_punks }
# Spawns a long-running section of code and returns the ID of the spawned process.
# By default the process will be a forked process. To use threading, pass
@@ -157,7 +125,7 @@ def self.wait(sids = [])
ActiveRecord::Base.verify_active_connections!() if defined?(ActiveRecord)
end
- class SpawnId
+ class Id
attr_accessor :type
attr_accessor :handle
def initialize(t, h)
@@ -209,7 +177,7 @@ def self.fork_it(options)
# ensure log is flushed since we are using exit!
@@logger.flush if @@logger && @@logger.respond_to?(:flush)
# this child might also have children to kill if it called spawn
- Spawn::kill_punks
+ Spawn.kill_punks
# this form of exit doesn't call at_exit handlers
exit!(0)
end
@@ -220,15 +188,15 @@ def self.fork_it(options)
Process.detach(child)
# remove dead children from the target list to avoid memory leaks
- @@punks.delete_if {|punk| !Spawn::alive?(punk)}
+ @@punks.delete_if {|punk| !alive?(punk)}
# mark this child for death when this process dies
if options[:kill]
@@punks << child
@@logger.debug "spawn> death row = #{@@punks.inspect}" if @@logger
end
- return SpawnId.new(:fork, child)
+ return Spawn::Id.new(:fork, child)
end
def self.thread_it(options)
@@ -239,7 +207,7 @@ def self.thread_it(options)
yield
end
thr.priority = -options[:nice] if options[:nice]
- return SpawnId.new(:thread, thr)
+ return Spawn::Id.new(:thread, thr)
end
# In case we don't have rails, can't call opts.symbolize_keys
@@ -250,3 +218,6 @@ def self.symbolize_options(hash)
end
end
end
+
+# patches depends on Spawn so require it after the class
+require 'patches'

0 comments on commit 889ca52

Please sign in to comment.