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 +11 -2
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/dequeue_demo.rb +3 -1
- data/enqueue_demo.rb +2 -2
- data/lib/parallel_queue.rb +27 -2
- data/parallel_queue.gemspec +3 -3
- metadata +20 -20
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
|
-
|
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.
|
1
|
+
0.1.1
|
data/dequeue_demo.rb
CHANGED
@@ -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")) }
|
data/enqueue_demo.rb
CHANGED
@@ -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
|
14
|
+
while counter < 40000
|
15
15
|
id = ids.sample
|
16
16
|
queue.enqueue(id, counter)
|
17
17
|
puts "enqueue: #{counter}"
|
data/lib/parallel_queue.rb
CHANGED
@@ -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
|
-
|
99
|
-
|
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:
|
data/parallel_queue.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "parallel_queue"
|
8
|
-
s.version = "0.1.
|
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-
|
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.
|
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-
|
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: &
|
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: *
|
24
|
+
version_requirements: *2161227500
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
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: *
|
35
|
+
version_requirements: *2161261120
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: bundler
|
38
|
-
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: *
|
46
|
+
version_requirements: *2161260240
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: jeweler
|
49
|
-
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: *
|
57
|
+
version_requirements: *2161259560
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: pry
|
60
|
-
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: *
|
68
|
+
version_requirements: *2161258840
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: pry-nav
|
71
|
-
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: *
|
79
|
+
version_requirements: *2161257440
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: pry-stack_explorer
|
82
|
-
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: *
|
91
|
-
description:
|
92
|
-
|
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:
|
131
|
+
hash: 1400047173269459282
|
132
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
133
|
none: false
|
134
134
|
requirements:
|