floormanager 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -19,7 +19,7 @@ See the examples for more advanced usage.
19
19
 
20
20
  == TODO
21
21
 
22
- * Write the tests and examples
22
+ * Write the tests
23
23
 
24
24
  == Copyright
25
25
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
@@ -0,0 +1,61 @@
1
+ require 'httparty'
2
+ require 'floormanager'
3
+
4
+ # = Example Twitter client with robust concurrent search.
5
+ #
6
+ # Will handle rate limiting and errors gracefully, optionally
7
+ # retrying for a number of times before failing.
8
+ #
9
+ # == Usage:
10
+ #
11
+ # twitter = Twitter.new(:concurrency => 10, :retries => 5, :retry_delay => 10)
12
+ # results = twitter.concurrent_search(['ruby', 'httparty', 'floormanager'])
13
+ # results.each do |search_string, tweets|
14
+ # unless tweets.failed?
15
+ # puts tweets.inspect
16
+ # end
17
+ # end
18
+
19
+ class Twitter
20
+ include HTTParty
21
+
22
+ def initialize(options={})
23
+ @concurrency = options[:concurrency] || 20
24
+ @retries = options[:retries] || 0
25
+ @retry_delay = options[:retry_delay] || 2.0
26
+ end
27
+ attr_accessor :concurrency, :retries, :retry_delay
28
+
29
+ base_uri 'http://search.twitter.com'
30
+ default_params :rpp => '100'
31
+ format :json
32
+
33
+ def concurrent_search(query_strings)
34
+ queue = FloorManager::Queue.new(query_strings)
35
+ workers = FloorManager::Workers.new(queue)
36
+ workers.perform(:threads => @concurrency) do |query_string|
37
+ retries = 0
38
+ begin
39
+ results = self.class.get('/search.json', :query => {:q => "\"#{query_string}\""})
40
+ # Handle rate limiting
41
+ if results.code == 420
42
+ if result.headers['retry-after']
43
+ retry_delay = result.headers['retry-after'].first.to_i
44
+ else
45
+ retry_delay = 60
46
+ end
47
+ workers.halt(retry_delay) # Halt all workers for the retry delay
48
+ retry
49
+ else
50
+ results['results']
51
+ end
52
+ rescue Exception => error
53
+ if retries < @retries # If at first you don't succeed, try and try again
54
+ retries += 1
55
+ sleep(@retry_delay) and retry
56
+ end
57
+ workers.failed(error) # Return a failed result after 5 tries
58
+ end
59
+ end
60
+ end
61
+ end
data/floormanager.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{floormanager}
8
- s.version = "0.2.0"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Inge J\303\270rgensen"]
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  "README.rdoc",
24
24
  "Rakefile",
25
25
  "VERSION",
26
+ "examples/twitter.rb",
26
27
  "floormanager.gemspec",
27
28
  "lib/floormanager.rb",
28
29
  "lib/floormanager/queue.rb",
@@ -40,7 +41,8 @@ Gem::Specification.new do |s|
40
41
  s.summary = %q{Handle threaded workers like a champ}
41
42
  s.test_files = [
42
43
  "spec/floormanager_spec.rb",
43
- "spec/spec_helper.rb"
44
+ "spec/spec_helper.rb",
45
+ "examples/twitter.rb"
44
46
  ]
45
47
 
46
48
  if s.respond_to? :specification_version then
@@ -1,22 +1,16 @@
1
1
  module FloorManager
2
2
  class Result < FloorManager::BasicObject
3
3
  attr_accessor :result, :state
4
- attr_reader :delegate
5
4
 
6
- def initialize(delegate, result, state=States::SUCCESS)
7
- @delegate = delegate
5
+ def initialize(result, state=States::SUCCESS)
8
6
  @result = result
9
7
  @state = state
10
8
  end
11
9
 
12
10
  def method_missing(name, *args, &block)
13
- @delegate.send(name, *args, &block)
11
+ @result.send(name, *args, &block)
14
12
  end
15
13
 
16
- def state
17
- @state
18
- end
19
-
20
14
  def failed?
21
15
  @state == States::FAILED
22
16
  end
@@ -15,7 +15,7 @@ module FloorManager
15
15
  until queue.done?
16
16
  if item = checkout
17
17
  result = yield(item)
18
- result = Result.new(result, result, (result.state rescue States::SUCCESS))
18
+ result = Result.new(result, (result.state rescue States::SUCCESS))
19
19
  checkin(item, result, result.state)
20
20
  else
21
21
  Thread.pass
@@ -28,11 +28,11 @@ module FloorManager
28
28
  end
29
29
 
30
30
  def checkout
31
- @mutex.synchronize{@queue.checkout}
31
+ synchronize{@queue.checkout}
32
32
  end
33
33
 
34
34
  def checkin(*args)
35
- @mutex.synchronize{@queue.checkin(*args)}
35
+ synchronize{@queue.checkin(*args)}
36
36
  end
37
37
 
38
38
  def synchronize
@@ -40,15 +40,19 @@ module FloorManager
40
40
  end
41
41
  alias :exclusively :synchronize
42
42
 
43
+ def halt(time)
44
+ synchronize{sleep(time)}
45
+ end
46
+
43
47
  def result(result, state=States::SUCCESS)
44
- Result.new(result, result, state)
48
+ Result.new(result, state)
45
49
  end
46
50
 
47
51
  def success(result)
48
52
  result(result, States::SUCCESS)
49
53
  end
50
54
 
51
- def fail(result)
55
+ def failed(result=nil)
52
56
  result(result, States::FAILED)
53
57
  end
54
58
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 0
9
- version: 0.2.0
8
+ - 1
9
+ version: 0.2.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Inge J\xC3\xB8rgensen"
@@ -47,6 +47,7 @@ files:
47
47
  - README.rdoc
48
48
  - Rakefile
49
49
  - VERSION
50
+ - examples/twitter.rb
50
51
  - floormanager.gemspec
51
52
  - lib/floormanager.rb
52
53
  - lib/floormanager/queue.rb
@@ -89,3 +90,4 @@ summary: Handle threaded workers like a champ
89
90
  test_files:
90
91
  - spec/floormanager_spec.rb
91
92
  - spec/spec_helper.rb
93
+ - examples/twitter.rb