unified-queues 0.1.0
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/.document +5 -0
- data/CHANGES.txt +3 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +32 -0
- data/LICENSE.txt +20 -0
- data/README.md +88 -0
- data/Rakefile +29 -0
- data/VERSION +1 -0
- data/debug +33 -0
- data/lib/unified-queues.rb +5 -0
- data/lib/unified-queues/multi.rb +209 -0
- data/lib/unified-queues/multi/driver.rb +176 -0
- data/lib/unified-queues/multi/driver/em-jack.rb +200 -0
- data/lib/unified-queues/multi/driver/unified-queues.rb +227 -0
- data/lib/unified-queues/single.rb +178 -0
- data/lib/unified-queues/single/driver.rb +147 -0
- data/lib/unified-queues/single/driver/algorithms.rb +100 -0
- data/lib/unified-queues/single/driver/array.rb +94 -0
- data/lib/unified-queues/single/driver/depq.rb +95 -0
- data/lib/unified-queues/single/driver/evented-queue.rb +96 -0
- data/lib/unified-queues/single/driver/priority_queue.rb +221 -0
- data/lib/unified-queues/single/driver/queue.rb +105 -0
- data/test +297 -0
- metadata +218 -0
data/.document
ADDED
data/CHANGES.txt
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
gem "abstract", ">= 1.0.0"
|
5
|
+
gem "hash-utils", ">= 0.18.1"
|
6
|
+
gem "lookup-hash", ">= 0"
|
7
|
+
|
8
|
+
# Add dependencies to develop your gem here.
|
9
|
+
# Include everything needed to run rake, tests, features, etc.
|
10
|
+
group :development do
|
11
|
+
gem "bundler", ">= 1.0.0"
|
12
|
+
gem "jeweler2", ">= 2.0.0"
|
13
|
+
gem "riot", ">= 0.12.3"
|
14
|
+
gem "PriorityQueue", ">= 0"
|
15
|
+
gem "algorithms", ">= 0"
|
16
|
+
gem "depq", ">= 0"
|
17
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
PriorityQueue (0.1.2)
|
5
|
+
abstract (1.0.0)
|
6
|
+
algorithms (0.3.0)
|
7
|
+
depq (0.6)
|
8
|
+
git (1.2.5)
|
9
|
+
hash-utils (1.0.0)
|
10
|
+
ruby-version
|
11
|
+
jeweler2 (2.0.9)
|
12
|
+
git (>= 1.2.5)
|
13
|
+
lookup-hash (0.2.0)
|
14
|
+
hash-utils (>= 0.11.0)
|
15
|
+
riot (0.12.5)
|
16
|
+
rr
|
17
|
+
rr (1.0.4)
|
18
|
+
ruby-version (0.3.1)
|
19
|
+
|
20
|
+
PLATFORMS
|
21
|
+
ruby
|
22
|
+
|
23
|
+
DEPENDENCIES
|
24
|
+
PriorityQueue
|
25
|
+
abstract (>= 1.0.0)
|
26
|
+
algorithms
|
27
|
+
bundler (>= 1.0.0)
|
28
|
+
depq
|
29
|
+
hash-utils (>= 0.18.1)
|
30
|
+
jeweler2 (>= 2.0.0)
|
31
|
+
lookup-hash
|
32
|
+
riot (>= 0.12.3)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 - 2012 Martin Kozák (martinkozak@martinkozak.net)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
Ruby Unified Queues
|
2
|
+
===================
|
3
|
+
|
4
|
+
**unified-queues** is an unified queue interface which unifies
|
5
|
+
several both normal and priority queue implementations to the single
|
6
|
+
queue API. Usage is simple:
|
7
|
+
|
8
|
+
require "unified-queues"
|
9
|
+
|
10
|
+
# Depq
|
11
|
+
require "depq"
|
12
|
+
depq_queue = UnifiedQueues::Single::new(Depq)
|
13
|
+
|
14
|
+
# Ruby Array
|
15
|
+
array_queue = UnifiedQueues::Single::new(Array)
|
16
|
+
|
17
|
+
# ...the same API!
|
18
|
+
depq_queue.push(:foo)
|
19
|
+
depq_queue.pop! # will return :foo
|
20
|
+
|
21
|
+
array_queue.push(:foo)
|
22
|
+
array_queue.pop! # will return :foo
|
23
|
+
|
24
|
+
Evented queues are also supported by transparent way; simply provide
|
25
|
+
blocks to calls instead of expecting return values. Currently, the
|
26
|
+
following classes are supported:
|
27
|
+
|
28
|
+
* `Queue` and `Array` (from Ruby),
|
29
|
+
* `Depq` (from `depq` gem),
|
30
|
+
* `Containers::Heap` (from `algorithms` gem),
|
31
|
+
* `CPriorityQueue`, `PoorPriorityQueue` and `RubyPriorityQueue` (from `priority_queue` gem),
|
32
|
+
* `EventedQueue` (from `evented-queue` gem).
|
33
|
+
|
34
|
+
And for multiqueues:
|
35
|
+
|
36
|
+
* `UnifiedQueues::Single` (from `unified-queues` gem),
|
37
|
+
* `EMJack::Connection` (from `em-jack` beanstalk gem)
|
38
|
+
|
39
|
+
### Multiqueue Support
|
40
|
+
|
41
|
+
*Multiqueue* is a queue which is composed of more queues and single
|
42
|
+
queue can be selected for writing into or reading from. An example
|
43
|
+
of this type of queues are for example some queue servers which
|
44
|
+
typically contain more than one queue. By this way, an unified queue
|
45
|
+
interface can be implemented for more queue servers too.
|
46
|
+
|
47
|
+
Reasonable example isn't available, but see the [QRPC][1] project
|
48
|
+
where unified multiqueues are implemented.
|
49
|
+
|
50
|
+
Multiqueue driver for single unified queue interface is also
|
51
|
+
implemented, so it's possible to build a multiqueue interface from
|
52
|
+
the common datatypes or Ruby priority queues implementations by
|
53
|
+
an universal and transparent way.
|
54
|
+
|
55
|
+
##### Hardcore example
|
56
|
+
|
57
|
+
Hardcore example can by for example following (bonus points for
|
58
|
+
decoding what it does):
|
59
|
+
|
60
|
+
UnifiedQueues::Multi::new UnifiedQueues::Single, ::EM::Wrapper::new(REUQ), UnifiedQueues::Single, CPriorityQueue
|
61
|
+
|
62
|
+
Well, it creates an unified queue interface from the `CPriorityQueue`
|
63
|
+
library, wraps it to an evented interface (converts standard
|
64
|
+
interface to the evented one), converts it to the evented unified
|
65
|
+
queue interface again and creates a multiqueue interface from it. It
|
66
|
+
may sounds difficulty, but it simply *creates an evented unified
|
67
|
+
multiqueue interface from non-evented proprietary library*. Cool.
|
68
|
+
|
69
|
+
Contributing
|
70
|
+
------------
|
71
|
+
|
72
|
+
1. Fork it.
|
73
|
+
2. Create a branch (`git checkout -b 20101220-my-change`).
|
74
|
+
3. Commit your changes (`git commit -am "Added something"`).
|
75
|
+
4. Push to the branch (`git push origin 20101220-my-change`).
|
76
|
+
5. Create an [Issue][9] with a link to your branch.
|
77
|
+
6. Enjoy a refreshing Diet Coke and wait.
|
78
|
+
|
79
|
+
|
80
|
+
Copyright
|
81
|
+
---------
|
82
|
+
|
83
|
+
Copyright © 2011 - 2012 [Martin Kozák][10]. See `LICENSE.txt` for
|
84
|
+
further details.
|
85
|
+
|
86
|
+
[1]: http://github.com/martinkozak/qrpc
|
87
|
+
[9]: http://github.com/martinkozak/unified-queues/issues
|
88
|
+
[10]: http://www.martinkozak.net/
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler'
|
4
|
+
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'rake'
|
14
|
+
require 'jeweler2'
|
15
|
+
|
16
|
+
Jeweler::Tasks.new do |gem|
|
17
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
18
|
+
gem.name = "unified-queues"
|
19
|
+
gem.homepage = "http://github.com/martinkozak/unified-queue"
|
20
|
+
gem.license = "MIT"
|
21
|
+
gem.summary = 'Unifies many queue implementations under the single interface. Includes both single queue libraries and multiple queue libraries.'
|
22
|
+
gem.email = "martinkozak@martinkozak.net"
|
23
|
+
gem.authors = ["Martin Kozák"]
|
24
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
25
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
26
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
27
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
28
|
+
end
|
29
|
+
Jeweler::RubygemsDotOrgTasks.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/debug
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
4
|
+
|
5
|
+
$:.push("./lib")
|
6
|
+
$:.unshift("./lib")
|
7
|
+
|
8
|
+
require "em-jack"
|
9
|
+
require "unified-queues"
|
10
|
+
require "em-batch"
|
11
|
+
|
12
|
+
EM::run do
|
13
|
+
q = UnifiedQueues::Multi::new(EMJack::Connection)
|
14
|
+
|
15
|
+
queue = EM::Sequencer::new(q)
|
16
|
+
queue.use(:xxx)
|
17
|
+
queue.push("x", 2)
|
18
|
+
queue.push("y", 1)
|
19
|
+
queue.subscribe(:xxx)
|
20
|
+
|
21
|
+
queue.execute do
|
22
|
+
queue = EM::Sequencer::new(q)
|
23
|
+
queue.pop
|
24
|
+
queue.pop
|
25
|
+
queue.pop
|
26
|
+
|
27
|
+
queue.execute do
|
28
|
+
p queue.results
|
29
|
+
|
30
|
+
#q.pop
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "unified-queues/multi/driver"
|
5
|
+
require "hash-utils/module"
|
6
|
+
|
7
|
+
##
|
8
|
+
# Base 9Unified Queues+ module.
|
9
|
+
#
|
10
|
+
|
11
|
+
module UnifiedQueues
|
12
|
+
|
13
|
+
##
|
14
|
+
# More queues single interface.
|
15
|
+
#
|
16
|
+
|
17
|
+
class Multi
|
18
|
+
|
19
|
+
##
|
20
|
+
# Contains assignment of classnames to drivers.
|
21
|
+
# @return [Hash]
|
22
|
+
#
|
23
|
+
|
24
|
+
DRIVERS = Hash[
|
25
|
+
:"UnifiedQueues::Single" => "unified-queues.rb",
|
26
|
+
:"EMJack::Connection" => "em-jack.rb"
|
27
|
+
]
|
28
|
+
|
29
|
+
##
|
30
|
+
# Contains driver for specific class instance.
|
31
|
+
# @return [UnifiedQueues::Multi::Driver] driver instance
|
32
|
+
#
|
33
|
+
|
34
|
+
attr_accessor :driver
|
35
|
+
@driver
|
36
|
+
|
37
|
+
##
|
38
|
+
# Constructor.
|
39
|
+
#
|
40
|
+
# @param [Class|UnifiedQueues::Multi::Driver] cls required class object or driver instance
|
41
|
+
# @param [Array] *args array of arguments for the queue constructor
|
42
|
+
# @param [Proc] &block block for the queue constructor
|
43
|
+
#
|
44
|
+
|
45
|
+
def initialize(cls, *args, &block)
|
46
|
+
if cls.kind_of? UnifiedQueues::Multi::Driver
|
47
|
+
@driver = cls
|
48
|
+
else
|
49
|
+
self.assign_driver(cls, args, block)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Assigns driver to interface according to given class name.
|
55
|
+
#
|
56
|
+
# @param [Class] cls required class
|
57
|
+
# @param [Array] args array of arguments for the queue constructor
|
58
|
+
# @param [Proc] block block for the queue constructor
|
59
|
+
# @return [UnifiedQueues::Multi::Driver] new driver instance
|
60
|
+
#
|
61
|
+
|
62
|
+
def assign_driver(cls, args, block)
|
63
|
+
_cls = cls
|
64
|
+
if not _cls.kind_of? Class
|
65
|
+
_cls = cls.class
|
66
|
+
end
|
67
|
+
|
68
|
+
driver = nil
|
69
|
+
name = nil
|
70
|
+
|
71
|
+
self.class::DRIVERS.each_pair do |_name, _driver|
|
72
|
+
begin
|
73
|
+
_module = Module::get_module(_name.to_s)
|
74
|
+
rescue NameError
|
75
|
+
next
|
76
|
+
end
|
77
|
+
|
78
|
+
if _cls <= _module
|
79
|
+
driver = _driver
|
80
|
+
name = _name
|
81
|
+
break
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
###
|
86
|
+
|
87
|
+
require "unified-queues/multi/driver/" << driver
|
88
|
+
|
89
|
+
path = name.to_s.split("::")
|
90
|
+
classname = path.shift << 'Driver::' << path.join('::')
|
91
|
+
_module = Module::get_module("UnifiedQueues::Multi::Driver::" << classname)
|
92
|
+
|
93
|
+
args = [cls] + args
|
94
|
+
@driver = _module::new(*args, &block)
|
95
|
+
return @driver
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Pushes value to the currently used queue.
|
100
|
+
#
|
101
|
+
# @param [Object] value
|
102
|
+
# @param [Object] key key for priority purposes
|
103
|
+
#
|
104
|
+
|
105
|
+
def push(value, key = value, &block)
|
106
|
+
@driver.push(value, key, &block)
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Pops value from the queue. In contrast to default Queue library,
|
111
|
+
# blocks or returns +nil+ if empty.
|
112
|
+
#
|
113
|
+
# @param [Boolean|Integer] blocking +true+ or timeout if it should block, +false+ otherwise
|
114
|
+
# @return [Object|nil]
|
115
|
+
#
|
116
|
+
|
117
|
+
def pop(blocking = false, &block)
|
118
|
+
@driver.pop(blocking, &block)
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
# Sets queue with given name as used. So marks it as target
|
123
|
+
# for {#push}.
|
124
|
+
#
|
125
|
+
# @param [Object] name name of the required queue
|
126
|
+
#
|
127
|
+
|
128
|
+
def use(name, &block)
|
129
|
+
@driver.use(name, &block)
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Subscribes to the queue. So marks it as target for {#pop}.
|
134
|
+
# Note, than only single queue usally can be subscribed at
|
135
|
+
# one time.
|
136
|
+
#
|
137
|
+
# @param [Object] name name of the required queue
|
138
|
+
#
|
139
|
+
|
140
|
+
def subscribe(name, &block)
|
141
|
+
@driver.subscribe(name, &block)
|
142
|
+
end
|
143
|
+
|
144
|
+
##
|
145
|
+
# Unsubscribes from the queue.
|
146
|
+
# @param [Object] name name of the required queue
|
147
|
+
#
|
148
|
+
|
149
|
+
def unsubscribe(name, &block)
|
150
|
+
@driver.unsubscribe(name, &block)
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Currently used queue.
|
155
|
+
# @return [Queue]
|
156
|
+
#
|
157
|
+
|
158
|
+
def used(&block)
|
159
|
+
@driver.used(&block)
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Currently subscribed queue.
|
164
|
+
# @return [Queue]
|
165
|
+
#
|
166
|
+
|
167
|
+
def subscribed(&block)
|
168
|
+
@driver.subscribed(&block)
|
169
|
+
end
|
170
|
+
|
171
|
+
##
|
172
|
+
# Lists names of all available queues.
|
173
|
+
# @return [Array]
|
174
|
+
#
|
175
|
+
|
176
|
+
def list(&block)
|
177
|
+
@driver.list(&block)
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Lists all used queues.
|
182
|
+
# @return [Array]
|
183
|
+
#
|
184
|
+
|
185
|
+
def list_used(&block)
|
186
|
+
@driver.list_used(&block)
|
187
|
+
end
|
188
|
+
|
189
|
+
##
|
190
|
+
# Lists all subscribed queues.
|
191
|
+
# @return [Array]
|
192
|
+
#
|
193
|
+
|
194
|
+
def list_subscribed(&block)
|
195
|
+
@driver.list_subscribed(&block)
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Closes the session.
|
200
|
+
#
|
201
|
+
|
202
|
+
def close(&block)
|
203
|
+
@driver.close(&block)
|
204
|
+
end
|
205
|
+
|
206
|
+
alias :close! :close
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|