Class: Spawnling
- Inherits:
-
Object
- Object
- Spawnling
- Defined in:
- lib/spawnling.rb,
lib/spawnling/version.rb
Constant Summary collapse
- RAILS_1_x =
nil
- RAILS_2_2 =
nil
- RAILS_3_x =
nil
- VERSION =
'2.1.4'
- @@default_options =
{ # default to forking (unless windows or jruby) :method => ((RUBY_PLATFORM =~ /(win32|mingw32|java)/) ? :thread : :fork), :nice => nil, :kill => false, :argv => nil }
- @@resources =
things to close in child process
[]
- @@punks =
forked children to kill on exit
[]
- @@logger =
in some environments, logger isn’t defined
defined?(::Rails) ? ::Rails.logger : ::Logger.new(STDERR)
Instance Attribute Summary collapse
-
#handle ⇒ Object
Returns the value of attribute handle.
-
#type ⇒ Object
Returns the value of attribute type.
Class Method Summary collapse
- .alive?(pid) ⇒ Boolean
- .allow_concurrency? ⇒ Boolean
-
.close_resources ⇒ Object
close all the resources added by calls to resource_to_close.
-
.default_options(options = {}) ⇒ Object
Set the options to use every time spawn is called unless specified otherwise.
- .kill_punks ⇒ Object
- .logger=(logger) ⇒ Object
-
.resources_to_close(*resources) ⇒ Object
set the resources to disconnect from in the child process (when forking).
- .run(opts = {}, &block) ⇒ Object
- .wait(sids = []) ⇒ Object
Instance Method Summary collapse
-
#initialize(opts = {}, &block) ⇒ Spawnling
constructor
Spawns a long-running section of code and returns the ID of the spawned process.
Constructor Details
#initialize(opts = {}, &block) ⇒ Spawnling
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 :method => :thread or override the default behavior in the environment by setting ‘Spawnling::method :thread’.
97 98 99 |
# File 'lib/spawnling.rb', line 97 def initialize(opts = {}, &block) self.class.run(opts, &block) end |
Instance Attribute Details
#handle ⇒ Object
Returns the value of attribute handle.
36 37 38 |
# File 'lib/spawnling.rb', line 36 def handle @handle end |
#type ⇒ Object
Returns the value of attribute type.
35 36 37 |
# File 'lib/spawnling.rb', line 35 def type @type end |
Class Method Details
.alive?(pid) ⇒ Boolean
68 69 70 71 72 73 74 75 76 |
# File 'lib/spawnling.rb', line 68 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 |
.allow_concurrency? ⇒ Boolean
124 125 126 127 128 129 130 131 132 133 |
# File 'lib/spawnling.rb', line 124 def self.allow_concurrency? return true if RAILS_2_2 if defined?(ActiveRecord) && ActiveRecord::Base.respond_to?(:allow_concurrency) ActiveRecord::Base.allow_concurrency elsif defined?(Rails) Rails.application.config.allow_concurrency else true # assume user knows what they are doing end end |
.close_resources ⇒ Object
close all the resources added by calls to resource_to_close
60 61 62 63 64 65 66 |
# File 'lib/spawnling.rb', line 60 def self.close_resources @@resources.each do |resource| resource.close if resource && resource.respond_to?(:close) && !resource.closed? end # in case somebody spawns recursively @@resources.clear end |
.default_options(options = {}) ⇒ Object
Set the options to use every time spawn is called unless specified otherwise. For example, in your environment, do something like this:
Spawnling:: = {:nice => 5}
to default to using the :nice option with a value of 5 on every call. Valid options are:
:method => (:thread | :fork | :yield)
:nice => nice value of the forked process
:kill => whether or not the parent process will kill the
spawned child process when the parent exits
:argv => changes name of the spawned process as seen in ps
49 50 51 52 |
# File 'lib/spawnling.rb', line 49 def self.( = {}) @@default_options.merge!() @@logger.info "spawn> default options = #{.inspect}" if @@logger end |
.kill_punks ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/spawnling.rb', line 78 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) rescue end end end @@punks = [] end |
.logger=(logger) ⇒ Object
31 32 33 |
# File 'lib/spawnling.rb', line 31 def self.logger=(logger) @@logger = logger end |
.resources_to_close(*resources) ⇒ Object
set the resources to disconnect from in the child process (when forking)
55 56 57 |
# File 'lib/spawnling.rb', line 55 def self.resources_to_close(*resources) @@resources = resources end |
.run(opts = {}, &block) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/spawnling.rb', line 101 def self.run(opts = {}, &block) raise "Must give block of code to be spawned" unless block_given? = @@default_options.merge((opts)) # setting options[:method] will override configured value in default_options[:method] if [:method] == :yield yield elsif [:method].respond_to?(:call) [:method].call(proc { yield }) elsif [:method] == :thread # for versions before 2.2, check for allow_concurrency if allow_concurrency? @type = :thread @handle = thread_it() { yield } else @@logger.error("spawn(:method=>:thread) only allowed when allow_concurrency=true") raise "spawn requires config.active_record.allow_concurrency=true when used with :method=>:thread" end else @type = :fork @handle = fork_it() { yield } end end |
.wait(sids = []) ⇒ Object
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/spawnling.rb', line 135 def self.wait(sids = []) # wait for all threads and/or forks (if a single sid passed in, convert to array first) Array(sids).each do |sid| if sid.type == :thread sid.handle.join() else begin Process.wait(sid.handle) rescue # if the process is already done, ignore the error end end end # clean up connections from expired threads ActiveRecord::Base.verify_active_connections!() if defined?(ActiveRecord) end |