Giter Club home page Giter Club logo

girl_friday's Introduction

Please use Brandon Hilkert's sucker_punch instead of girl_friday now.

girl_friday is a Ruby library for performing asynchronous tasks. Often times you don't want to block a web response by performing some task, like sending an email, so you can just use this gem to perform it in the background. It works with any Ruby application, including Rails 3 applications.

Installation

We recommend using JRuby 1.6+ or Rubinius 2.0+ with girl_friday. Both are excellent options for executing Ruby these days.

gem install girl_friday

girl_friday does not support Ruby 1.8 (MRI) because of its lack of native threading. Ruby 1.9.3 will work reasonably well if you use gems that release the GIL for network I/O (mysql2 is a good example of this, do not use the original mysql gem).

Usage

Put girl_friday in your Gemfile:

gem 'girl_friday'

In your Rails app, create a config/initializers/girl_friday.rb which defines your queues:

EMAIL_QUEUE = GirlFriday::WorkQueue.new(:user_email, :size => 3) do |msg|
  UserMailer.registration_email(msg).deliver
end

IMAGE_QUEUE = GirlFriday::WorkQueue.new(:image_crawler, :size => 7) do |msg|
  ImageCrawler.process(msg)
end

:size is the number of workers to spin up and defaults to 5. Keep in mind, ActiveRecord defaults to a connection pool size of 5 so if your workers are accessing the database you'll want to ensure that the connection pool is large enough by modifying config/database.yml.

In order to use the Redis backend, you must use a connection pool to share a set of Redis connections with other threads and GirlFriday queues using the connection_pool gem:

require 'connection_pool'

redis_pool = ConnectionPool.new(:size => 5, :timeout => 5) { Redis.new }

CLEAN_FILTER_QUEUE = GirlFriday::WorkQueue.new(:clean_filter, :store => GirlFriday::Store::Redis, :store_config => { :pool => redis_pool }) do |msg|
  Filter.clean(msg)
end

In your controller action or model, you can call #push(msg)

EMAIL_QUEUE.push(:email => @user.email, :name => @user.name)

The msg parameter to push is just a Hash whose contents are completely up to you.

Your message processing block should not access any instance data or variables outside of the block. That's shared mutable state and dangerous to touch! I also strongly recommend your queue processor block be VERY short, ideally just a method call or two. You can unit test those methods easily but not the processor block itself.

You can call GirlFriday::WorkQueue.immediate! to process jobs immediately, which is helpful when testing. GirlFriday::WorkQueue.queue! will revert this & jobs will be processed by actors.

Queues are not garbage collected until they are shutdown, even if you have no reference to them. Make sure you call WorkQueue#shutdown if you are dynamically creating them so you don't leak memory. GirlFriday.shutdown! will shut down all running queues in the process.

More Detail

Please see the girl_friday wiki for more detail and advanced options and tuning. You'll find details on queue persistence with Redis, implementing clean shutdown, querying runtime metrics and SO MUCH MORE!

From wikipedia:

The term Man Friday has become an idiom, still in mainstream usage, to describe an especially faithful servant or one's best servant or right-hand man. The female equivalent is Girl Friday. The title of the movie His Girl Friday alludes to it and may have popularized it.

Thanks

Carbon Five, I wrote and maintained girl_friday on their clock.

This gem contains a copy of the Rubinius Actor API, modified to work on any Ruby VM. Thanks to Evan Phoenix, MenTaLguY and the Rubinius project for permission to use and distribute this code.

Author

Mike Perham, @mperham, mikeperham.com

girl_friday's People

Contributors

jc00ke avatar joenoon avatar mperham avatar pointlessone avatar ryanlecompte avatar sanemat avatar sferik avatar shime avatar vaudoc avatar xaviershay 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  avatar  avatar

girl_friday's Issues

girl_friday integration with mod rails (passenger)

girl_friday works with mod rails (passenger) version 3.0.9; however to make it work you must change the spawn method to conservative (note: same thing with eventmachine) in the /etc/httpd/conf.d/myproject.conf

PassengerSpawnMethod conservative

this is not a bug; however, it would be nice to have this documented for the next guy :-)

Repeating Tasks

I have a sinatra app and would like to create a simple in-process monitor that runs in a repeating task:

while true
  sleep 1000
  check_something_and_send_an_alert_if_it_fails
end

Is girl_friday a good solution for persistent/repeating tasks like this?
Is there any example code that shows the best way to do repeating tasks with girl_friday?

tx, Andy

With Hoptoad installed you get no error logging in development

  8     def self.default
  9       defined?(HoptoadNotifier) ? Hoptoad : self
 10     end

In development Hoptoad doesn't send exceptions anywhere. This means that if you have the hoptoad gem in your Gemfile then girl_friday doesn't show development exceptions anywhere either.

Instructions for use on Heroku

On the main page for Girl Friday (http://mperham.github.com/girl_friday/) it mentions that for info on how to use Girl Friday on Heroku to the look on the github wiki pages. After quite a thorough search on the github wiki I can't find any reference to Heroku. Please could you point me in the right direction.

Thanks, Anthony

superclass mismatch for class Actor

Hey,

I'm getting this error

superclass mismatch for class Actor

It happens when I'm trying to use my Actor class (base on AR). It seems like this gem is defining an Actor class on the top level, and that conflicts with the class I have.

I there a way to help it? The gem provides the GirlFriday namespace, so Actor should probably be defined in that context, IMHO

Thanks

Work not being done in production

I've just tested sending mail using girl_friday in development and everything works great, I deployed to production and it isn't working (Ruby 1.9.2, Unicorn 3.5.0, Rails 3.0.7). Strangely, it works fine in production from the console but in the HTTP request it isn't doing anything. I've debugged it all the way to the point that it gets enqueued and that seems to be correct, but debug in the GirlFriday::WorkQueue do |msg| block isn't printed. Very strange... any ideas?

Race condition in test_should_allow_graceful_shutdown

In TestGirlFridayQueue#test_should_allow_graceful_shutdown, I consistently get the following when running with --seed=1415:

  1) Failure:
test_should_allow_graceful_shutdown(TestGirlFridayQueue) [/Users/woody/girl_friday/test/test_girl_friday_queue.rb:185]:
Expected: 1
  Actual: 4

However, if I add sleep 0.1 to line 184 of the test (right before assert_equal 1, GirlFriday.queues.size), I get consistently passing tests.

If I'm the only one that can repro it, I'm the only one that can fix it, but do you have any ideas of where to start? I'm willing to look in to it, but don't have time for a huge investment.

MacBookPro8,1 (13'' Intel Core i7, 2.7ghz) running ruby 1.9.3-p0.

Rails 3 with girl_friday server

In the wiki you say that we can add the server to a Rails 3 app by adding stuff to config.ru. Any reason why you don't recomment mounting if in routes.rb? Feels alot cleaner. Here's how I mount it in a Rails 3 app using routes.rb

  require 'girl_friday/server'
  mount GirlFriday::Server, at: '/girl_friday'

Missing License?

I have not managed to find the project's license. A COPYING or LICENSE file, or inclusion of the license in the README, would probably be a goodidea.

no such file to load -- sinatra/base (LoadError)

I added the following to my config.ru file:

require 'girl_friday/server'

run Rack::URLMap.new "/" => TestApp::Application, "/girl_friday" => GirlFriday::Server.new

when I start my app I get the following error:

/Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:239:in require': no such file to load -- sinatra/base (LoadError) from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:239:inblock in require'
from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:225:in block in load_dependency' from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:596:innew_constants_in'
from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:225:in load_dependency' from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:239:inrequire'
from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/girl_friday-0.9.4/lib/girl_friday/server.rb:1:in <top (required)>' from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:239:inrequire'
from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:239:in block in require' from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:225:inblock in load_dependency'
from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:596:in new_constants_in' from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:225:inload_dependency'
from /Users/fredrik/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.9/lib/active_support/dependencies.rb:239:in require' from /Users/fredrik/Projects/test-app/config.ru:2:inblock in

'

Rename this gem.

Shit like this is what's keeping women away from Ruby and computer science.

"can't create Thread (11)" errors using GirlFriday::Batch

I got this error on Heroku when using GirlFriday::Batch:

can't create Thread (11)
vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.4/lib/girl_friday/actor.rb:65:in initialize' vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.4/lib/girl_friday/actor.rb:65:innew'
vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.4/lib/girl_friday/actor.rb:65:in spawn' vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.4/lib/girl_friday/work_queue.rb:133:instart'
vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.4/lib/girl_friday/work_queue.rb:21:in initialize' vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.4/lib/girl_friday/batch.rb:16:innew'
vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.4/lib/girl_friday/batch.rb:16:in `initialize'

any ideas?

rails app crashes running under jruby and thin

My web app running under jruby 1.6.3 and thin seems to crash and java thread dump file has some reference to girl_friday as shown below:

Stack: [0xb4832000,0xb48b3000], sp=0xb48b1b74, free space=510k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0x6eef1] markOopDesc::must_be_preserved_with_bias(oopDesc) const
+0x21
V [libjvm.so+0x32a313] klassKlass::oop_follow_contents(oopDesc)+0x2a3
V [libjvm.so+0x6e5aa] arrayKlassKlass::oop_follow_contents(oopDesc)+0x16a
V [libjvm.so+0x37c55b] objArrayKlassKlass::oop_follow_contents(oopDesc)+0xdb
V [libjvm.so+0x34212d] MarkSweep::follow_stack()+0x3d
V [libjvm.so+0x342bc8] void MarkSweep::follow_root(oopDesc*)+0x68
V [libjvm.so+0x444a2c] Universe::oops_do(OopClosure, bool)+0x1c
V [libjvm.so+0x3ccc62] SharedHeap::process_strong_roots(bool, bool, SharedHeap
::ScanningOption, OopClosure, CodeBlobClosure, OopsInGenClosure)+0x2f2
V [libjvm.so+0x209cb8] GenCollectedHeap::gen_process_strong_roots(int, bool, b
ool, bool, SharedHeap::ScanningOption, OopsInGenClosure, bool, OopsInGenClosure
)+0x68
V [libjvm.so+0x20bec6] GenMarkSweep::invoke_at_safepoint(int, ReferenceProcess
or, bool)+0x196
V [libjvm.so+0x215408] OneContigSpaceCardGeneration::collect(bool, bool, unsig
ned, bool)+0x68
V [libjvm.so+0x20953e] GenCollectedHeap::do_collection(bool, bool, unsigned, b
ool, int)+0x45e
V [libjvm.so+0x20a8f9] GenCollectedHeap::do_full_collection(bool, int)+0x49
V [libjvm.so+0x46a40b] VM_GenCollectForPermanentAllocation::doit()+0x17b
V [libjvm.so+0x478d86] VM_Operation::evaluate()+0x46
V [libjvm.so+0x478233] VMThread::evaluate_operation(VM_Operation)+0x83
V [libjvm.so+0x4784a0] VMThread::loop()+0x190
V [libjvm.so+0x477f90] VMThread::run()+0x80
V [libjvm.so+0x38e97e] java_start(Thread)+0x14e
C [libpthread.so.0+0x6940] signed char+0x6940

VM_Operation (0xb6ead280): GenCollectForPermanentAllocation, mode: safepoint, re
quested by thread 0xb6b05400

--------------- P R O C E S S ---------------

Java Threads: ( => current thread )
0xb316c400 JavaThread "Cext reference reaper" daemon [_thread_blocked, id=2382
3, stack(0xb2cfe000,0xb2eff000)]
0xb315ec00 JavaThread "RubyThread-1: /home/ec2-user/.rvm/gems/jruby-1.6.3@dm_a
pp/gems/girl_friday-0.9.1/lib/girl_friday/actor.rb:65" daemon [_thread_blocked,
id=23620, stack(0xb2eff000,0xb3100000)]
0xb37a5000 JavaThread "ReferenceReaper" daemon [_thread_blocked, id=23619, sta
ck(0xb34f8000,0xb36f9000)]
0xb6b3c000 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=23617,
stack(0xb39c5000,0xb3bc6000)]
0xb6b3a000 JavaThread "C1 CompilerThread0" daemon [_thread_blocked, id=23616,
stack(0xb3bc6000,0xb3c47000)]
0xb6b38800 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=23615, s
tack(0xb3c47000,0xb3e48000)]
0xb6b34800 JavaThread "Finalizer" daemon [_thread_blocked, id=23614, stack(0xb
--More--(20%)

Things seem to be better when I use webrick rather than thin.
I am running Java HotSpot(TM) Client VM (build 20.2-b06, mixed mode, sharing)

Any ideas what could be going on?

persistent queues remove jobs from the database before being completed

I am looking at the example mongodb store.

When a job is popped, it is removed from the database. This means if the server crashes before the job is completed the data will be lost. I easily added some code to set a status field of push or pop instead of removing from the database. The part I need help with is a way for the workers to signal back to the persistent store that the job is fully completed so that the job can then be removed. I know I could put that directly into the worker, but it seems that this should be pushed back into the framework.

    class Mongo
      def pop  
        val = collection.find_and_modify(:sort => [['$natural', 1]],
                                         :query  => {:status => 'push'},
                                         :update => {:status => 'pop'},
                                         )
        Marshal.load(val["work"]) if val 
      end 

      def push(work)
        val = Marshal.dump(work)
        collection.insert({ "work" => val, "status" => 'push' })
      end
    end

GirlFriday::Batch exhibits odd behavior

I have the following test case:

require 'set'
require 'pp'
require 'girl_friday'

def assert(cond)
  raise RuntimeException.new("failure") unless cond
end

batch = GirlFriday::Batch.new(nil, :size => 5) do |msg|
  msg[:n]
end

0.upto(100) do |i|
  batch.push({:n => i})
end

result = batch.results
assert(Set.new(result) == Set.new(0..100))

When I run it, it blocks for 30 seconds at the end and completes successfully:

$ bundle exec ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]
$ bundle list
Gems included by the bundle:
  * activemodel (3.2.3)
  * activerecord (3.2.3)
  * activesupport (3.2.3)
  * arel (3.0.2)
  * builder (3.0.0)
  * bundler (1.1.4)
  * connection_pool (0.1.0)
  * girl_friday (0.9.7)
  * i18n (0.6.0)
  * multi_json (1.3.5)
  * mysql (2.8.1)
  * mysql2 (0.3.11)
  * sqlite3 (1.3.6)
  * tzinfo (0.3.33)
$ time bundle exec ruby friday_testcase.rb

real    0m30.432s
user    0m0.396s
sys 0m0.036s

However, if I include a "puts 'foo'" at the end of the test case, it works fine (competes in under a second).

When included in a Rails app, test suites always return 0 exit status

We use airbrake in our Rails 3.1 app for error handling, which uses girl_friday for asynchronous notifications. When using that feature of the airbrake gem, I realized our test suites always returned a 0 exit status regardless of pass or failure, and regardless of which test suite I used (minitest or RSpec). This broke our CI process.

https://github.com/mperham/girl_friday/blob/master/lib/girl_friday.rb#L96 is probably related. However, setting $testing to true in our spec_helper/test_helper does not resolve the bug.

I figured out pretty quickly that an at_exit callback was messing with our suites, but chasing it down with a binary search through our Gemfile wasn't very fun! Is there perhaps an easier way to identify whether or not girl_friday is being run in a testing environment?

GirlFriday.status error: LocalJumpError: no block given (yield)

I put this in my girl_friday.rb initializer:

require 'redis'
require 'connection_pool'

$redis = ConnectionPool.new(size: 4) { Redis.connect(url: ENV["REDISTOGO_URL"]) }

SYNC_ACCOUNT_QUEUE = GirlFriday::WorkQueue.new(:sync_account, size: 2, store: GirlFriday::Store::Redis, store_config: { pool: $redis }) do |msg|
Account.sync_account_info(msg[:account_id])
end

When I tried to run GirlFriday.status I get this now:

LocalJumpError: no block given (yield)
from /app/vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.6/lib/girl_friday/persistence.rb:56:in block in redis'
from /app/vendor/bundle/ruby/1.9.1/gems/connection_pool-0.1.0/lib/connection_pool.rb:41:inwith'
from /app/vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.6/lib/girl_friday/persistence.rb:55:in redis'
from /app/vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.6/lib/girl_friday/persistence.rb:44:insize'
from /app/vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.6/lib/girl_friday/work_queue.rb:55:in status'
from /app/vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.6/lib/girl_friday.rb:43:inblock in status'
from /app/vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.6/lib/girl_friday.rb:41:in each'
from /app/vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.6/lib/girl_friday.rb:41:ininject'
from /app/vendor/bundle/ruby/1.9.1/gems/girl_friday-0.9.6/lib/girl_friday.rb:41:in `status'

girl_friday tries to use Rails.logger before it exists

On rails-3.1.0.rc4 and 9af75d7 rake can't load any more:

$ bin/rake --trace db:test:prepare                                                                                                                                                           
rake aborted!                                                                                                                                                                                                                 
undefined method `debug' for nil:NilClass                                                                                                                                                                                     
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/bundler/gems/girl_friday-9af75d7269e0/lib/girl_friday/work_queue.rb:25:in `<class:WorkQueue>'                                                                                      
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/bundler/gems/girl_friday-9af75d7269e0/lib/girl_friday/work_queue.rb:3:in `<module:GirlFriday>'                                                                                     
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/bundler/gems/girl_friday-9af75d7269e0/lib/girl_friday/work_queue.rb:1:in `<top (required)>'                                                                                        
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:237:in `require'                                                                                                   
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:237:in `block in require'                                                                                          
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:223:in `block in load_dependency'                                                                                  
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:639:in `new_constants_in'                                                                                          
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:223:in `load_dependency'                                                                                           
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:237:in `require'                                                                                                   
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/bundler/gems/girl_friday-9af75d7269e0/lib/girl_friday.rb:13:in `<top (required)>'                                                                                                  
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/bundler-1.0.15/lib/bundler/runtime.rb:68:in `require'                                                                                                                         
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/bundler-1.0.15/lib/bundler/runtime.rb:68:in `block (2 levels) in require'                                                                                                     
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/bundler-1.0.15/lib/bundler/runtime.rb:66:in `each'                                                                                                                            
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/bundler-1.0.15/lib/bundler/runtime.rb:66:in `block in require'                                                                                                                
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/bundler-1.0.15/lib/bundler/runtime.rb:55:in `each'
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/bundler-1.0.15/lib/bundler/runtime.rb:55:in `require'
/home/betelgeuse/.rvm/gems/ruby-1.9.2-p180/gems/bundler-1.0.15/lib/bundler.rb:120:in `require'

Actor class in global scope?

Am I correct in understanding that this gem places the 'Actor' class in the global scope? After installing Airbrake (which pulls in girl_friday), our Rails app now fails because 'Actor' has already been defined. Any suggestions for a straightforward solution that doesn't involve s/actor/aktor/?

Queue not working relaliably on Ruby 1.9.2

I have a Ruby 1.9.2 app on Heroku with the following queue:

SYNC_FRIENDS_QUEUE = GirlFriday::WorkQueue.new(:sync_friends) do |msg|
Account.sync_friends(msg[:account_id])
end

I've noticed that sometimes the job is never executed at random. Don't see anything in the logs when it happens. Any ideas?

threadsafe is not enabled.

Queue Order Last In First Out?

So I was looking at the code. And noticed that the order is Last in First Out(LIFO) so if the job process speed were ever to match the job adding speed the first items in the queue would never get processed. Wouldn't it be better to either let the programmer decide if it was LIFO or First in First Out(FIFO)?

Maybe change the Store Api from push to add and pop to process_next to accommodate the change in the way jobs are processed.

And maybe add a function to retrieve and remove an item from queue by letting a queue item return a unique ID.

Model.new is missing in rails

as title. when I run lots of works with one job, it sometime shows

Job Error  -> undefined method `new' on nil:NilClass.

my environment is rbx with 1.9.3
(let me make sure, just rvm rbx and type "rbx -X19 -v" and would change to ruby 1.9.3 right?)

and I also added

GirlFriday::WorkQueue.immediate!

into any place that it should be..
but still doesn't works.

Setting up girl_friday in sinatra app

I'm a newbie so I'm sorry if this question is off-base.

I have an app that started from the default Facebook app template provided on heroku. It uses Sinatra instead of Rails and seems to be working fine. But now I want to add in the ability to do some background processing (going through a Facebook user's friends and adding info to my db, etc.) while the user waits on a loading page.

I've tried following the steps listed (see mine below) but I'm hitting this exception:

NameError - uninitialized constant Sinatra::Application::QUEUE:

Here's what I've done:

  • added girl_friday to my Gemfile

  • ran bundle install successfully

  • created the directory /config/initializers/ with file girl_friday.rb:

     QUEUE = GirlFriday::WorkQueue.new(:user_client, :size => 3) do |msg|
       UserRefresh.process(msg)
     end
    
  • created the class UserRefresh in my app.rb file with method process:

     class UserRefresh
    
       def process(client)
         ...
         {:value1 => "blah", :value2 => "blahblah"} #return a result
       end
     end
    
  • called the queue to push some work onto it and use the result upon completion:

     QUEUE.push(:client => @client) do |result|
       puts result
     end
    

Can someone steer me in the right direction? Is Rails required or can I make this work with just Sinatra and girl_friday?

Thanks!

pipeline.rb - which image library is required?

I'm running OS X 10.7. When I run the pipeline.rb example I am told it cannot load libclparser.dylib from OpenCL.framework. How do I this? (perhaps put this at the top of the pipeline.rb file?)

$ ruby examples/pipeline.rb 
#<Thread:0x617e53c9>: Pushing http://blog.carbonfive.com
#<Thread:0x17773a14>: Fetching image: http://blog.carbonfive.com/wp-content/uploads/2011/08/carbonite-1.png
#<Thread:0x132fae6c>: Fetching image: http://blog.carbonfive.com/wp-includes/images/rss.png
dyld: Library not loaded: /System/Library/Frameworks/OpenCL.framework/Versions/A/Libraries/libclparser.dylib
  Referenced from: /usr/local/bin/identify
  Reason: image not found
#<Thread:0x17773a14>: Image: 

# hangs here

Any method to check if a task is running?

Hey! Is there any method to check if my task is running? For example, I have this task:

SHARE_UPDATER_QUEUE = GirlFriday::WorkQueue.new(:share_updater, :size => 7) do |msg|
    Company.update_shares
end

Is there any way I can know (from my model's update_share method) if SHARE_UPDATER_QUEUE is running? Or wait until a task is done to continue processing the rest of the queue?

redis test timing out

$ bundle exec rake
/Users/drnic/.rvm/gems/jruby-1.6.3@gf/gems/flexmock-minitest-1.0.1/lib/flexmock/minitest.rb:4 warning: already initialized constant VERSION
jruby 1.6.3 (ruby-1.9.2-p136) (2011-07-07 965162f) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_26) [darwin-x86_64-java]
Run options: --seed 51191

# Running tests:

........E....

Finished tests in 2.466000s, 5.2717 tests/s, 11.7599 assertions/s.

  1) Error:
test_should_persist_with_redis_instance(TestGirlFriday):
Timeout::Error: Timeout::Error
    /Users/drnic/Projects/gems/girl_friday/test/timed_queue.rb:27:in `timed_pop'
    /Users/drnic/Projects/gems/girl_friday/test/timed_queue.rb:22:in `timed_pop'
    /Users/drnic/Projects/gems/girl_friday/test/helper.rb:22:in `async_test'
    /Users/drnic/Projects/gems/girl_friday/test/test_girl_friday.rb:132:in `test_should_persist_with_redis_instance'
    org/jruby/RubyBasicObject.java:1684:in `__send__'

13 tests, 29 assertions, 0 failures, 1 errors, 0 skips
rake aborted!

I have redis running:

$ ps ax | grep redis
 1517   ??  R      6:32.07 /usr/local/Cellar/redis/2.2.11/bin/redis-server /usr/local/etc/redis.conf
56251 s006  R+     0:00.00 grep redis

Thoughts on what to do to get this test passing?

can't convert Symbol into Integer (TypeError) during start

I updated my code according the to latest commits, results below:

/Users/kain/.rvm/gems/ruby-1.9.3-preview1/bundler/gems/girl_friday-3c97ba78f22c/lib/girl_friday/persistence.rb:26:in `[]': can't convert Symbol into Integer (TypeError)
  from /Users/kain/.rvm/gems/ruby-1.9.3-preview1/bundler/gems/girl_friday-3c97ba78f22c/lib/girl_friday/persistence.rb:26:in `initialize'
  from /Users/kain/.rvm/gems/ruby-1.9.3-preview1/bundler/gems/girl_friday-3c97ba78f22c/lib/girl_friday/work_queue.rb:21:in `new'
  from /Users/kain/.rvm/gems/ruby-1.9.3-preview1/bundler/gems/girl_friday-3c97ba78f22c/lib/girl_friday/work_queue.rb:21:in `initialize'
  from /Users/kain/Sites/myproj/config/initializers/girl_friday.rb:22:in `new'
  from /Users/kain/Sites/myproj/config/initializers/girl_friday.rb:22:in `<top (required)>'

Sample worker:

uri = URI.parse(Settings.app.redis.uri)
redis_pool = ConnectionPool.new(:size => 5, :timeout => 5) { Redis.new(:host => uri.host, :port => uri.port, :password => uri.password) }

TRACK_NOW_PLAYING_QUEUE = GirlFriday::WorkQueue.new(:scrobble, size: 2, store: GirlFriday::Store::Redis, store_config: [{ pool: redis_pool }]) do |packet|

release latest as 0.9.8, please?

Several problems have been fixed since the last release (0.9.7). Gathering these into a release would be helpful.

The fix I need is the updated dependency on connection_pool (from 0.1.0 to 0.9.0). I've built a gem that depends on girl_friday, and having the wrong connection_pool dragged in to my users' apps is problematic.

undefined method `with' for nil:NilClass

I'm not quite sure what is causing this. I have a working queue that is processing tasks correctly, however I see these exceptions for some reason despite the task running correctly:

irb(main):023:0> a.save()
=> true
undefined method `with' for nil:NilClass
irb(main):024:0> /home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/persistence.rb:53:in `redis'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/persistence.rb:32:in `push'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/work_queue.rb:127:in `on_work'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/work_queue.rb:182:in `block (3 levels) in supervisor_loop'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:310:in `call'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:310:in `_receive'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:107:in `receive'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/work_queue.rb:177:in `block in supervisor_loop'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/work_queue.rb:176:in `loop'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/work_queue.rb:176:in `supervisor_loop'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/work_queue.rb:156:in `block in start'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:69:in `call'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:69:in `block (2 levels) in spawn'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:212:in `block in initialize'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:377:in `watchdog'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:212:in `initialize'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:66:in `new'
/home/deployer/xanview-portals/demo1/shared/bundle/ruby/1.9.1/gems/girl_friday-0.10.0/lib/girl_friday/actor.rb:66:in `block in spawn'

This is the task:

require 'connection_pool'
require 'redis'

redis_pool = ConnectionPool.new(:size => 5, :timeout => 5) { Redis.new }
defaults = { size: 1, store: GirlFriday::Store::Redis, store_config: { pool: redis_pool } }

GEOCODER_QUEUE = GirlFriday::WorkQueue.new(:geocoder, defaults) do |msg|
  object = msg[:model_name].constantize.find(msg[:id])

  # Don't geocode for local LAN addresses
  unless IPAddress(msg[:ip]).private? or msg[:ip] == "127.0.0.1"
    geo = Geocoder.search(msg[:ip])
    object.update_attributes!(
      coordinates: [geo[0].longitude, geo[0].latitude],
      country: geo[0].country,
      country_code: geo[0].country_code,
      city: geo[0].city
    )
  end
end

And the "msg" passed to the queue looks like this:

GEOCODER_QUEUE.push(model_name: self.class.model_name, id: self.id, ip: remote_ip)

Any ideas what is causing this?

Specs fail on Gentoo

In trying to figure out why GF wasn't processing on EY I noticed the specs fail to run on Gentoo. I'll try to get this sorted out, since I use EY and they use Gentoo.

RuntimeError: ObjectSpace is disabled under JRuby

I'm getting this error under JRuby, when I stop the app (ex. when I close a rails console or warble finishing packaging), I'm not sure if is serious or how to fix it.

The backtrace:

RuntimeError: ObjectSpace is disabled; each_object will only work with Class, pass -X+O to enable
 each_object at org/jruby/RubyObjectSpace.java:167
        each at org/jruby/RubyEnumerator.java:189
        to_a at org/jruby/RubyEnumerable.java:375
      queues at /Users/koombeamacbook/.rvm/gems/jruby-1.6.2@consumption/gems/girl_friday-0.9.3/lib/girl_friday.rb:20
   shutdown! at /Users/koombeamacbook/.rvm/gems/jruby-1.6.2@consumption/gems/girl_friday-0.9.3/lib/girl_friday.rb:36
      (root) at /Users/koombeamacbook/.rvm/gems/jruby-1.6.2@consumption/gems/girl_friday-0.9.3/lib/girl_friday.rb:63
        call at org/jruby/RubyProc.java:268
        call at org/jruby/RubyProc.java:232

Intermittently failing batch test

test_simple_batch_operation fails some of the time on all impls.

∴ rake
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]
Loaded suite /home/jesse/.rvm/gems/ruby-1.9.2-p290@global/gems/rake-0.9.2/lib/rake/rake_test_loader
Started
...F.............
Finished in 0.645033 seconds.

  1) Failure:
test_simple_batch_operation(TestBatch) [/home/jesse/projects/girl_friday/test/test_batch.rb:19]:
Expected 0.5 - 0.0112529 (0.4887471) to be < 0.1.

17 tests, 37 assertions, 1 failures, 0 errors, 0 skips

Move conversation from Blog

Hey, this is Michael (the guy who posted on your blog regarding Girl Friday and RBX/Rainbows, etc)

Thought it might be easier to keep this project-specific talk on GitHub rather than on your blog, might clutter it up and get lost over time :)

Anyway to pick up where we left off:

I tried Thin + Ruby 1.9.2 - this seems to work. It queues and processes data in the background. In development mode, while jobs are being processed, and spamming the refresh key (to simulate "heavy" load) I occasionally get the error where it says it expected the User model to be defined in app/models/user.rb - I'm suspecting this is because it doesn't store the models in memory in development mode and it conflicts when I refresh and it processes. I tried to replicate this in production mode and was unable to, so im fairly sure that's just because it doesn't store the models in memory in production and reloads on each request.

When running thin --threaded under RBX it simply fails. It hangs infinitely as far as I can see. So that's a no-go. thin --threaded under Ruby 1.9.2 does not improve performance at all (unless there are some I/O blocking things going down somewhere of course, then it's a good improvement to speed up requests) but it actually does work and is as fast as without --threaded

Running Thin without --threaded with RBX does not (as you already thought) enable threading. Performance actually gets a few times worse. Rainbows! hangs when you do the initial request, or it takes like 30-60 if you'er patient enough to wait, but it's the same with each request. I checked the mailing list and noticed your post already. Seems like it's more of a RBX or RVM issue? In any case, with RVM + RBX Hydra it seems like it doesn't work at all.

So Unicorn, Rainbows, Thin, Passenger all don't seem to work. What's left?

no such file to load -- girl_friday/server (LoadError)

require ::File.expand_path('../config/environment',  __FILE__)
require 'girl_friday/server'

run Rack::URLMap.new \
  "/"            => Gfapp::Application,
  "/girl_friday" => GirlFriday::Server.new

Seems it can't find the Sinatra app, which is odd because the path should be correct, looking at the gem structure and the lib being in the load path.

Using GF for periodic tasks on Heroku

Would it be possible to use girl_friday for handling periodic tasks on heroku (or anywhere else)?

I have a small and simple task to do every hour. The task is written below.

class TaskQueue < GirlFriday::WorkQueue
  include Singleton
  def initialize
    super(:task_queue, size: 1) do
      loop {
        Task.to_do
        sleep 3600
      }
    end 
  end 

  def self.push *args
    instance.push *args
  end 

end

I've tried to make a rails initializer that would start the task above: TaskQueue.push(nil)
This does not seem to work as expected on my machine locally.

Is there a way to accomplish this idea somehow?
Reason for this would be simplicity: not having to deal with cron or setting up (paid) heroku scheduler addon. Can't think of any drawbacks.
Thanks for help!

rails master warning

:public is no longer used to avoid overloading Module#public, use :public_folder instead
from /Users/kain/.rvm/gems/ruby-1.9.3-preview1/bundler/gems/girl_friday-dbd3c7f9cade/lib/girl_friday/server.rb:17:in `<class:Server>'

Can't get Redis store to work

I've added the following to my redis.rb initializer:
uri = URI.parse(ENV['REDISTOGO_URL'] || 'redis://localhost:6379')
$redis = Redis.new(host: uri.host, port: uri.port, password: uri.password)

and the following to my girl_friday.rb initializer:

SYNC_FRIENDS_QUEUE = GirlFriday::WorkQueue.new(:sync_friends, size: 2, store: GirlFriday::Store::Redis, store_config: [{ redis: $redis }]) do |msg|
Account.sync_friends(msg[:account_id])
end

However, when I push stuff to the queue (SYNC_FRIENDS_QUEUE.push(account_id: account.id))), it gets processed in memory. Tailing the Redis log shows no connected clients. Only when I do GirlFriday.status can I see the Redis client connected. Am I configuring something wrong?

Redis To Go

I'm considering pushing all my queued items to RedisToGo.com - The free plan provides 5mb storage (plenty for queues since I only stores id's so I doubt it'll fill up faster than that it's being processed due to the :size => 10 option.

I have a question regarding this however. I have set up 5 GirlFriday::WorkQueue instances, all using RedisToGo. This would mean I'm making 5 connections with RedisToGo am I right?

You mentioned in your wiki or readme something about ActiveRecord's pool size, that you must increase it when increasing the :size option. But that has nothing to do with the amount of connections going to RedisToGo right? I'm asking this because RedisToGo allows only 10 clients to connect, looking at your source it seems that you only establish a new connection per GirlFriday::WorkQueue instance - not per thread that's actually processing jobs ( which you can increase with the :size => amount option ).

Is this correct? What's nice is that you can have multiple free plans so you could essentially just spin up a RedisToGo free instance for each GirlFriday::WorkQueue instance if this is the case.

Thanks!

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.