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
@@ -0,0 +1,176 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "abstract"
|
5
|
+
|
6
|
+
|
7
|
+
##
|
8
|
+
# Base +Unified Queues+ module.
|
9
|
+
#
|
10
|
+
|
11
|
+
module UnifiedQueues
|
12
|
+
|
13
|
+
##
|
14
|
+
# More queues single interface.
|
15
|
+
#
|
16
|
+
|
17
|
+
class Multi
|
18
|
+
|
19
|
+
##
|
20
|
+
# Abstract multi driver class.
|
21
|
+
# @abstract
|
22
|
+
#
|
23
|
+
|
24
|
+
class Driver
|
25
|
+
|
26
|
+
##
|
27
|
+
# Holds native object.
|
28
|
+
# @return [Object]
|
29
|
+
#
|
30
|
+
|
31
|
+
attr_accessor :native
|
32
|
+
@native
|
33
|
+
|
34
|
+
##
|
35
|
+
# Constructor.
|
36
|
+
#
|
37
|
+
|
38
|
+
def initialize(cls, *args, &block)
|
39
|
+
if self.instance_of? UniversalQueues::Multi::Driver
|
40
|
+
not_implemented
|
41
|
+
end
|
42
|
+
|
43
|
+
if cls.kind_of? Class
|
44
|
+
@native = cls::new(*args, &block)
|
45
|
+
else
|
46
|
+
@native = cls
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Pushes value to the currently used queue.
|
52
|
+
#
|
53
|
+
# @param [Object] value
|
54
|
+
# @abstract
|
55
|
+
#
|
56
|
+
|
57
|
+
def push(value, &block)
|
58
|
+
not_implemented
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Pops value from the queue. In contrast to default Queue library,
|
63
|
+
# blocks or returns +nil+ if empty.
|
64
|
+
#
|
65
|
+
# @param [Boolean|Integer] blocking +true+ or timeout if it should block, +false+ otherwise
|
66
|
+
# @return [Object|nil]
|
67
|
+
# @abstract
|
68
|
+
#
|
69
|
+
|
70
|
+
def pop(blocking = false, &block)
|
71
|
+
not_implemented
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Sets queue with given name as used. So marks it as target
|
76
|
+
# for {#push}.
|
77
|
+
#
|
78
|
+
# @param [Object] name name of the required queue
|
79
|
+
# @abstract
|
80
|
+
#
|
81
|
+
|
82
|
+
def use(name, &block)
|
83
|
+
not_implemented
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Subscribes to the queue. So marks it as target for {#pop}.
|
88
|
+
# Note, than only single queue can be subscribed at one time.
|
89
|
+
#
|
90
|
+
# @param [Object] name name of the required queue
|
91
|
+
# @abstract
|
92
|
+
#
|
93
|
+
|
94
|
+
def subscribe(name, &block)
|
95
|
+
not_implemented
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Unsubscribes from the queue.
|
100
|
+
#
|
101
|
+
# @param [Object] name name of the required queue\
|
102
|
+
# @abstract
|
103
|
+
#
|
104
|
+
|
105
|
+
def unsubscribe(name, &block)
|
106
|
+
not_implemented
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Currently used queue.
|
111
|
+
#
|
112
|
+
# @return [Queue]
|
113
|
+
# @abstract
|
114
|
+
#
|
115
|
+
|
116
|
+
def used(&block)
|
117
|
+
not_implemented
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# Currently subscribed queue.
|
122
|
+
#
|
123
|
+
# @return [UniversalQueues::Single]
|
124
|
+
# @abstract
|
125
|
+
#
|
126
|
+
|
127
|
+
def subscribed(&block)
|
128
|
+
not_implemented
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# Lists names of all available queues.
|
133
|
+
#
|
134
|
+
# @return [Array]
|
135
|
+
# @abstract
|
136
|
+
#
|
137
|
+
|
138
|
+
def list(&block)
|
139
|
+
not_implemented
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Lists all used queues.
|
144
|
+
#
|
145
|
+
# @return [Array]
|
146
|
+
# @abstract
|
147
|
+
#
|
148
|
+
|
149
|
+
def list_used(&block)
|
150
|
+
not_implemented
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Lists all subscribed queues.
|
155
|
+
#
|
156
|
+
# @return [Array]
|
157
|
+
# @abstract
|
158
|
+
#
|
159
|
+
|
160
|
+
def list_subscribed(&block)
|
161
|
+
not_implemented
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# Closes the session.
|
166
|
+
#
|
167
|
+
|
168
|
+
def close(&block)
|
169
|
+
yield if not block.nil?
|
170
|
+
end
|
171
|
+
|
172
|
+
alias :close! :close
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "hash-utils/array"
|
5
|
+
require "hash-utils/object"
|
6
|
+
require "lookup-hash"
|
7
|
+
|
8
|
+
##
|
9
|
+
# Base +Unified Queues+ module.
|
10
|
+
#
|
11
|
+
|
12
|
+
module UnifiedQueues
|
13
|
+
|
14
|
+
##
|
15
|
+
# Universal multi queue interface.
|
16
|
+
#
|
17
|
+
|
18
|
+
class Multi
|
19
|
+
|
20
|
+
##
|
21
|
+
# Abstract multi driver class.
|
22
|
+
# @abstract
|
23
|
+
#
|
24
|
+
|
25
|
+
class Driver
|
26
|
+
|
27
|
+
##
|
28
|
+
# Wraper according to +UnifiedQueues::Single+ internal structure.
|
29
|
+
#
|
30
|
+
|
31
|
+
module EMJackDriver
|
32
|
+
|
33
|
+
##
|
34
|
+
# Multi queue driver for unified queues single queue interface.
|
35
|
+
#
|
36
|
+
|
37
|
+
class Connection < Driver
|
38
|
+
|
39
|
+
##
|
40
|
+
# Holds native connection object.
|
41
|
+
# @return EMJack::Connection
|
42
|
+
#
|
43
|
+
|
44
|
+
@native
|
45
|
+
|
46
|
+
##
|
47
|
+
# Tracks currently used queue name.
|
48
|
+
# @return Object
|
49
|
+
#
|
50
|
+
|
51
|
+
@used_name
|
52
|
+
|
53
|
+
##
|
54
|
+
# Tracks currently subscribed queue names.
|
55
|
+
# @return [LookupHash]
|
56
|
+
#
|
57
|
+
|
58
|
+
@subscribed_names
|
59
|
+
|
60
|
+
##
|
61
|
+
# Constructor.
|
62
|
+
#
|
63
|
+
|
64
|
+
def initialize(cls, *args, &block)
|
65
|
+
@native = cls::new(*args, &block)
|
66
|
+
@subscribed_names = LookupHash["default"]
|
67
|
+
@used_name = "default"
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Pushes value to the currently used queue.
|
72
|
+
#
|
73
|
+
# @param [Object] value
|
74
|
+
# @param [Integer] key key for priority queues
|
75
|
+
#
|
76
|
+
|
77
|
+
def push(value, key = value, &block)
|
78
|
+
@native.put(value, :priority => key, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Pops value from the queue. Callback is recurring, so it will
|
83
|
+
# keep callback active after +#pop+.
|
84
|
+
#
|
85
|
+
# @param [Boolean] blocking indicates, it should block or not
|
86
|
+
# @return [Object, nil]
|
87
|
+
#
|
88
|
+
|
89
|
+
def pop(blocking = false, &block)
|
90
|
+
timeout = blocking ? nil : 0
|
91
|
+
@native.each_job(timeout) do |job|
|
92
|
+
result = job.body
|
93
|
+
job.delete do
|
94
|
+
yield result
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Sets queue with given name as used. So marks it as target
|
101
|
+
# for {#push}.
|
102
|
+
#
|
103
|
+
# @param [Object] name name of the required queue
|
104
|
+
#
|
105
|
+
|
106
|
+
def use(name, &block)
|
107
|
+
if name != @used_name
|
108
|
+
@used_name = name
|
109
|
+
@native.use(name, &block)
|
110
|
+
elsif not block.nil?
|
111
|
+
EM::next_tick do
|
112
|
+
yield
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# Subscribes to the queue. So marks it as target for {#pop}.
|
119
|
+
# Note, than only single queue can be subscribed at one time.
|
120
|
+
#
|
121
|
+
# @param [Object] name name of the required queue
|
122
|
+
#
|
123
|
+
|
124
|
+
def subscribe(name, &block)
|
125
|
+
if not name.in? @subscribed_names
|
126
|
+
@subscribed_names << name
|
127
|
+
@native.watch(name, &block)
|
128
|
+
elsif not block.nil?
|
129
|
+
EM::next_tick do
|
130
|
+
yield
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# Unsubscribes from the queue.
|
137
|
+
# @param [Object] name name of the required queue\
|
138
|
+
#
|
139
|
+
|
140
|
+
def unsubscribe(name, &block)
|
141
|
+
if name.in? @subscribed_names
|
142
|
+
@subscribed_names.delete name
|
143
|
+
@native.ignore(name, &block)
|
144
|
+
elsif not block.nil?
|
145
|
+
EM::next_tick do
|
146
|
+
yield
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# Currently used queue.
|
153
|
+
# @return [Queue]
|
154
|
+
#
|
155
|
+
|
156
|
+
def used
|
157
|
+
yield self
|
158
|
+
end
|
159
|
+
|
160
|
+
##
|
161
|
+
# Currently subscribed queue.
|
162
|
+
# @return [Queue]
|
163
|
+
#
|
164
|
+
|
165
|
+
def subscribed
|
166
|
+
yield self
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Lists names of all available queues.
|
171
|
+
# @return [Array]
|
172
|
+
#
|
173
|
+
|
174
|
+
def list(&block)
|
175
|
+
@native.list(&block)
|
176
|
+
end
|
177
|
+
|
178
|
+
##
|
179
|
+
# Lists all used queues.
|
180
|
+
# @return [Array]
|
181
|
+
#
|
182
|
+
|
183
|
+
def list_used(&block)
|
184
|
+
@native.list(:used, &block)
|
185
|
+
end
|
186
|
+
|
187
|
+
##
|
188
|
+
# Lists all subscribed queues.
|
189
|
+
# @return [Array]
|
190
|
+
#
|
191
|
+
|
192
|
+
def list_subscribed(&block)
|
193
|
+
@native.list(:watched, &block)
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "hash-utils/array"
|
5
|
+
require "hash-utils/object"
|
6
|
+
|
7
|
+
##
|
8
|
+
# Base +Unified Queues+ module.
|
9
|
+
#
|
10
|
+
|
11
|
+
module UnifiedQueues
|
12
|
+
|
13
|
+
##
|
14
|
+
# Universal multi queue interface.
|
15
|
+
#
|
16
|
+
|
17
|
+
class Multi
|
18
|
+
|
19
|
+
##
|
20
|
+
# Abstract multi driver class.
|
21
|
+
# @abstract
|
22
|
+
#
|
23
|
+
|
24
|
+
class Driver
|
25
|
+
|
26
|
+
##
|
27
|
+
# Wraper according to +UnifiedQueues::Single+ internal structure.
|
28
|
+
#
|
29
|
+
|
30
|
+
module UnifiedQueuesDriver
|
31
|
+
|
32
|
+
##
|
33
|
+
# Multi queue driver for unified queues single queue interface.
|
34
|
+
#
|
35
|
+
|
36
|
+
class Single < Driver
|
37
|
+
|
38
|
+
##
|
39
|
+
# Holds available queues.
|
40
|
+
# @return Hash
|
41
|
+
#
|
42
|
+
|
43
|
+
@queues
|
44
|
+
|
45
|
+
##
|
46
|
+
# Holds default queue class.
|
47
|
+
# @return [Class]
|
48
|
+
#
|
49
|
+
|
50
|
+
@class
|
51
|
+
|
52
|
+
##
|
53
|
+
# Contains currently used queue specification.
|
54
|
+
# @return Array
|
55
|
+
#
|
56
|
+
|
57
|
+
@used
|
58
|
+
|
59
|
+
##
|
60
|
+
# Contains currently subscribed queue specification.
|
61
|
+
# @return Array
|
62
|
+
#
|
63
|
+
|
64
|
+
@subscribed
|
65
|
+
|
66
|
+
##
|
67
|
+
# Constructor.
|
68
|
+
#
|
69
|
+
|
70
|
+
def initialize(cls, *args, &block)
|
71
|
+
@queues = { }
|
72
|
+
@class = [cls, args, block]
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Pushes value to the currently used queue.
|
77
|
+
#
|
78
|
+
# @param [Object] value
|
79
|
+
# @param [Object] key key for priority queues
|
80
|
+
#
|
81
|
+
|
82
|
+
def push(value, key = value, &block)
|
83
|
+
self.used.push(value, key, &block)
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Pops value from the queue. In contrast to default Queue library,
|
88
|
+
# blocks or returns +nil+ if empty.
|
89
|
+
#
|
90
|
+
# @param [Boolean|Integer] blocking +true+ or timeout if it should block, +false+ otherwise
|
91
|
+
# @return [Object|nil]
|
92
|
+
#
|
93
|
+
|
94
|
+
def pop(blocking = false, &block)
|
95
|
+
self.subscribed.pop(blocking, &block)
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Creates new queue under given name.
|
100
|
+
#
|
101
|
+
# @param [Object] name identification
|
102
|
+
# @return [Queue] new queue
|
103
|
+
#
|
104
|
+
|
105
|
+
def create(name, cls = @class)
|
106
|
+
if not name.in? @queues
|
107
|
+
self[name] = cls.first::new(*cls.second, &cls.third)
|
108
|
+
else
|
109
|
+
self[name]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Inserts queue instance to queues.
|
115
|
+
#
|
116
|
+
# @param [Object] name identification
|
117
|
+
# @param [Containers::Heap] queue heap instance
|
118
|
+
#
|
119
|
+
|
120
|
+
def insert(name, queue)
|
121
|
+
@queues[name] = queue
|
122
|
+
end
|
123
|
+
|
124
|
+
alias :[]= :insert
|
125
|
+
|
126
|
+
##
|
127
|
+
# Returns named queue from instance.
|
128
|
+
# @param [Object] name queue name
|
129
|
+
#
|
130
|
+
|
131
|
+
def get(name)
|
132
|
+
@queues[name]
|
133
|
+
end
|
134
|
+
|
135
|
+
alias :[] :get
|
136
|
+
|
137
|
+
##
|
138
|
+
# Sets queue with given name as used. So marks it as target
|
139
|
+
# for {#push}.
|
140
|
+
#
|
141
|
+
# @param [Object] name name of the required queue
|
142
|
+
#
|
143
|
+
|
144
|
+
def use(name, &block)
|
145
|
+
self.create(name)
|
146
|
+
@used = [name, self[name]]
|
147
|
+
yield if not block.nil?
|
148
|
+
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# Subscribes to the queue. So marks it as target for {#pop}.
|
152
|
+
# Note, than only single queue can be subscribed at one time.
|
153
|
+
#
|
154
|
+
# @param [Object] name name of the required queue
|
155
|
+
#
|
156
|
+
|
157
|
+
def subscribe(name, &block)
|
158
|
+
self.create(name)
|
159
|
+
@subscribed = [name, self[name]]
|
160
|
+
yield if not block.nil?
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Unsubscribes from the queue.
|
165
|
+
# @param [Object] name name of the required queue\
|
166
|
+
#
|
167
|
+
|
168
|
+
def unsubscribe(name, &block)
|
169
|
+
if not @subscribed.nil? and (@subscribed.first == name)
|
170
|
+
@subscribed = nil
|
171
|
+
end
|
172
|
+
|
173
|
+
yield if not block.nil?
|
174
|
+
end
|
175
|
+
|
176
|
+
##
|
177
|
+
# Currently used queue.
|
178
|
+
# @return [Queue]
|
179
|
+
#
|
180
|
+
|
181
|
+
def used(&block)
|
182
|
+
yield @used.second if not block.nil?
|
183
|
+
return @used.second
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Currently subscribed queue.
|
188
|
+
# @return [Queue]
|
189
|
+
#
|
190
|
+
|
191
|
+
def subscribed(&block)
|
192
|
+
yield @subscribed.second if not block.nil?
|
193
|
+
return @subscribed.second
|
194
|
+
end
|
195
|
+
|
196
|
+
##
|
197
|
+
# Lists names of all available queues.
|
198
|
+
# @return [Array]
|
199
|
+
#
|
200
|
+
|
201
|
+
def list
|
202
|
+
@queues.keys
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Lists all used queues.
|
207
|
+
# @return [Array]
|
208
|
+
#
|
209
|
+
|
210
|
+
def list_used
|
211
|
+
[@used.first]
|
212
|
+
end
|
213
|
+
|
214
|
+
##
|
215
|
+
# Lists all subscribed queues.
|
216
|
+
# @return [Array]
|
217
|
+
#
|
218
|
+
|
219
|
+
def list_subscribed
|
220
|
+
[@subscribed.first]
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|