Giter VIP home page Giter VIP logo

spawnling's Introduction

Spawnling

Gem Version Build Status Coverage Status Dependency Status Code Climate

News

2013-4-15 gem renamed from "spawn-block" (lame) to "spawnling" (awesome). Sadly the name "spawn" was taken before I got around to making this into a gem so I decided to give it a new name and a new home.

Also, now runs with ruby 1.9 (and later). Because ruby "stole" the name "spawn", this gem now has been redefined to use "Spawnling.new(&block)" instead of "spawn(&block)". Other than that nothing has changed in the basic usage. Read below for detailed usage.

Spawnling

This gem provides a 'Spawnling' class to easily fork OR thread long-running sections of code so that your application can return results to your users more quickly. It works by creating new database connections in ActiveRecord::Base for the spawned block so that you don't have to worry about database connections working, they just do.

The gem also patches ActiveRecord::Base to handle some known bugs when using threads if you prefer using the threaded model over forking.

Installation

The name of the gem is "spawnling" (unfortunately somebody took the name "spawn" before I was able to convert this to a gem).

git

If you want to live on the latest master branch, add this to your Gemfile,

gem 'spawnling', :git => 'https://github.com/tra/spawnling'

and use bundler to manage it (bundle install, bundle update).

rubygem

If you'd rather install from the latest gem,

gem 'spawnling', '~>2.1'

configure

Make sure that ActiveRecord reconnects to your database automatically when needed, for instance put

production/development:
  ...
  reconnect: true

into your config/database.yml.

Usage

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):

Spawnling.new do
  logger.info("I feel sleepy...")
  sleep 11
  logger.info("Time to wake up!")
end

If everything is working correctly, your controller should finish quickly then you'll see 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 Spawnling.wait(), like this:

spawns = []
N.times do |i|
  # spawn N blocks of code
  spawns << Spawnling.new do
    something(i)
  end
end
# wait for all N blocks of code to finish running
Spawnling.wait(spawns)

Options

The options you can pass to spawn are:

OptionValues
:method:fork, :thread, :yield
:niceinteger value 0-19, 19 = really nice
:killboolean value indicating whether the parent should kill the spawned process when it exits (only valid when :method => :fork)
:argvstring to override the process name
:detachboolean value indicating whether the parent should Process.detach the spawned processes. (defaults to true). You *must* Spawnling.wait or Process.wait if you use this. Changing this allows you to wait for the first child to exit instead of waiting for all of them.

Any option to spawn can be set as a default so that you don't have to pass them in to every call of spawn. To configure the spawn default options, add a line to your configuration file(s) like this:

  Spawnling::default_options :method => :thread

If you don't set any default options, the :method will default to :fork. To specify different values for different environments, add the default_options call to he appropriate environment file (development.rb, test.rb). For testing you can set the default :method to :yield so that the code is run inline.

  # in environment.rb
  Spawnling::default_options :method => :fork, :nice => 7
  # in test.rb, will override the environment.rb setting
  Spawnling::default_options :method => :yield

This allows you to set your production and development environments to use different methods according to your needs.

be nice

If you want your forked child to run at a lower priority than the parent process, pass in the :nice option like this:

Spawnling.new(:nice => 7) do
  do_something_nicely
end

fork me

By default, spawn will use the fork to spawn child processes. You can configure it to do threading either by telling the spawn method when you call it or by configuring your environment. For example, this is how you can tell spawn to use threading on the call,

Spawnling.new(:method => :thread) do
  something
end

When you use threaded spawning, make sure that your application is thread-safe. Rails can be switched to thread-safe mode with (not sure if this is needed anymore)

  # Enable threaded mode
  config.threadsafe!

in environments/your_environment.rb

kill or be killed

Depending on your application, you may want the children processes to go away when the parent process exits. By default spawn lets the children live after the parent dies. But you can tell it to kill the children by setting the :kill option to true.

a process by any other name

If you'd like to be able to identify which processes are spawned by looking at the output of ps then set the :argv option with a string of your choice. You should then be able to see this string as the process name when listing the running processes (ps).

For example, if you do something like this,

3.times do |i|
 Spawnling.new(:argv => "spawn -#{i}-") do
   something(i)
  end
end

then in the shell,

$ ps -ef | grep spawn
502  2645  2642   0   0:00.01 ttys002    0:00.02 spawn -0-
502  2646  2642   0   0:00.02 ttys002    0:00.02 spawn -1-
502  2647  2642   0   0:00.02 ttys002    0:00.03 spawn -2-

The length of the process name may be limited by your OS so you might want to experiment to see how long it can be (it may be limited by the length of the original process name).

Forking vs. Threading

There are several tradeoffs for using threading vs. forking. Forking was chosen as the default primarily because it requires no configuration to get it working out of the box.

Forking advantages:

  • more reliable? - the ActiveRecord code is generally not deemed to be thread-safe. Even though spawn attempts to patch known problems with the threaded implementation, there are no guarantees. Forking is heavier but should be fairly reliable.
  • keep running - this could also be a disadvantage, but you may find you want to fork off a process that could have a life longer than its parent. For example, maybe you want to restart your server without killing the spawned processes. We don't necessarily condone this (i.e. haven't tried it) but it's technically possible.
  • easier - forking works out of the box with spawn, threading requires you set allow_concurrency=true (for older versions of Rails). Also, beware of automatic reloading of classes in development mode (config.cache_classes = false).

Threading advantages:

  • less filling - threads take less resources... how much less? it depends. Some flavors of Unix are pretty efficient at forking so the threading advantage may not be as big as you think... but then again, maybe it's more than you think. ๐Ÿ˜‰
  • debugging - you can set breakpoints in your threads

Acknowledgements

This plugin was initially inspired by Scott Persinger's blog post on how to use fork in rails for background processing (link no longer available).

Further inspiration for the threading implementation came from Jonathon Rochkind's blog post on threading in rails.

Also thanks to all who have helped debug problems and suggest improvements including:

  • Ahmed Adam, Tristan Schneiter, Scott Haug, Andrew Garfield, Eugene Otto, Dan Sharp, Olivier Ruffin, Adrian Duyzer, Cyrille Labesse

  • Garry Tan, Matt Jankowski (Rails 2.2.x fixes), Mina Naguib (Rails 2.3.6 fix)

  • Tim Kadom, Mauricio Marcon Zaffari, Danial Pearce, Hongli Lai, Scott Wadden (passenger fixes)

  • Will Bryant, James Sanders (memcache fix)

  • David Kelso, Richard Hirner, Luke van der Hoeven (gemification and Rails 3 support)

  • 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 ([email protected]), see LICENSE

spawnling's People

Contributors

aclemons avatar adriand avatar adz avatar bikerduweb avatar carpeliam avatar corlinus avatar drsharp avatar ericstewart avatar jagthedrummer avatar jaygooby avatar joelvh avatar kuahyeow avatar lasserafn avatar mjankowski avatar mnoack avatar plukevdh avatar qen avatar seandilda avatar ssinghi avatar tkadom avatar tra avatar wellmatchdev avatar willbryant avatar yinhm avatar zaius avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spawnling's Issues

undefined method `fields` for nil

I know it's bad etiquette to submit a bug report without a test case, but I'm not sure how to reproduce this in a small test case. In my app, using spawnling from inside a controller action occasionally causes these exceptions to be thrown spuriously:

NoMethodError: undefined method `fields' for nil:NilClass

This is happening on a call to model.reload.

I suspect there may be some file descriptor left open in the child process that may need to be closed.

undefined method `alive?' for #<Spawn:0x007f8bb44ff758 @type=:fork>

Hey, I have a Spawn.new block in my controller, but when I call it multiple times with all the same information, Spawn throws an exception (though it still appears to successfully fork the process and execute).

Do you know what might be going on here?

code in question

Spawn.new(:method => :fork, :kill => true, :nice => 10, :argv => 'pdf generation fork') do
            @my_obj.pdf_generator
 end

Rails 4.x compatibility

I just had the issue that on windows there only is threading and in lib/spawnling.rb in sel.frun there is a check for "allow_concurrency?" that fails and then the line
@@logger.error("spawn(:method=>:thread) only allowed when allow_concurrency=true")
fails because @@logger isn't there. So all i got was:

D:/Informer/ruby/lib/ruby/gems/2.0.0/gems/spawnling-2.1.3/lib/spawnling.rb:112:in run': undefined methoderror' for nil:NilClass (NoMethodError)

Then clean_connections failed at "verify_active_conenctions!" strangely so because i'd have expected the "respond_to?" check catching that.

I quickly monkey patched it this way:

class Spawnling
def self.allow_concurrency?
true
end
def self.clean_connections
ActiveRecord::Base.clear_active_connections!
end
end

But i guess you should check and set allow_concurreny true if rails >= 4.0.0.
And the clean_conenctions should somehow call the ConnecteionPool Reaper but i haven't yet figured out myself how to do that.

Usable with MongoDB / mongoid?

Hi, is the dependency to ActiveRecord necessary or could you maybe change the behavior so that i could use it with MongoDB or even without any db in the background at all?

Thanks for that thing :), Cheers

Spawn should be usable anywhere

Currently spawn only works for Models, Controllers and Observers.

But let's say I want to use spawn within a paperclip processor, well it won't work.

API changed?

I've just ran an bundle update (I probably shouldn't have but that's an other discussion ;) and I can't get spawnling to work anymore.

Taking the basic example from the readme:

Spawnling.new do
  logger.info("I feel sleepy...")
  sleep 11
  logger.info("Time to wake up!")
end
Must give block of code to be spawned (RuntimeError)
    from ~/.rvm/gems/ruby-2.0.0-p353@newbysh/gems/spawnling-2.1.2/lib/spawnling.rb:94:in `initialize'

I've tried to look at the code but I'm seriously confused how it's suppose to work at this point. I appreciate any tips anybody could give.

Cannot use :method => :thread

The README says use :method => :thread, but I have to use :method => :threads instead.

irb(main):016:0> s= Spawnling.new(:method=>:thread) do puts 'hi' end
NoMethodError: undefined method `error' for nil:NilClass
    from (irb):16:in `new'
    from (irb):16
    from <root>/bin/rails:8:in `<top (required)>'
    from -e:1:in `<main>'
irb(main):021:0> Spawnling.new(:method=>:threads) do puts 'hi' end
=> #<Spawnling:0x007f38f27348a8 @type=:fork, @handle=17866>
irb(main):022:0> hi

I'm in RoR:

[devpc ~]$ ruby --version
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
[devpc ~]$ rails --version
Rails 4.2.4

spawning does not work in models

spawn is not defined in my models. is there a reason why i would not want to spawn a process in my model? how can i make the module accessible?

Convert to a gem

The latest (master) codebase works with Rails 2.3.10, but it needs some love to convert it into a gem. Could you please do the changes and release it? I will fork the latest version (as of today) and send you a pull request for the same.

Broken under rails 2.3.6, 2.3.7 and 2.3.8 (with fix)

Commit http://github.com/rails/rails/commit/841c01fa0fa92aa6e3c2e5029444a9cbb4f161f3 in rails broken spawn, which makes it behave weird in rails 2.3.6 onwards

Below is a simple fix:
--- a/vendor/plugins/spawn/lib/patches.rb
+++ b/vendor/plugins/spawn/lib/patches.rb
@@ -4,8 +4,13 @@ class ActiveRecord::Base
if Spawn::RAILS_2_2
def self.spawn_reconnect(klass=self)
# keep ancestors' connection_handlers around to avoid them being garbage collected
- (@@ancestor_connection_handlers ||= []) << @@connection_handler
- @@connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
+ if self.respond_to?(:connection_handler)
+ (@@ancestor_connection_handlers ||= []) << self.connection_handler
+ self.connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
+ else
+ (@@ancestor_connection_handlers ||= []) << @@connection_handler
+ @connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
+ end
establish_connection
end
else

Gem in combination with rails 3.2.19 complains about uninitialized constant RAILS_CACHE

Running rails console gives:

/var/lib/gems/1.9.1/gems/railties-3.2.19/lib/rails.rb:90:in cache': uninitialized constant RAILS_CACHE (NameError) from /var/lib/gems/1.9.1/gems/spawnling-2.1.5/lib/patches.rb:138:in<top (required)>'
from /var/lib/gems/1.9.1/gems/spawnling-2.1.5/lib/spawnling.rb:250:in require' from /var/lib/gems/1.9.1/gems/spawnling-2.1.5/lib/spawnling.rb:250:in<top (required)>'
from /var/lib/gems/1.9.1/gems/bundler-1.3.5/lib/bundler/runtime.rb:72:in require' from /var/lib/gems/1.9.1/gems/bundler-1.3.5/lib/bundler/runtime.rb:72:inblock (2 levels) in require'
from /var/lib/gems/1.9.1/gems/bundler-1.3.5/lib/bundler/runtime.rb:70:in each' from /var/lib/gems/1.9.1/gems/bundler-1.3.5/lib/bundler/runtime.rb:70:inblock in require'
from /var/lib/gems/1.9.1/gems/bundler-1.3.5/lib/bundler/runtime.rb:59:in each' from /var/lib/gems/1.9.1/gems/bundler-1.3.5/lib/bundler/runtime.rb:59:inrequire'
from /var/lib/gems/1.9.1/gems/bundler-1.3.5/lib/bundler.rb:132:in require' from /export/www/myapp/ruby/config/application.rb:13:in<top (required)>'
from /var/lib/gems/1.9.1/gems/railties-3.2.19/lib/rails/commands.rb:39:in require' from /var/lib/gems/1.9.1/gems/railties-3.2.19/lib/rails/commands.rb:39:in<top (required)>'
from script/rails:6:in require' from script/rails:6:in

'

Temp solution for Rails 3 is to downgrade to rails 3.2.18 and spawnling 2.1.1

How to get rid of zombie processes?

I spawning new processes in rails controller, I don't want to block the controller, so I don't wait() them. But this create zombie processes.

Is this a problem? How to get rid of zombie processes?

Wrong options logic in Spawn#spawn

Hi,

Line 42 says: "setting options[:method] will override configured value in @@method"

The logic says no, wouldn't switching

  • if options[:method] == :yield || @@method == :yield

to

  • if options[:method] == :yield || (options[:method] == nil && @@method == :yield)

be better?

Cyrille

'verify_active_connections!' is no longer available in Rails 4

Using Spawnling.wait() causes a error when trying to import some data to database:

NoMethodError: undefined method `verify_active_connections!' for ActiveRecord::Base:Class
    from /Users/user/.rvm/gems/ruby-2.1.0/gems/activerecord-4.0.4/lib/active_record/dynamic_matchers.rb:22:in `method_missing'
    from /Users/user/.rvm/gems/ruby-2.1.0/gems/spawnling-2.1.1/lib/spawnling.rb:131:in `wait'
    from /*** hidden ***.rb:104:in `import!'
    from /*** hidden ***.rb:147:in `import!'
    from /*** hidden ***.rb:41:in `ftp_import!'
    from (irb):1
    from /Users/user/.rvm/gems/ruby-2.1.0/gems/railties-4.0.4/lib/rails/commands/console.rb:90:in `start'
    from /Users/user/.rvm/gems/ruby-2.1.0/gems/railties-4.0.4/lib/rails/commands/console.rb:9:in `start'
    from /Users/user/.rvm/gems/ruby-2.1.0/gems/railties-4.0.4/lib/rails/commands.rb:62:in `<top (required)>'
    from bin/rails:4:in `require'
    from bin/rails:4:in `<main>'

Priority for threads

I think it would be nice to be able to set the priority for threads just like you can do for processes.
It is possible using "thr.priority= integer", like below.

The value of the integer is however different compared to process, so therefore it might be better to use something else than the :nice option.

Regards Mats

def thread_it(options)
  # clean up stale connections from previous threads
  ActiveRecord::Base.verify_active_connections!()
  thr = Thread.new do
    # run the long-running code block
    yield
  end
  thr.priority = options[:nice] if options[:nice]
  return SpawnId.new(:thread, thr)
end

Problem with log rotation

I've had some very weird crashes while using spawn. I've tested high and low, and all I could find out is that it seems related to log rotation.
A consistent behavior I experienced: when the log rotates, either the parent or the child process becomes unable to write on the new logfile (maybe because of a stale file handler?).

Sometimes this seems connected to the crash, sometimes not. Anyway, this is the backtrace:
Read error: #<NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each>
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/utils.rb:196:in initialize' /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/content_length.rb:14:innew'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/content_length.rb:14:in call' /Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/chunked.rb:15:incall'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/handler/mongrel.rb:64:in process' /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:159:inorig_process_client'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in each' /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:inorig_process_client'
/Users/simbul/Sites/spawnlog/vendor/plugins/spawn/lib/patches.rb:61:in process_client' /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:inrun'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in initialize' /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:innew'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in run' /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:ininitialize'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in new' /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:inrun'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/handler/mongrel.rb:34:in run' /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/commands/server.rb:111 /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:ingem_original_require'
/Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
script/server:3

I'm willing to help with further testing, if needed. At the moment, I don't seem able to make head nor tail of it.

Spawning within threads throws exception

Using fork method for spawn. I have a daemon which spawns jobs on request, but I wanted to limit concurrency, so created 3 worker threads to do the spawning within. I then ran into this race condition, and extracted the failure into the simplified code below. Any ideas? I was unable to figure out what is going wrong. Its probably something weird in my environment as I can't duplicate it in a fresh rails app

foo.rb:
class SpawnInit
include Spawn
def initialize
sid = spawn do
puts "Spawn initialized"
end
wait([sid])
end
end

threads = []
threads << Thread.new { SpawnInit.new }
threads << Thread.new { SpawnInit.new }
threads.each {|t| t.join}

within RAILS_ROOT

./script/runner foo.rb

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/monitor.rb:285:in stop': stopping only thread (ThreadError) note: use sleep to stop forever from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/monitor.rb:285:inmon_acquire'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/monitor.rb:214:in mon_enter' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/monitor.rb:240:insynchronize'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/logger.rb:496:in write' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/logger.rb:326:inadd'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/logger.rb:374:in info' from /Users/mconway/Documents/eclipse/workspace/sml/vendor/plugins/spawn/lib/spawn.rb:118:infork_it'
from /Users/mconway/Documents/eclipse/workspace/sml/vendor/plugins/spawn/lib/spawn.rb:90:in fork' ... 9 levels... from /Users/mconway/Documents/eclipse/workspace/sml/vendor/rails/railties/lib/commands/runner.rb:45 from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:ingem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
from ./script/runner:3
Spawn initialized

"Executing in another thread" error under Rails 3 and Oci8

I'm running the edge branch of spawn under rails 3, connecting to an oracle database (using ruby-oci8 gem)

Spawn works most of the time, but will often raise an error:

     28:           - precache_portlet_details(:portlet => portlet, :id => record.id)   
  ruby-oci8 (2.0.4) lib/oci8/oci8.rb:287:in`__execute'
  ruby-oci8 (2.0.4) lib/oci8/oci8.rb:287:in `exec'
  ruby-oci8 (2.0.4) lib/oci8/oci8.rb:115:in`exec'
  app/helpers/application_helper.rb:14:in `precache_portlet_details'

The precache_portlet_details method consists of a simple call to render a partial via spawn:

    spawn(:method => :thread)  do
       controller.display_details(:portlet => opts[:portlet],  :cache_only => true)
    end
  end

If I add a sleep(1) in the spawned method, it runs fine 80% of the time, and if I add a sleep(2) it seems to run fine 100% of the time. I can use the sleep(2) as a work around, but would prefer not to....

I'm unable to try spawn using :method => :fork, as I cannot get the spawned block to connect to the database.

Typo in example code

The readme has typos in this code example:

# in environment.rb
Spawn::method :method => :fork, :nice => 7
# in test.rb, will override the environment.rb setting
Spawn::method :method => :yield

On both lines, Spawn::method :method => ... should read Spawn::default_options :method => ...

uninitialized class variable @@logger in Spawn (NameError)

After following the directions in the README I'm getting this error when I try to do anything (start a console or server, run rake, etc...):

lib/spawn.rb:42:in `default_options': uninitialized class variable @@logger in Spawn (NameError)

This is my config line in environments/development.rb
Spawn::default_options({ :method => :thread })

This same config was working for me with the older version, but after upgrading to 'edge' I've started to see the error. I think it has something to do with the self.included method that was introduced in this commit:

jagthedrummer@134a0c9

I can add "include Spawn" right before that config option and everything works just like it should. But that really shouldn't be needed if Spawn is supposed to function as a gem. Right?

Is there any reason that the creation of the logger and the inclusion of the patches file needs to be wrapped in the self.included function? It seems like it should work just inline. Maybe I'll test that out...

Thanks,
Jeremy

I need small usability fix, hope you like it :)

Hi, thank you for the great plugin :). I'm working now on server side part of flash game. I needed some logic to repeat every few seconds. I decided to move this logick into initializer (to run only once, forever with delay). Here is what i got

require 'spawn'

class Spawner
  extend Spawn
end

Spawner::spawn do
  while true
    # Doing my stuff
    sleep(5)
   end
end

And here is what i would like to have

Spawner::spawn do
  while true
    # Doing my stuff
    sleep(5)
  end
end

The problem is that Spawn is a module and we cannot use it in "Spawn::spawn do ..." way, so i needed to extend some class with this module and using that class. I think moving something like

class Spawner
  extend Spawn
end

into plugin code would be great idea.

Also plugin will need some documentation update. When i searched similar functionality (1 process for application that runs forever with delay) i have not found exactly what i need. This feature is not described anywhere.

passenger (2.2.1) not spawning

In development mode using passenger 2.2.1 spawn isn't spawning properly, rather my long running tasks are executing in the same process (i.e. when I upload a file to be processed, the browser does not get redirected until after the file has been processed).
I'm running passenger 2.2.1, my rails environment is:

Ruby version 1.8.7 (i686-darwin9)
RubyGems version 1.3.2
Rack version 1.0 bundled
Rails version 2.3.2
Active Record version 2.3.2
Action Pack version 2.3.2
Active Resource version 2.3.2
Action Mailer version 2.3.2
Active Support version 2.3.2
Edge Rails revision unknown
Application root XXX
Environment development

In my controller I'm calling spawn like so:

spawn(:nice => 7) do
method_call()
end
do stuff ...

I have the latest version of the spawn plugin installed as well.
Everything was working fine when I was using mongrel directly...

Do you have any ideas on what I should try?

(I have just tried this on a production setup and it is still happening...)
passenger (2.0.6)

connection_handler change in Rails 2.3.8

I had to patch the Spawn plugin, since it didn't worked anymore with Rails 2.3.8. After some debug, I noticed that the connection_handler is accessed in another way. Therefore I had to patch the plugin:

--- patches.rb  (revision 54)
+++ patches.rb  (working copy)
@@ -1,9 +1,16 @@
 # see activerecord/lib/active_record/connection_adaptors/abstract/connection_specification.rb
 class ActiveRecord::Base
   # reconnect without disconnecting
-  if Spawn::RAILS_2_2
+  if Spawn::RAILS_2_3_8
     def self.spawn_reconnect(klass=self)
       # keep ancestors' connection_handlers around to avoid them being garbage collected
+      (@@ancestor_connection_handlers ||= []) << self.connection_handler
+      self.connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
+      establish_connection
+    end
+  elsif Spawn::RAILS_2_2
+    def self.spawn_reconnect(klass=self)
+      # keep ancestors' connection_handlers around to avoid them being garbage collected
       (@@ancestor_connection_handlers ||= []) << @@connection_handler
       @@connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
       establish_connection

--- spawn.rb    (revision 54)
+++ spawn.rb    (working copy)
@@ -1,6 +1,7 @@
 module Spawn
   RAILS_1_x = (::Rails::VERSION::MAJOR == 1) unless defined?(RAILS_1_x)
   RAILS_2_2 = (::Rails::VERSION::MAJOR > 2 || (::Rails::VERSION::MAJOR == 2 && ::Rails::VERSION::MINOR >= 2)) unless defined?(RAILS_2_2)
+  RAILS_2_3_8 = (::Rails::VERSION::MAJOR > 2 || (::Rails::VERSION::MAJOR == 2 && ::Rails::VERSION::MINOR >= 3 && ::Rails::VERSION::TINY >= 8)) unless defined?(RAILS_2_3_8)

Spawn needs a new name

Spawn is such a good name that Ruby 1.9 decided to steal it (damn you Matz!). I'm not inclined to monkey-patch ruby so it's probably time to come up with a new name. Here's some ideas:

spelling variations

spon - nice & short
spown - spawn has been p0wn3d
spawnd - spawn daemon, just add a 'd'
spawned - past tense
spark - spawn/fork
spork - spawn/fork - unfortunately already a gem with this name

synonyms

beget - parent process begets child process
branch - branching metaphor, too generic?
hatch - children start out as eggs
sow - like a seed
cleave - with a knife
dispatch - send it away
launch - off you go!

miscellaneous

khan - after Genghis Khan who was a prolific spawner of children
drone - a worker bee process

Feel free to give your 2 cents and pick your top 3 favorites.

master branch throws an exception if you're not using memcache

When trying to use the master branch, I get this error when running rails server (rails 3.2):

You don't have memcache-client installed in your application. Please add it to your Gemfile and run bundle install

I locally reverted 5cc9610
and this problem went away. Please consider reverting/fixing that patch.

Can't allocate memory

We seeing a lot of the following types of errors:

Errno::ENOMEM: Cannot allocate memory - fork(2)

[GEM_ROOT]/bundler/gems/spawn-beaf7937cae9/lib/spawn.rb:165:in fork' [GEM_ROOT]/bundler/gems/spawn-beaf7937cae9/lib/spawn.rb:165:infork_it'
[GEM_ROOT]/bundler/gems/spawn-beaf7937cae9/lib/spawn.rb:130:in `spawn_block'

They are occurring even though at the time 50% of our 4GB RAM is being utilized. Our environment is Ruby 1.9.2, Rails 3.1.1, Nginx 1.0.6 and Passenger 3.0.6.

Release a gem?

I think the most recent release was in 2010, but now there are some significant fixes that haven't been rolled out yet (including making ActiveRecord optional). Could you possibly cut a new gem?

Need to preserve all connection pools

Rails supports multiple databases among models via Model.establish_connection('other_database'), and spawn resets these connection pools:

Ex, we put delayed jobs in a different database:

ActiveRecord::Base.connection_handler.connection_pools.keys # => [ "Delayed::Job", "ActiveRecord::Base"]

spawn { ActiveRecord::Base.connection_handler.connection_pools.keys } # => ["ActiveRecord::Base"]

I'm currently hacking around this, but thought I'd make a ticket.

Support for Windows platform

In order for spawn to work with InstantRails on Windows or in a cygwin environment, spawn must also check for the "mingw32" ruby platform. Since the change is so small, I'll just paste the diff below, rather than forking and sending a pull request.

diff --git a/lib/spawn.rb b/lib/spawn.rb
index f60ede7..8b6afaa 100644
--- a/lib/spawn.rb
+++ b/lib/spawn.rb
@@ -4,7 +4,7 @@ module Spawn

   @@default_options = {
     # default to forking (unless windows or jruby)
-    :method => ((RUBY_PLATFORM =~ /(win32|java)/) ? :thread : :fork),
+    :method => ((RUBY_PLATFORM =~ /(win32|mingw32|java)/) ? :thread : :fork),
     :nice   => nil,
     :kill   => false,
     :argv   => nil

Question: Timeframe for releasing current changes

Hi,

Wondering if you had a schedule in mind for releasing master to RubyGems? I looked at the diffs and there's not much I would be worried about but I do like to keep up-to-date with critical infrastructure such as Spawling.

Thanks,

Simon

Segfaults under rails 3

Plugin segfaults under rails 3. Not sure of the source. Seems to be when interacting with the new ActiveRecord. Working on a fix, but don't have much background with this plugin's code. Will update at some point in the future.

missing dependencies

I just installed this gem and tried the sample code. I get the following error

You don't have dalli installed in your application. Please add it to your Gemfile and run bundle install
rake aborted!
LoadError: cannot load such file -- dalli

So I was wondering if this gem is supposed to work without dalli ? Because dalli on the other hand needs memcached, and I dont want to include two more gems because of this one. Actually it should mention the dependencies.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.