girl_friday 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  rvm:
2
2
  - 1.9.2
3
+ - 1.9.3
3
4
  - jruby
4
- - rbx-2.0
5
5
  branches:
6
6
  only:
7
7
  - master
data/History.md CHANGED
@@ -1,6 +1,13 @@
1
1
  Changes
2
2
  ================
3
3
 
4
+ 0.9.6
5
+ ---------
6
+
7
+ * Completely switch to connection\_pool for Redis backend.
8
+ The Redis store no longer connects for you automatically, so it's mandatory to use
9
+ connection\_pool.
10
+
4
11
  0.9.5
5
12
  ---------
6
13
 
data/README.md CHANGED
@@ -1,11 +1,7 @@
1
1
  girl\_friday
2
2
  ====================
3
3
 
4
- Have a task you want to get done sometime soon but don't want to do it yourself? Give it to girl\_friday! From wikipedia:
5
-
6
- > The term Man Friday has become an idiom, still in mainstream usage, to describe an especially faithful servant or
7
- > one's best servant or right-hand man. The female equivalent is Girl Friday. The title of the movie His Girl Friday
8
- > alludes to it and may have popularized it.
4
+ [![Travis-CI build status](https://secure.travis-ci.org/mperham/girl_friday.png)](http://travis-ci.org/mperham/girl\_friday)
9
5
 
10
6
  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.
11
7
 
@@ -37,22 +33,16 @@ In your Rails app, create a `config/initializers/girl_friday.rb` which defines y
37
33
  ImageCrawler.process(msg)
38
34
  end
39
35
 
40
- SCRAPE_QUEUE = GirlFriday::WorkQueue.new(:scrape_sites, :size => 4, :store => GirlFriday::Store::Redis, :store_config => [{ :host => 'host' }]) do |msg|
41
- Page.scrape(msg)
42
- end
43
-
44
- TRANSCODE_QUEUE = GirlFriday::WorkQueue.new(:scrape_sites, :size => 4, :store => GirlFriday::Store::Redis, :store_config => [{ :redis => $redis }]) do |msg|
45
- VideoProcessor.transcode(msg)
46
- end
47
-
48
36
  :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`.
49
37
 
50
- You can use a connection pool to share a set of Redis connections with
38
+ In order to use the Redis backend, you must use a connection pool to share a set of Redis connections with
51
39
  other threads and GirlFriday queues using the `connection\_pool` gem:
52
40
 
53
41
  require 'connection_pool'
42
+
54
43
  redis_pool = ConnectionPool.new(:size => 5, :timeout => 5) { Redis.new }
55
- CLEAN_FILTER_QUEUE = GirlFriday::WorkQueue.new(:clean_filter, :store => GirlFriday::Store::Redis, :store_config => [{ :redis => redis_pool}]) do |msg|
44
+
45
+ CLEAN_FILTER_QUEUE = GirlFriday::WorkQueue.new(:clean_filter, :store => GirlFriday::Store::Redis, :store_config => [{ :pool => redis_pool}]) do |msg|
56
46
  Filter.clean(msg)
57
47
  end
58
48
 
@@ -71,11 +61,18 @@ have no reference to them. Make sure you call `WorkQueue#shutdown` if you are
71
61
  dynamically creating them so you don't leak memory. `GirlFriday.shutdown!` will shut down all
72
62
  running queues in the process.
73
63
 
64
+
74
65
  More Detail
75
66
  --------------------
76
67
 
77
68
  Please see the [girl\_friday wiki](https://github.com/mperham/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!
78
69
 
70
+ From wikipedia:
71
+
72
+ > The term Man Friday has become an idiom, still in mainstream usage, to describe an especially faithful servant or
73
+ > one's best servant or right-hand man. The female equivalent is Girl Friday. The title of the movie His Girl Friday
74
+ > alludes to it and may have popularized it.
75
+
79
76
 
80
77
  Thanks
81
78
  --------------------
data/TODO.md CHANGED
@@ -1,5 +1,5 @@
1
1
  TODO
2
- ===============
2
+ ==============
3
3
 
4
4
  - rufus-scheduler integration for scheduled tasks
5
5
  - web admin UI to surface status() metrics
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
- s.add_development_dependency 'sinatra', '~> 1.0'
20
- s.add_development_dependency 'rake'
19
+ s.add_dependency 'connection_pool', '~> 0.1.0'
20
+ s.add_development_dependency 'sinatra', '~> 1.0'
21
+ s.add_development_dependency 'rake'
21
22
  end
@@ -17,10 +17,10 @@ require 'girl_friday/batch'
17
17
 
18
18
  module GirlFriday
19
19
 
20
- @@lock = Mutex.new
20
+ @lock = Mutex.new
21
21
 
22
22
  def self.add_queue(ref)
23
- @@lock.synchronize do
23
+ @lock.synchronize do
24
24
  @queues ||= []
25
25
  @queues.reject! { |q| !q.weakref_alive? }
26
26
  @queues << ref
@@ -28,7 +28,7 @@ module GirlFriday
28
28
  end
29
29
 
30
30
  def self.remove_queue(ref)
31
- @@lock.synchronize do
31
+ @lock.synchronize do
32
32
  @queues.delete ref
33
33
  end
34
34
  end
@@ -81,7 +81,7 @@ module GirlFriday
81
81
  end
82
82
 
83
83
  m.synchronize do
84
- var.wait(m, timeout)
84
+ var.wait(m, timeout) if count != 0
85
85
  end
86
86
  end
87
87
  count
@@ -23,17 +23,20 @@ module GirlFriday
23
23
  class Redis
24
24
  def initialize(name, options)
25
25
  @opts = options
26
+ unless @opts[:pool]
27
+ raise ArgumentError, "you must pass in a :pool"
28
+ end
26
29
  @key = "girl_friday-#{name}-#{environment}"
27
30
  end
28
31
 
29
32
  def push(work)
30
33
  val = Marshal.dump(work)
31
- redis.rpush(@key, val)
34
+ redis{ |r| r.rpush(@key, val) }
32
35
  end
33
36
  alias_method :<<, :push
34
37
 
35
38
  def pop
36
- val = redis.lpop(@key)
39
+ val = redis{ |r| r.lpop(@key) }
37
40
  Marshal.load(val) if val
38
41
  end
39
42
 
@@ -48,8 +51,12 @@ module GirlFriday
48
51
  end
49
52
 
50
53
  def redis
51
- @redis ||= (@opts.delete(:redis) || ::Redis.connect(*@opts))
54
+ @redis ||= @opts.delete(:pool)
55
+ @redis.with do |pooled|
56
+ yield pooled
57
+ end
52
58
  end
53
59
  end
60
+
54
61
  end
55
62
  end
@@ -1,3 +1,3 @@
1
1
  module GirlFriday
2
- VERSION = "0.9.5"
2
+ VERSION = "0.9.6"
3
3
  end
@@ -15,9 +15,10 @@ module GirlFriday
15
15
 
16
16
  @shutdown = false
17
17
  @busy_workers = []
18
+ @ready_workers = nil
18
19
  @created_at = Time.now.to_i
19
20
  @total_processed = @total_errors = @total_queued = 0
20
- @persister = (options[:store] || Store::InMemory).new(name, (options[:store_config] || []))
21
+ @persister = (options[:store] || Store::InMemory).new(name, (options[:store_config] || {}))
21
22
  @weakref = WeakRef.new(self)
22
23
  start
23
24
  GirlFriday.add_queue @weakref
@@ -49,7 +50,7 @@ module GirlFriday
49
50
  { @name => {
50
51
  :pid => $$,
51
52
  :pool_size => @size,
52
- :ready => ready_workers.size,
53
+ :ready => @ready_workers ? @ready_workers.size : 0,
53
54
  :busy => @busy_workers.size,
54
55
  :backlog => @persister.size,
55
56
  :total_queued => @total_queued,
@@ -127,8 +128,10 @@ module GirlFriday
127
128
 
128
129
  def start
129
130
  @supervisor = Actor.spawn do
131
+ Thread.current[:label] = "#{name}-supervisor"
130
132
  supervisor = Actor.current
131
133
  @work_loop = Proc.new do
134
+ Thread.current[:label] = "#{name}-worker"
132
135
  while !@shutdown do
133
136
  work = Actor.receive
134
137
  if !@shutdown
@@ -6,7 +6,7 @@ at_exit do
6
6
  Thread.list.each do |thread|
7
7
  next if thread.status == 'run'
8
8
  puts "WARNING: lingering threads found. All threads should be shutdown and garbage collected."
9
- p [thread, thread['name']]
9
+ p [thread, thread[:label], thread.object_id]
10
10
  # puts thread.backtrace.join("\n")
11
11
  end
12
12
  end
@@ -87,44 +87,12 @@ class TestGirlFriday < MiniTest::Unit::TestCase
87
87
  assert(metrics[:total_processed] > 0)
88
88
  end
89
89
 
90
- def test_should_persist_with_redis
91
- begin
92
- require 'redis'
93
- redis = Redis.new
94
- redis.flushdb
95
- rescue LoadError
96
- return puts "Skipping redis test, 'redis' gem not found: #{$!.message}"
97
- rescue Errno::ECONNREFUSED
98
- return puts 'Skipping redis test, not running locally'
99
- end
100
-
101
- mutex = Mutex.new
102
- total = 100
103
- count = 0
104
- incr = Proc.new do
105
- mutex.synchronize do
106
- count += 1
107
- end
108
- end
109
-
110
- async_test(1.0) do |cb|
111
- queue = GirlFriday::WorkQueue.new('redis', :size => 2, :store => GirlFriday::Store::Redis) do |msg|
112
- incr.call
113
- queue.shutdown do
114
- cb.call
115
- end if count == total
116
- end
117
- total.times do
118
- queue.push(:text => 'foo')
119
- end
120
- end
121
- end
122
-
123
- def test_should_persist_with_redis_instance
90
+ def test_should_persist_with_redis_connection_pool
124
91
  begin
125
92
  require 'redis'
126
- redis = Redis.new
127
- redis.flushdb
93
+ require 'connection_pool'
94
+ pool = ConnectionPool.new(:size => 5, :timeout => 2){ Redis.new }
95
+ pool.flushdb
128
96
  rescue LoadError
129
97
  return puts "Skipping redis test, 'redis' gem not found: #{$!.message}"
130
98
  rescue Errno::ECONNREFUSED
@@ -140,8 +108,8 @@ class TestGirlFriday < MiniTest::Unit::TestCase
140
108
  end
141
109
  end
142
110
 
143
- async_test(1.0) do |cb|
144
- queue = GirlFriday::WorkQueue.new('redis-instance', :size => 2, :store => GirlFriday::Store::Redis, :store_config => [{ :redis => redis }]) do |msg|
111
+ async_test(2.0) do |cb|
112
+ queue = GirlFriday::WorkQueue.new('redis-pool', :size => 2, :store => GirlFriday::Store::Redis, :store_config => { :pool => pool }) do |msg|
145
113
  incr.call
146
114
  queue.shutdown do
147
115
  cb.call
@@ -153,36 +121,10 @@ class TestGirlFriday < MiniTest::Unit::TestCase
153
121
  end
154
122
  end
155
123
 
156
- def test_should_persist_with_redis_connection_pool
157
- begin
158
- require 'redis'
159
- require 'connection_pool'
160
- redis = ConnectionPool.new(:size => 5, :timeout => 5){ Redis.new }
161
- redis.flushdb
162
- rescue LoadError
163
- return puts "Skipping redis test, 'redis' gem not found: #{$!.message}"
164
- rescue Errno::ECONNREFUSED
165
- return puts 'Skipping redis test, not running locally'
166
- end
167
-
168
- mutex = Mutex.new
169
- total = 100
170
- count = 0
171
- incr = Proc.new do
172
- mutex.synchronize do
173
- count += 1
174
- end
175
- end
176
-
177
- async_test(1.0) do |cb|
178
- queue = GirlFriday::WorkQueue.new('redis-pool', :size => 2, :store => GirlFriday::Store::Redis, :store_config => [{ :redis => redis }]) do |msg|
179
- incr.call
180
- queue.shutdown do
181
- cb.call
182
- end if count == total
183
- end
184
- total.times do
185
- queue.push(:text => 'foo')
124
+ def test_should_raise_if_no_store_config_passed_in_for_redis_backend
125
+ assert_raises(ArgumentError) do
126
+ GirlFriday::WorkQueue.new('raise-test', :store => GirlFriday::Store::Redis) do |msg|
127
+ # doing work
186
128
  end
187
129
  end
188
130
  end
@@ -221,7 +163,8 @@ class TestGirlFriday < MiniTest::Unit::TestCase
221
163
  cb.call
222
164
  end
223
165
  end
224
- refute queue.instance_variable_defined?(:@ready_workers)
166
+ assert queue.instance_variable_defined?(:@ready_workers)
167
+ assert_nil queue.instance_variable_get(:@ready_workers)
225
168
  # don't instantiate the worker threads until we actually put
226
169
  # work onto the queue.
227
170
  queue << 'empty msg'
metadata CHANGED
@@ -1,39 +1,49 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: girl_friday
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.9.5
4
+ version: 0.9.6
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mike Perham
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-22 00:00:00.000000000 -07:00
13
- default_executable:
12
+ date: 2011-09-26 00:00:00.000000000Z
14
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: connection_pool
16
+ requirement: &22271180 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.1.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *22271180
15
25
  - !ruby/object:Gem::Dependency
16
26
  name: sinatra
17
- version_requirements: &2086 !ruby/object:Gem::Requirement
27
+ requirement: &22270680 !ruby/object:Gem::Requirement
28
+ none: false
18
29
  requirements:
19
30
  - - ~>
20
31
  - !ruby/object:Gem::Version
21
32
  version: '1.0'
22
- none: false
23
- requirement: *2086
24
- prerelease: false
25
33
  type: :development
34
+ prerelease: false
35
+ version_requirements: *22270680
26
36
  - !ruby/object:Gem::Dependency
27
37
  name: rake
28
- version_requirements: &2104 !ruby/object:Gem::Requirement
38
+ requirement: &22270300 !ruby/object:Gem::Requirement
39
+ none: false
29
40
  requirements:
30
41
  - - ! '>='
31
42
  - !ruby/object:Gem::Version
32
43
  version: '0'
33
- none: false
34
- requirement: *2104
35
- prerelease: false
36
44
  type: :development
45
+ prerelease: false
46
+ version_requirements: *22270300
37
47
  description: Background processing, simplified
38
48
  email:
39
49
  - mperham@gmail.com
@@ -73,35 +83,28 @@ files:
73
83
  - test/test_girl_friday.rb
74
84
  - test/test_girl_friday_immediately.rb
75
85
  - test/test_girl_friday_queue.rb
76
- has_rdoc: true
77
86
  homepage: http://github.com/mperham/girl_friday
78
87
  licenses: []
79
- post_install_message:
88
+ post_install_message:
80
89
  rdoc_options: []
81
90
  require_paths:
82
91
  - lib
83
92
  required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
84
94
  requirements:
85
95
  - - ! '>='
86
96
  - !ruby/object:Gem::Version
87
97
  version: '0'
88
- none: false
89
98
  required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
90
100
  requirements:
91
101
  - - ! '>='
92
102
  - !ruby/object:Gem::Version
93
103
  version: '0'
94
- none: false
95
104
  requirements: []
96
105
  rubyforge_project: girl_friday
97
- rubygems_version: 1.5.1
98
- signing_key:
106
+ rubygems_version: 1.8.6
107
+ signing_key:
99
108
  specification_version: 3
100
109
  summary: Background processing, simplified
101
- test_files:
102
- - test/helper.rb
103
- - test/test_batch.rb
104
- - test/test_girl_friday.rb
105
- - test/test_girl_friday_immediately.rb
106
- - test/test_girl_friday_queue.rb
107
- ...
110
+ test_files: []