parallel_queue 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -18,7 +18,14 @@ Example:
18
18
  require 'redis'
19
19
  require 'parallel_queue'
20
20
  redis = Redis.new(:host => '127.0.0.1', :port => '6379')
21
- queue = ParallelQueue.new(redis, 'my_object_message_queue')
21
+ queue = ParallelQueue.new(redis, 'my_object_message_queue', :maxlength => 1000)
22
+ # The optional :maxlength option limits the length of each individual message queue.
23
+ # When a queue that already has maxlength messages receives a new message, the
24
+ # oldest message in that queue is discarded (O(1)).
25
+ # Because there is one queue per message emitter, one queue becoming full has no effect
26
+ # on the remaining queues (no messages will be lost for other emitters unless they,
27
+ # too, reach :maxlength). If maxlength is omitted, then queue length is not
28
+ # artificially limited.
22
29
  queue.enqueue('123', 'hello world')
23
30
  queue.enqueue('peanuts', 'Chalie Brown')
24
31
  queue.enqueue('peanuts', 'Snoopy')
@@ -67,13 +74,15 @@ Terminal 2:
67
74
  Terminal 3 (run the command in terminal 3 after starting 1 & 2):
68
75
 
69
76
  $ ruby enqueue_demo.rb
70
- After a few seconds have passed, press control-c in Terminal 3.
77
+ This will automatically end after enqueueing 40000 times
71
78
  Terminals 1 & 2 will automatically stop when they finish processing
72
79
  the data enqueued by Terminal 3.
73
80
 
74
81
  To check for any common values between d1.txt and d2.txt (there should be none):
75
82
 
76
83
  $ comm -1 -2 d1.txt d2.txt
84
+ should not have any matches (make sure you delete
85
+ the two files between runs)
77
86
 
78
87
 
79
88
 
data/Rakefile CHANGED
@@ -18,7 +18,7 @@ Jeweler::Tasks.new do |gem|
18
18
  gem.homepage = "http://github.com/populr/parallel_queue"
19
19
  gem.license = "MIT"
20
20
  gem.summary = %Q{A thread safe, Redis backed, parallel queue abstraction}
21
- gem.description = %Q{Motivation for creating this was for queueing messages based on ID so that very chatty message emitters don't prevent messages from others from being processed}
21
+ gem.description = %Q{A thread safe, Redis backed, parallel queue abstraction. Motivation for creating this was for queueing messages based on ID so that very chatty message emitters don't prevent messages from others from being processed}
22
22
  gem.email = "daniel@populr.me"
23
23
  gem.authors = ["Daniel Nelson"]
24
24
  # dependencies defined in Gemfile
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -13,11 +13,13 @@ filename = ARGV[0]
13
13
  return puts "File name required" if filename.nil?
14
14
 
15
15
  array = []
16
+ start = nil
16
17
  while array.empty? || queue.queue_count > 0
18
+ start = Time.now if start.nil? && !array.empty?
17
19
  queue.dequeue_each() do |item|
18
20
  array << item.to_i
19
21
  puts "dequeue: #{item}"
20
22
  end
21
23
  end
22
-
24
+ puts Time.now - start
23
25
  File.open(filename, 'w') { |f| f.write(array.sort.join("\n")) }
@@ -7,11 +7,11 @@ require 'pry-nav'
7
7
  require 'pry-stack_explorer'
8
8
 
9
9
  redis = Redis.new(:host => '127.0.0.1', :port => '6379')
10
- queue = ParallelQueue.new(redis, 'demo_queue')
10
+ queue = ParallelQueue.new(redis, 'demo_queue', :maxlength => 1000)
11
11
 
12
12
  counter = 0
13
13
  ids = ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs']
14
- while true
14
+ while counter < 40000
15
15
  id = ids.sample
16
16
  queue.enqueue(id, counter)
17
17
  puts "enqueue: #{counter}"
@@ -45,6 +45,27 @@ class ParallelQueue
45
45
  release_lock
46
46
  item
47
47
  else # couldn't acquire or break the lock. wait and try again
48
+ # A small sleep value is actually faster than no sleep value, presumably because no
49
+ # delay puts too much stress on Redis
50
+ # Experiment:
51
+ # started dequeue_demo.rb in two terminals
52
+ # started enqueue_demo.rb in a third terminal
53
+ # enqueue_demo.rb is set to run until it enqueues 40,000 times
54
+ # dequeue_demo.rb times its run, starting from the first time there is data to
55
+ # dequeue, and running through until all data have been dequeued
56
+ # times reported are the average of both dequeue terminals (which consitently ended
57
+ # within 0.1 second of one another)
58
+ # Sleep Delay Run Duration (in seconds)
59
+ # 0.01 22.6
60
+ # 0.001 22.3
61
+ # no sleep 25.1
62
+ # 0.001 23.8
63
+ # 0.001 23.8
64
+ # 0.01 22.6
65
+ # 0.01 22.7
66
+ # no sleep 25.1
67
+ # no sleep 25.0
68
+ #
48
69
  sleep 0.01
49
70
  dequeue
50
71
  end
@@ -69,6 +90,8 @@ class ParallelQueue
69
90
  self.current_queue_index = 0
70
91
  release_lock
71
92
  else # couldn't acquire or break the lock. wait and try again
93
+ # a small sleep value is actually faster than no sleep value, presumably because no
94
+ # delay puts too much stress on Redis
72
95
  sleep 0.01
73
96
  delete_all!
74
97
  end
@@ -95,8 +118,10 @@ class ParallelQueue
95
118
  end
96
119
 
97
120
  def current_queue_index # :nodoc:
98
- return 0 if queue_count == 0
99
- @current_queue_index % queue_count
121
+ # in a multi-threaded environment, queue_count can go from non-zero to zero
122
+ # between a conditional check and the mod computation, so rescue the exception
123
+ # rather than trying to prevent it
124
+ @current_queue_index % queue_count rescue 0
100
125
  end
101
126
 
102
127
  def current_queue_index=(index) # :nodoc:
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "parallel_queue"
8
- s.version = "0.1.0"
8
+ s.version = "0.1.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Daniel Nelson"]
12
- s.date = "2012-05-11"
13
- s.description = "Motivation for creating this was for queueing messages based on ID so that very chatty message emitters don't prevent messages from others from being processed"
12
+ s.date = "2012-05-14"
13
+ s.description = "A thread safe, Redis backed, parallel queue abstraction. Motivation for creating this was for queueing messages based on ID so that very chatty message emitters don't prevent messages from others from being processed"
14
14
  s.email = "daniel@populr.me"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel_queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-11 00:00:00.000000000 Z
12
+ date: 2012-05-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
16
- requirement: &2161456900 !ruby/object:Gem::Requirement
16
+ requirement: &2161227500 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2161456900
24
+ version_requirements: *2161227500
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &2161489940 !ruby/object:Gem::Requirement
27
+ requirement: &2161261120 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2161489940
35
+ version_requirements: *2161261120
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bundler
38
- requirement: &2161488860 !ruby/object:Gem::Requirement
38
+ requirement: &2161260240 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2161488860
46
+ version_requirements: *2161260240
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: jeweler
49
- requirement: &2161488220 !ruby/object:Gem::Requirement
49
+ requirement: &2161259560 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2161488220
57
+ version_requirements: *2161259560
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: pry
60
- requirement: &2161487480 !ruby/object:Gem::Requirement
60
+ requirement: &2161258840 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2161487480
68
+ version_requirements: *2161258840
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: pry-nav
71
- requirement: &2161486340 !ruby/object:Gem::Requirement
71
+ requirement: &2161257440 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2161486340
79
+ version_requirements: *2161257440
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: pry-stack_explorer
82
- requirement: &2161483620 !ruby/object:Gem::Requirement
82
+ requirement: &2161254620 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *2161483620
91
- description: Motivation for creating this was for queueing messages based on ID so
92
- that very chatty message emitters don't prevent messages from others from being
93
- processed
90
+ version_requirements: *2161254620
91
+ description: A thread safe, Redis backed, parallel queue abstraction. Motivation for
92
+ creating this was for queueing messages based on ID so that very chatty message
93
+ emitters don't prevent messages from others from being processed
94
94
  email: daniel@populr.me
95
95
  executables: []
96
96
  extensions: []
@@ -128,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
128
128
  version: '0'
129
129
  segments:
130
130
  - 0
131
- hash: -1593146586268589980
131
+ hash: 1400047173269459282
132
132
  required_rubygems_version: !ruby/object:Gem::Requirement
133
133
  none: false
134
134
  requirements: