ruote-beanstalk 2.1.10 → 2.1.11

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.
@@ -1,147 +1,3 @@
1
- #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in
12
- # all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #
22
- # Made in Japan.
23
- #++
24
1
 
25
- require 'beanstalk-client'
26
-
27
- #require 'ruote/part/local_participant'
28
-
29
-
30
- module Ruote
31
- module Beanstalk
32
-
33
- #
34
- # This participant emits workitems towards a beanstalk queue.
35
- #
36
- # engine.register_participant(
37
- # :heavy_labour,
38
- # :reply_by_default => true, :beanstalk => '127.0.0.1:11300')
39
- #
40
- #
41
- # == workitem format
42
- #
43
- # Workitems are encoded in the format
44
- #
45
- # [ 'workitem', workitem.to_h ]
46
- #
47
- # and then serialized as JSON strings.
48
- #
49
- #
50
- # == cancel items
51
- #
52
- # Like workitems, but the format is
53
- #
54
- # [ 'cancelitem', fei.to_h, flavour.to_s ]
55
- #
56
- # where fei is the FlowExpressionId of the expression getting cancelled
57
- # (and whose workitems are to be retired) and flavour is either 'cancel' or
58
- # 'kill'.
59
- #
60
- #
61
- # == extending this participant
62
- #
63
- # Extend and overwrite encode_workitem and encode_cancelitem or
64
- # simply re-open the class and change those methods.
65
- #
66
- #
67
- # == :beanstalk
68
- #
69
- # Indicates which beanstalk to talk to
70
- #
71
- # engine.register_participant(
72
- # 'alice'
73
- # Ruote::Beanstalk::BsParticipant,
74
- # 'beanstalk' => '127.0.0.1:11300')
75
- #
76
- #
77
- # == :tube
78
- #
79
- # Most of the time, you want the workitems (or the cancelitems) to be
80
- # emitted over/in a specific tube
81
- #
82
- # engine.register_participant(
83
- # 'alice'
84
- # Ruote::Beanstalk::BsParticipant,
85
- # 'beanstalk' => '127.0.0.1:11300',
86
- # 'tube' => 'ruote-workitems')
87
- #
88
- #
89
- # == :reply_by_default
90
- #
91
- # If the participant is configured with 'reply_by_default' => true, the
92
- # participant will dispatch the workitem over to Beanstalk and then
93
- # immediately reply to its ruote engine (letting the flow resume).
94
- #
95
- # engine.register_participant(
96
- # 'alice'
97
- # Ruote::Beanstalk::BsParticipant,
98
- # 'beanstalk' => '127.0.0.1:11300',
99
- # 'reply_by_default' => true)
100
- #
101
- class BsParticipant
102
-
103
- include Ruote::LocalParticipant
104
-
105
- def initialize (opts)
106
-
107
- @opts = opts
108
- end
109
-
110
- def consume (workitem)
111
-
112
- connection.put(encode_workitem(workitem))
113
-
114
- reply(workitem) if @opts['reply_by_default']
115
- end
116
-
117
- def cancel (fei, flavour)
118
-
119
- connection.put(encode_cancelitem(fei, flavour))
120
- end
121
-
122
- def encode_workitem (workitem)
123
-
124
- Rufus::Json.encode([ 'workitem', workitem.to_h ])
125
- end
126
-
127
- def encode_cancelitem (fei, flavour)
128
-
129
- Rufus::Json.encode([ 'cancelitem', fei.to_h, flavour.to_s ])
130
- end
131
-
132
- protected
133
-
134
- def connection
135
-
136
- con = ::Beanstalk::Connection.new(@opts['beanstalk'])
137
-
138
- if tube = @opts['tube']
139
- con.use(tube)
140
- end
141
-
142
- con
143
- end
144
- end
145
- end
146
- end
2
+ require 'ruote/beanstalk/participant_proxy'
147
3
 
@@ -0,0 +1,157 @@
1
+ #--
2
+ # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+ require 'beanstalk-client'
26
+
27
+ #require 'ruote/part/local_participant'
28
+
29
+
30
+ module Ruote
31
+ module Beanstalk
32
+
33
+ #
34
+ # This participant emits workitems towards a beanstalk queue.
35
+ #
36
+ # engine.register_participant(
37
+ # :heavy_labour,
38
+ # :reply_by_default => true, :beanstalk => '127.0.0.1:11300')
39
+ #
40
+ #
41
+ # == workitem format
42
+ #
43
+ # Workitems are encoded in the format
44
+ #
45
+ # [ 'workitem', workitem.to_h ]
46
+ #
47
+ # and then serialized as JSON strings.
48
+ #
49
+ #
50
+ # == cancel items
51
+ #
52
+ # Like workitems, but the format is
53
+ #
54
+ # [ 'cancelitem', fei.to_h, flavour.to_s ]
55
+ #
56
+ # where fei is the FlowExpressionId of the expression getting cancelled
57
+ # (and whose workitems are to be retired) and flavour is either 'cancel' or
58
+ # 'kill'.
59
+ #
60
+ #
61
+ # == extending this participant
62
+ #
63
+ # Extend and overwrite encode_workitem and encode_cancelitem or
64
+ # simply re-open the class and change those methods.
65
+ #
66
+ #
67
+ # == :beanstalk
68
+ #
69
+ # Indicates which beanstalk to talk to
70
+ #
71
+ # engine.register_participant(
72
+ # 'alice'
73
+ # Ruote::Beanstalk::ParticipantProxy,
74
+ # 'beanstalk' => '127.0.0.1:11300')
75
+ #
76
+ #
77
+ # == :tube
78
+ #
79
+ # Most of the time, you want the workitems (or the cancelitems) to be
80
+ # emitted over/in a specific tube
81
+ #
82
+ # engine.register_participant(
83
+ # 'alice'
84
+ # Ruote::Beanstalk::ParticipantProxy,
85
+ # 'beanstalk' => '127.0.0.1:11300',
86
+ # 'tube' => 'ruote-workitems')
87
+ #
88
+ #
89
+ # == :reply_by_default
90
+ #
91
+ # If the participant is configured with 'reply_by_default' => true, the
92
+ # participant will dispatch the workitem over to Beanstalk and then
93
+ # immediately reply to its ruote engine (letting the flow resume).
94
+ #
95
+ # engine.register_participant(
96
+ # 'alice'
97
+ # Ruote::Beanstalk::ParticipantProxy,
98
+ # 'beanstalk' => '127.0.0.1:11300',
99
+ # 'reply_by_default' => true)
100
+ #
101
+ class ParticipantProxy
102
+
103
+ include Ruote::LocalParticipant
104
+
105
+ def initialize(opts)
106
+
107
+ @opts = opts
108
+ end
109
+
110
+ def consume(workitem)
111
+
112
+ con = new_connection
113
+
114
+ con.put(encode_workitem(workitem))
115
+
116
+ reply(workitem) if @opts['reply_by_default']
117
+
118
+ ensure
119
+ con.close rescue nil
120
+ end
121
+
122
+ def cancel(fei, flavour)
123
+
124
+ con = new_connection
125
+
126
+ con.put(encode_cancelitem(fei, flavour))
127
+
128
+ ensure
129
+ con.close rescue nil
130
+ end
131
+
132
+ def encode_workitem(workitem)
133
+
134
+ Rufus::Json.encode([ 'workitem', workitem.to_h ])
135
+ end
136
+
137
+ def encode_cancelitem(fei, flavour)
138
+
139
+ Rufus::Json.encode([ 'cancelitem', fei.to_h, flavour.to_s ])
140
+ end
141
+
142
+ protected
143
+
144
+ def new_connection
145
+
146
+ con = ::Beanstalk::Connection.new(@opts['beanstalk'])
147
+
148
+ if tube = @opts['tube']
149
+ con.use(tube)
150
+ end
151
+
152
+ con
153
+ end
154
+ end
155
+ end
156
+ end
157
+
@@ -33,29 +33,29 @@ module Beanstalk
33
33
  #
34
34
  # An error class for error emitted by the "remote side" and received here.
35
35
  #
36
- class BsReceiveError < RuntimeError
36
+ class ReceiveError < RuntimeError
37
37
 
38
38
  attr_reader :fei
39
39
 
40
- def initialize (fei)
40
+ def initialize(fei)
41
41
  @fei = fei
42
42
  super("for #{Ruote::FlowExpressionId.to_storage_id(fei)}")
43
43
  end
44
44
  end
45
45
 
46
46
  #
47
- # Whereas BsParticipant emits workitems (and cancelitems) to a Beanstalk
47
+ # Whereas ParticipantProxy emits workitems(and cancelitems) to a Beanstalk
48
48
  # queue, the receiver watches a Beanstalk queue/tube.
49
49
  #
50
50
  # An example initialization :
51
51
  #
52
- # Ruote::Beanstalk::BsReceiver.new(
52
+ # Ruote::Beanstalk::Receiver.new(
53
53
  # engine, '127.0.0.1:11300', :tube => 'out')
54
54
  #
55
55
  #
56
56
  # == workitem format
57
57
  #
58
- # BsParticipant and BsReceiver share the same format :3
58
+ # ParticipantProxy and Receiver share the same format :3
59
59
  #
60
60
  # [ 'workitem', workitem_as_a_hash ]
61
61
  # # or
@@ -72,14 +72,14 @@ module Beanstalk
72
72
  #
73
73
  # Indicates to the receiver which beanstalk tube it should listen to.
74
74
  #
75
- # Ruote::Beanstalk::BsReceiver.new(
75
+ # Ruote::Beanstalk::Receiver.new(
76
76
  # engine, '127.0.0.1:11300', :tube => 'out')
77
77
  #
78
- class BsReceiver < Ruote::Receiver
78
+ class Receiver < ::Ruote::Receiver
79
79
 
80
80
  # cwes = context, worker, engine or storage
81
81
  #
82
- def initialize (cwes, beanstalk, options={})
82
+ def initialize(cwes, beanstalk, options={})
83
83
 
84
84
  super(cwes, options)
85
85
 
@@ -90,7 +90,7 @@ module Beanstalk
90
90
 
91
91
  protected
92
92
 
93
- def listen (beanstalk, tube)
93
+ def listen(beanstalk, tube)
94
94
 
95
95
  con = ::Beanstalk::Connection.new(beanstalk)
96
96
  con.watch(tube)
@@ -108,31 +108,31 @@ module Beanstalk
108
108
  end
109
109
 
110
110
  # Is meant to return a hash with a first element that is either
111
- # 'workitem', 'error' or 'launchitem' (a type).
111
+ # 'workitem', 'error' or 'launchitem'(a type).
112
112
  # The second element depends on the type.
113
- # It's mappend on Ruote::Beanstalk::BsParticipant anyway.
113
+ # It's mappend on Ruote::Beanstalk::ParticipantProxy anyway.
114
114
  #
115
- def decode (job)
115
+ def decode(job)
116
116
 
117
117
  Rufus::Json.decode(job.body)
118
118
  end
119
119
 
120
- def process (job)
120
+ def process(job)
121
121
 
122
122
  type, data = decode(job)
123
123
 
124
124
  if type == 'workitem'
125
125
 
126
- # data holds a workitem (as a Hash)
126
+ # data holds a workitem(as a Hash)
127
127
 
128
128
  reply(data)
129
129
 
130
130
  elsif type == 'error'
131
131
 
132
- # data holds a fei (FlowExpressionId) (as a Hash)
132
+ # data holds a fei(FlowExpressionId) (as a Hash)
133
133
 
134
134
  @context.error_handler.action_handle(
135
- 'dispatch', data, BsReceiveError.new(data))
135
+ 'dispatch', data, ReceiveError.new(data))
136
136
 
137
137
  elsif type == 'launchitem'
138
138
 
@@ -33,7 +33,7 @@ module Beanstalk
33
33
  #
34
34
  # An error class just for BsStorage.
35
35
  #
36
- class BsStorageError < RuntimeError
36
+ class StorageError < RuntimeError
37
37
  end
38
38
 
39
39
  #
@@ -47,9 +47,9 @@ module Beanstalk
47
47
  #
48
48
  # engine = Ruote::Engine.new(
49
49
  # Ruote::Worker.new(
50
- # Ruote::Beanstalk::BsStorage.new('127.0.0.1:11300', opts)))
50
+ # Ruote::Beanstalk::Storage.new('127.0.0.1:11300', opts)))
51
51
  #
52
- # All the operations (put, get, get_many, ...) of the storage are done
52
+ # All the operations(put, get, get_many, ...) of the storage are done
53
53
  # by a server, connected to the same beanstalk queue.
54
54
  #
55
55
  # == server
@@ -57,7 +57,7 @@ module Beanstalk
57
57
  # The storage point to a beanstalk queue and receives orders from clients
58
58
  # via the queue.
59
59
  #
60
- # Ruote::Beanstalk::BsStorage.new(':11300', 'ruote_work', :fork => true)
60
+ # Ruote::Beanstalk::Storage.new(':11300', 'ruote_work', :fork => true)
61
61
  #
62
62
  # Note the directory passed as a string. When in server mode, this storage
63
63
  # uses an embedded Ruote::FsStorage for the actual storage.
@@ -66,11 +66,11 @@ module Beanstalk
66
66
  # the Beanstalk server. The storage takes care of stopping the beanstalk
67
67
  # server when the Ruby process exits.
68
68
  #
69
- class BsStorage
69
+ class Storage
70
70
 
71
71
  include Ruote::StorageBase
72
72
 
73
- def initialize (uri, directory=nil, options=nil)
73
+ def initialize(uri, directory=nil, options=nil)
74
74
 
75
75
  @uri, address, port = split_uri(uri)
76
76
 
@@ -113,7 +113,21 @@ module Beanstalk
113
113
  serve if @cloche
114
114
  end
115
115
 
116
- def put (doc, opts={})
116
+ # One catch : will return [] in case of [network] error
117
+ #
118
+ def get_msgs
119
+
120
+ super rescue []
121
+ end
122
+
123
+ # One catch : will return true (failure) in case of [network] error
124
+ #
125
+ def reserve(doc)
126
+
127
+ super(doc) rescue true
128
+ end
129
+
130
+ def put(doc, opts={})
117
131
 
118
132
  doc.merge!('put_at' => Ruote.now_to_utc_s)
119
133
 
@@ -123,33 +137,40 @@ module Beanstalk
123
137
 
124
138
  return r unless r.nil?
125
139
 
126
- doc['_rev'] = (doc['_rev'] || -1) + 1 if opts[:update_rev]
140
+ doc['_rev'] =(doc['_rev'] || -1) + 1 if opts[:update_rev]
127
141
 
128
142
  nil
129
143
  end
130
144
 
131
- def get (type, key)
145
+ def get(type, key)
132
146
 
133
147
  return @cloche.get(type, key) if @cloche
134
148
 
135
149
  operate('get', [ type, key ])
136
150
  end
137
151
 
138
- def delete (doc)
152
+ def delete(doc)
139
153
 
140
154
  return @cloche.delete(doc) if @cloche
141
155
 
142
156
  operate('delete', [ doc ])
143
157
  end
144
158
 
145
- def get_many (type, key=nil, opts={})
159
+ def get_many(type, key=nil, opts={})
146
160
 
147
- return @cloche.get_many(type, key, opts) if @cloche
161
+ return operate('get_many', [ type, key, opts ]) unless @cloche
162
+
163
+ if key
164
+ key = Array(key).collect { |k|
165
+ k[0..6] == '(?-mix:' ? Regexp.new(k[7..-2]) : "!#{k}"
166
+ } if key
167
+ end
168
+ # assuming /!#{wfid}$/...
148
169
 
149
- operate('get_many', [ type, key, opts ])
170
+ @cloche.get_many(type, key, opts)
150
171
  end
151
172
 
152
- def ids (type)
173
+ def ids(type)
153
174
 
154
175
  return @cloche.ids(type) if @cloche
155
176
 
@@ -165,7 +186,7 @@ module Beanstalk
165
186
  end
166
187
  end
167
188
 
168
- def dump (type)
189
+ def dump(type)
169
190
 
170
191
  get_many(type)
171
192
  end
@@ -174,23 +195,28 @@ module Beanstalk
174
195
 
175
196
  Thread.list.each do |t|
176
197
  t.keys.each do |k|
177
- next unless k.match(/^BeanstalkConnection\_/)
198
+ next unless k.to_s.match(CONN_KEY)
178
199
  t[k].close
179
200
  t[k] = nil
180
201
  end
181
202
  end
182
203
  end
183
204
 
205
+ def close
206
+
207
+ shutdown
208
+ end
209
+
184
210
  # Mainly used by ruote's test/unit/ut_17_storage.rb
185
211
  #
186
- def add_type (type)
212
+ def add_type(type)
187
213
 
188
214
  # nothing to do
189
215
  end
190
216
 
191
- # Nukes a db type and reputs it (losing all the documents that were in it).
217
+ # Nukes a db type and reputs it(losing all the documents that were in it).
192
218
  #
193
- def purge_type! (type)
219
+ def purge_type!(type)
194
220
 
195
221
  if @cloche
196
222
  @cloche.purge_type!(type)
@@ -201,10 +227,10 @@ module Beanstalk
201
227
 
202
228
  protected
203
229
 
204
- CONN_KEY = '__ruote_beanstalk_connection'
230
+ CONN_KEY = 'ruote-beanstalk-connection'
205
231
  TUBE_NAME = 'ruote-storage-commands'
206
232
 
207
- def split_uri (uri)
233
+ def split_uri(uri)
208
234
 
209
235
  uri = ':' if uri == ''
210
236
 
@@ -218,6 +244,15 @@ module Beanstalk
218
244
  def connection
219
245
 
220
246
  c = Thread.current[CONN_KEY]
247
+
248
+ #begin
249
+ # c.stats
250
+ # return c
251
+ #rescue Exception => e
252
+ # c = nil
253
+ #end if c
254
+ # keeping around the idea around
255
+
221
256
  return c if c
222
257
 
223
258
  c = ::Beanstalk::Connection.new(@uri, TUBE_NAME)
@@ -237,7 +272,7 @@ module Beanstalk
237
272
  put({ '_id' => 'engine', 'type' => 'configurations' }.merge(@options))
238
273
  end
239
274
 
240
- def operate (command, params)
275
+ def operate(command, params)
241
276
 
242
277
  client_id = "BsStorage-#{Thread.current.object_id}-#{$$}"
243
278
  timestamp = Time.now.to_f.to_s
@@ -251,11 +286,15 @@ module Beanstalk
251
286
 
252
287
  result = nil
253
288
 
254
- # NOTE : what about a timeout ?
255
-
256
289
  loop do
257
290
 
258
- job = con.reserve
291
+ job = nil
292
+ begin
293
+ job = con.reserve
294
+ rescue Exception => e
295
+ # probably our timeout
296
+ break
297
+ end
259
298
  job.delete
260
299
 
261
300
  result, ts = Rufus::Json.decode(job.body)
@@ -265,7 +304,7 @@ module Beanstalk
265
304
 
266
305
  if result.is_a?(Array) && result.first == 'error'
267
306
  raise ArgumentError.new(result.last) if result[1] == 'ArgumentError'
268
- raise BsStorageError.new(result.last)
307
+ raise StorageError.new(result.last)
269
308
  end
270
309
 
271
310
  result
@@ -1,7 +1,7 @@
1
1
 
2
2
  module Ruote
3
3
  module Beanstalk
4
- VERSION = '2.1.10'
4
+ VERSION = '2.1.11'
5
5
  end
6
6
  end
7
7
 
data/readme.rdoc ADDED
@@ -0,0 +1,5 @@
1
+
2
+ This is the rdoc for ruote-beanstalk.
3
+
4
+ For an overview, see http://github.com/jmettraux/ruote-beanstalk
5
+