dispatch-rider 1.0.3 → 1.1.4
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.
- checksums.yaml +5 -13
- data/README.md +31 -0
- data/lib/dispatch-rider/configuration.rb +4 -0
- data/lib/dispatch-rider/dispatcher.rb +1 -1
- data/lib/dispatch-rider/handlers/base.rb +41 -3
- data/lib/dispatch-rider/queue_services/aws_sqs.rb +8 -12
- data/lib/dispatch-rider/queue_services/aws_sqs/sqs_received_message.rb +34 -0
- data/lib/dispatch-rider/queue_services/base.rb +12 -5
- data/lib/dispatch-rider/queue_services/file_system.rb +8 -0
- data/lib/dispatch-rider/queue_services/file_system/fs_received_message.rb +23 -0
- data/lib/dispatch-rider/queue_services/file_system/queue.rb +5 -0
- data/lib/dispatch-rider/queue_services/received_message.rb +23 -0
- data/lib/dispatch-rider/version.rb +1 -1
- metadata +24 -21
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ODRkMGIyZWUzODdhMmYxNDg0MTgzZjQxYmQ3OGJlYWFkZTE1YTk0ZQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5abe7d067b30a87f2e255eae8d4cfc94782567b7
|
4
|
+
data.tar.gz: 2044e59ff77593e6c0d0aa10399210066228a7fd
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
YzVjNmFjZWM1MWQ0OGZjNzhiMDM3MzdmOWZjMDMzOGUyYjRlMzU1YTI5YmM5
|
11
|
-
YzZlMzRmNzY1MWZhYjE5NWM3MDdiNGMyNWUxZmVhYTZhZTkyZTk=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
OGJjYjBkYWY5NzdlOTIxMTgyYzU4ZTI2ODc3ODgzNzM2MmE0YjMzNGJmMDI2
|
14
|
-
OWM5OWQ1MTBiNmNjNzg2M2I4ZTVlODY5NTE1MGM5NzJjYmExYzMzYThmODc2
|
15
|
-
ODBlZGI4YWNlYTUwMTU3MzI5MDY1MTg3ZjQzYmE3MWI4YWQ5MmM=
|
6
|
+
metadata.gz: 36e44305e710150417a6bd3f3673ff8b9fd33cb8ac44e259114eebfdb3f9d8690b270b16e03942978ea8bb4d9af2679111736d03923e9c173a3a9b88a43f9120
|
7
|
+
data.tar.gz: 336fbb538b2a9998cb3e53e26217b3dedaad6e198f25ee02e79f96513b102045b38b9881b32ffad529a0a6295f42789325bb5cb9ca8ee4a4767ad7658ac3fbbc
|
data/README.md
CHANGED
@@ -212,6 +212,7 @@ DispatchRider.config do |config|
|
|
212
212
|
end
|
213
213
|
|
214
214
|
config.logger = Rails.logger
|
215
|
+
config.default_retry_timeout = 300
|
215
216
|
|
216
217
|
config.error_handler = DispatchRider::DefaultErrorHandler # an object that responds to .call(message, exception)
|
217
218
|
|
@@ -243,6 +244,9 @@ Each callback can have hooks plugged into it at `before`, `after` and `around` t
|
|
243
244
|
### Manual Setup
|
244
245
|
|
245
246
|
To setup a subscriber you'll need message handlers. The handlers are named the same as the message subjects.
|
247
|
+
Each handler may also specify a retry_timeout as shown below. When a job throws an exception it will be put back
|
248
|
+
on the queue in that time period if the queue supports timeouts. If the underlying queue (such as filesystem) does
|
249
|
+
not support retry then this setting is ineffective.
|
246
250
|
|
247
251
|
Sample message handler:
|
248
252
|
```ruby
|
@@ -253,6 +257,33 @@ class ReadNews < DispatchRider::Handlers::Base
|
|
253
257
|
puts headline
|
254
258
|
end
|
255
259
|
end
|
260
|
+
|
261
|
+
def retry_timeout
|
262
|
+
10.minutes
|
263
|
+
end
|
264
|
+
end
|
265
|
+
```
|
266
|
+
|
267
|
+
### Timeout & retry handling
|
268
|
+
|
269
|
+
If you have a long running job, or if you wish to retry a job later, you may use two methods in your
|
270
|
+
handler class. return_to_queue and extend_timeout.
|
271
|
+
|
272
|
+
return_to_queue will retry your item immediately.
|
273
|
+
extend_timeout will tell the queue you wish to hold this item longer.
|
274
|
+
|
275
|
+
```ruby
|
276
|
+
# app/handlers/foo_handler
|
277
|
+
class LongRunning < DispatchRider::Handlers::Base
|
278
|
+
def process(body)
|
279
|
+
my_loop.each do |item|
|
280
|
+
|
281
|
+
#... do some work ...
|
282
|
+
extend_timeout(1.hour)
|
283
|
+
end
|
284
|
+
rescue OutOfResourcesImOutError
|
285
|
+
return_to_queue #oops! Better give this to somebody else!
|
286
|
+
end
|
256
287
|
end
|
257
288
|
```
|
258
289
|
|
@@ -19,7 +19,7 @@ module DispatchRider
|
|
19
19
|
|
20
20
|
def dispatch(message)
|
21
21
|
callbacks.invoke(:dispatch_message, message) do
|
22
|
-
handler_registrar.fetch(message.subject).new.do_process(message
|
22
|
+
handler_registrar.fetch(message.subject).new.do_process(message)
|
23
23
|
end
|
24
24
|
true # success => true (delete message)
|
25
25
|
end
|
@@ -3,16 +3,54 @@ module DispatchRider
|
|
3
3
|
class Base
|
4
4
|
include NamedProcess
|
5
5
|
extend InheritanceTracking
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def set_default_retry( amount )
|
9
|
+
define_method(:retry_timeout) do
|
10
|
+
amount
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :raw_message
|
6
16
|
|
7
|
-
def do_process(
|
17
|
+
def do_process(raw_message)
|
8
18
|
with_named_process(self.class.name) do
|
9
|
-
|
19
|
+
@raw_message = raw_message
|
20
|
+
process(raw_message.body)
|
10
21
|
end
|
22
|
+
rescue Exception => e
|
23
|
+
self.retry if self.retry_on_failure?
|
24
|
+
raise e
|
11
25
|
end
|
12
26
|
|
13
|
-
def process(
|
27
|
+
def process(message)
|
14
28
|
raise NotImplementedError, "Method 'process' not overridden in subclass!"
|
15
29
|
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def extend_timeout(timeout)
|
34
|
+
raw_message.extend_timeout(timeout)
|
35
|
+
end
|
36
|
+
|
37
|
+
def return_to_queue
|
38
|
+
raw_message.return_to_queue
|
39
|
+
end
|
40
|
+
|
41
|
+
def retry
|
42
|
+
timeout = retry_timeout
|
43
|
+
case timeout
|
44
|
+
when :immediate
|
45
|
+
return_to_queue
|
46
|
+
else
|
47
|
+
extend_timeout(timeout)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def retry_on_failure?
|
52
|
+
self.respond_to? :retry_timeout
|
53
|
+
end
|
16
54
|
end
|
17
55
|
end
|
18
56
|
end
|
@@ -4,6 +4,7 @@ module DispatchRider
|
|
4
4
|
module QueueServices
|
5
5
|
class AwsSqs < Base
|
6
6
|
require "dispatch-rider/queue_services/aws_sqs/message_body_extractor"
|
7
|
+
require "dispatch-rider/queue_services/aws_sqs/sqs_received_message"
|
7
8
|
|
8
9
|
class AbortExecution < RuntimeError; end
|
9
10
|
class VisibilityTimeoutExceeded < RuntimeError; end
|
@@ -26,11 +27,11 @@ module DispatchRider
|
|
26
27
|
def pop(&block)
|
27
28
|
begin
|
28
29
|
queue.receive_message do |raw_item|
|
29
|
-
obj =
|
30
|
+
obj = SqsReceivedMessage.new(construct_message_from(raw_item), raw_item, queue)
|
30
31
|
|
31
|
-
|
32
|
-
raise AbortExecution, "false received from handler" unless block.call(obj
|
33
|
-
obj
|
32
|
+
visibility_timeout_shield(obj) do
|
33
|
+
raise AbortExecution, "false received from handler" unless block.call(obj)
|
34
|
+
obj
|
34
35
|
end
|
35
36
|
|
36
37
|
end
|
@@ -57,17 +58,12 @@ module DispatchRider
|
|
57
58
|
|
58
59
|
private
|
59
60
|
|
60
|
-
def
|
61
|
-
queue.visibility_timeout
|
62
|
-
end
|
63
|
-
|
64
|
-
def visibility_timout_shield(message)
|
65
|
-
start_time = Time.now
|
66
|
-
timeout = visibility_timeout # capture it at start
|
61
|
+
def visibility_timeout_shield(message)
|
67
62
|
begin
|
68
63
|
yield
|
69
64
|
ensure
|
70
|
-
duration = Time.now - start_time
|
65
|
+
duration = Time.now - message.start_time
|
66
|
+
timeout = message.total_timeout
|
71
67
|
raise VisibilityTimeoutExceeded, "message: #{message.subject}, #{message.body.inspect} took #{duration} seconds while the timeout was #{timeout}" if duration > timeout
|
72
68
|
end
|
73
69
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module DispatchRider
|
2
|
+
module QueueServices
|
3
|
+
class AwsSqs < Base
|
4
|
+
class SqsReceivedMessage < ReceivedMessage
|
5
|
+
attr_reader :total_timeout, :start_time
|
6
|
+
|
7
|
+
def initialize(message, raw_item, queue)
|
8
|
+
@total_timeout = queue.visibility_timeout
|
9
|
+
@start_time = Time.now
|
10
|
+
super(message, raw_item)
|
11
|
+
end
|
12
|
+
|
13
|
+
# NOTE: Setting the visibility timeout resets the timeout to NOW and makes it visibility timeout this time
|
14
|
+
# Essentially resetting the timer on this message
|
15
|
+
def extend_timeout(timeout)
|
16
|
+
item.visibility_timeout = timeout
|
17
|
+
if timeout > 0
|
18
|
+
@total_timeout = timeout + (Time.now - start_time).to_i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# We effectively return the item to the queue by setting
|
23
|
+
# the visibility timeout to zero. The item
|
24
|
+
# should become immediately visible.
|
25
|
+
# The next receiver will reset the visibility
|
26
|
+
# to something appropriate
|
27
|
+
def return_to_queue
|
28
|
+
extend_timeout(0)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -5,6 +5,7 @@
|
|
5
5
|
# initialize, push, pop and empty?
|
6
6
|
module DispatchRider
|
7
7
|
module QueueServices
|
8
|
+
require "dispatch-rider/queue_services/received_message"
|
8
9
|
class Base
|
9
10
|
attr_accessor :queue
|
10
11
|
|
@@ -26,17 +27,23 @@ module DispatchRider
|
|
26
27
|
raise NotImplementedError
|
27
28
|
end
|
28
29
|
|
30
|
+
|
31
|
+
#If you pass a block into pop it will wrap the deletion of the message with it's handling
|
29
32
|
def pop(&block)
|
30
|
-
|
31
|
-
if
|
32
|
-
block.call(
|
33
|
-
|
33
|
+
received = head
|
34
|
+
if received
|
35
|
+
block.call(received) && delete(received.item)
|
36
|
+
received
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
37
40
|
def head
|
38
41
|
raw_item = raw_head
|
39
|
-
raw_item &&
|
42
|
+
raw_item && received_message_for(raw_item)
|
43
|
+
end
|
44
|
+
|
45
|
+
def received_message_for(raw_item)
|
46
|
+
QueueServices::ReceivedMessage.new(construct_message_from(raw_item), raw_item)
|
40
47
|
end
|
41
48
|
|
42
49
|
def raw_head
|
@@ -22,10 +22,18 @@ module DispatchRider
|
|
22
22
|
def raw_head
|
23
23
|
queue.pop
|
24
24
|
end
|
25
|
+
|
26
|
+
def received_message_for(raw_item)
|
27
|
+
FsReceivedMessage.new(construct_message_from(raw_item), raw_item, queue)
|
28
|
+
end
|
25
29
|
|
26
30
|
def construct_message_from(item)
|
27
31
|
deserialize(item.read)
|
28
32
|
end
|
33
|
+
|
34
|
+
def put_back(item)
|
35
|
+
queue.put_back(item)
|
36
|
+
end
|
29
37
|
|
30
38
|
def delete(item)
|
31
39
|
queue.remove item
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DispatchRider
|
2
|
+
module QueueServices
|
3
|
+
class FileSystem < Base
|
4
|
+
class FsReceivedMessage < ReceivedMessage
|
5
|
+
attr_reader :queue
|
6
|
+
|
7
|
+
def initialize(message, item, queue)
|
8
|
+
@queue = queue
|
9
|
+
super(message, item)
|
10
|
+
end
|
11
|
+
|
12
|
+
def extend_timeout(timeout)
|
13
|
+
#file system doesn't support timeouts on items, so we ignore this.
|
14
|
+
end
|
15
|
+
|
16
|
+
def return_to_queue
|
17
|
+
queue.put_back(item)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DispatchRider
|
2
|
+
module QueueServices
|
3
|
+
class ReceivedMessage < SimpleDelegator
|
4
|
+
|
5
|
+
#Item is the raw message item as returned by the queue implementor
|
6
|
+
#it's contents will depend on the queue being used
|
7
|
+
attr_reader :item
|
8
|
+
|
9
|
+
def initialize(message, item)
|
10
|
+
@item = item
|
11
|
+
super(message)
|
12
|
+
end
|
13
|
+
|
14
|
+
def extend_timeout(time)
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
def return_to_queue
|
19
|
+
raise NotImplementedError
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dispatch-rider
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Suman Mukherjee
|
@@ -11,62 +11,62 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2014-
|
14
|
+
date: 2014-02-04 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activesupport
|
18
18
|
requirement: !ruby/object:Gem::Requirement
|
19
19
|
requirements:
|
20
|
-
- -
|
20
|
+
- - '>='
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: activemodel
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
requirements:
|
34
|
-
- -
|
34
|
+
- - '>='
|
35
35
|
- !ruby/object:Gem::Version
|
36
36
|
version: '0'
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
|
-
- -
|
41
|
+
- - '>='
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: '0'
|
44
44
|
- !ruby/object:Gem::Dependency
|
45
45
|
name: daemons
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
47
47
|
requirements:
|
48
|
-
- -
|
48
|
+
- - '>='
|
49
49
|
- !ruby/object:Gem::Version
|
50
50
|
version: '0'
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
|
-
- -
|
55
|
+
- - '>='
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
version: '0'
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: bundler
|
60
60
|
requirement: !ruby/object:Gem::Requirement
|
61
61
|
requirements:
|
62
|
-
- -
|
62
|
+
- - '>='
|
63
63
|
- !ruby/object:Gem::Version
|
64
64
|
version: '0'
|
65
65
|
type: :development
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
68
68
|
requirements:
|
69
|
-
- -
|
69
|
+
- - '>='
|
70
70
|
- !ruby/object:Gem::Version
|
71
71
|
version: '0'
|
72
72
|
- !ruby/object:Gem::Dependency
|
@@ -87,56 +87,56 @@ dependencies:
|
|
87
87
|
name: rake
|
88
88
|
requirement: !ruby/object:Gem::Requirement
|
89
89
|
requirements:
|
90
|
-
- -
|
90
|
+
- - '>='
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: '0'
|
93
93
|
type: :development
|
94
94
|
prerelease: false
|
95
95
|
version_requirements: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
|
-
- -
|
97
|
+
- - '>='
|
98
98
|
- !ruby/object:Gem::Version
|
99
99
|
version: '0'
|
100
100
|
- !ruby/object:Gem::Dependency
|
101
101
|
name: travis-lint
|
102
102
|
requirement: !ruby/object:Gem::Requirement
|
103
103
|
requirements:
|
104
|
-
- -
|
104
|
+
- - '>='
|
105
105
|
- !ruby/object:Gem::Version
|
106
106
|
version: '0'
|
107
107
|
type: :development
|
108
108
|
prerelease: false
|
109
109
|
version_requirements: !ruby/object:Gem::Requirement
|
110
110
|
requirements:
|
111
|
-
- -
|
111
|
+
- - '>='
|
112
112
|
- !ruby/object:Gem::Version
|
113
113
|
version: '0'
|
114
114
|
- !ruby/object:Gem::Dependency
|
115
115
|
name: rspec
|
116
116
|
requirement: !ruby/object:Gem::Requirement
|
117
117
|
requirements:
|
118
|
-
- -
|
118
|
+
- - '>='
|
119
119
|
- !ruby/object:Gem::Version
|
120
120
|
version: '0'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
123
|
version_requirements: !ruby/object:Gem::Requirement
|
124
124
|
requirements:
|
125
|
-
- -
|
125
|
+
- - '>='
|
126
126
|
- !ruby/object:Gem::Version
|
127
127
|
version: '0'
|
128
128
|
- !ruby/object:Gem::Dependency
|
129
129
|
name: debugger
|
130
130
|
requirement: !ruby/object:Gem::Requirement
|
131
131
|
requirements:
|
132
|
-
- -
|
132
|
+
- - '>='
|
133
133
|
- !ruby/object:Gem::Version
|
134
134
|
version: '0'
|
135
135
|
type: :development
|
136
136
|
prerelease: false
|
137
137
|
version_requirements: !ruby/object:Gem::Requirement
|
138
138
|
requirements:
|
139
|
-
- -
|
139
|
+
- - '>='
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
description: Messaging system that is customizable based on which queueing system
|
@@ -183,9 +183,12 @@ files:
|
|
183
183
|
- lib/dispatch-rider/queue_services.rb
|
184
184
|
- lib/dispatch-rider/queue_services/aws_sqs.rb
|
185
185
|
- lib/dispatch-rider/queue_services/aws_sqs/message_body_extractor.rb
|
186
|
+
- lib/dispatch-rider/queue_services/aws_sqs/sqs_received_message.rb
|
186
187
|
- lib/dispatch-rider/queue_services/base.rb
|
187
188
|
- lib/dispatch-rider/queue_services/file_system.rb
|
189
|
+
- lib/dispatch-rider/queue_services/file_system/fs_received_message.rb
|
188
190
|
- lib/dispatch-rider/queue_services/file_system/queue.rb
|
191
|
+
- lib/dispatch-rider/queue_services/received_message.rb
|
189
192
|
- lib/dispatch-rider/queue_services/simple.rb
|
190
193
|
- lib/dispatch-rider/registrars.rb
|
191
194
|
- lib/dispatch-rider/registrars/base.rb
|
@@ -213,17 +216,17 @@ require_paths:
|
|
213
216
|
- lib
|
214
217
|
required_ruby_version: !ruby/object:Gem::Requirement
|
215
218
|
requirements:
|
216
|
-
- -
|
219
|
+
- - '>='
|
217
220
|
- !ruby/object:Gem::Version
|
218
221
|
version: '0'
|
219
222
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
220
223
|
requirements:
|
221
|
-
- -
|
224
|
+
- - '>='
|
222
225
|
- !ruby/object:Gem::Version
|
223
226
|
version: '0'
|
224
227
|
requirements: []
|
225
228
|
rubyforge_project:
|
226
|
-
rubygems_version: 2.
|
229
|
+
rubygems_version: 2.0.14
|
227
230
|
signing_key:
|
228
231
|
specification_version: 4
|
229
232
|
summary: Messaging system based on the reactor patter. You can publish messages to
|