background_bunnies 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +2 -2
- data/README.md +133 -2
- data/lib/background_bunnies/bunny.rb +15 -2
- data/lib/background_bunnies/logger.rb +3 -3
- data/lib/background_bunnies/producer.rb +1 -1
- data/lib/background_bunnies/version.rb +1 -1
- metadata +2 -2
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2013
|
1
|
+
Copyright (c) 2013 Heapsource - http://www.heapsource.com
|
2
2
|
|
3
3
|
MIT License
|
4
4
|
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -15,10 +15,141 @@ And then execute:
|
|
15
15
|
Or install it yourself as:
|
16
16
|
|
17
17
|
$ gem install background_bunnies
|
18
|
+
|
19
|
+
## How it Works
|
18
20
|
|
19
|
-
|
21
|
+
Background Bunnies are workers fed by producers and broadcasters.
|
20
22
|
|
21
|
-
|
23
|
+
* A producer will create jobs intended for bunnies of type `queue` and only one worker will process the job. This is the default configuration.
|
24
|
+
* A broadcasters will produce jobs intented for bunnies of type `broadcast` and every single worker will receive the same job.
|
25
|
+
|
26
|
+
## Work Queues
|
27
|
+
|
28
|
+
A work client uses AMQP queues and only one bunny will perform the job, this is known as a work queue. This is the default configuration for all the bunnies.
|
29
|
+
|
30
|
+
Example Bunny Worker:
|
31
|
+
|
32
|
+
require 'background_bunnies'
|
33
|
+
|
34
|
+
class BackgroundBunnies::Workers::ImageTransform
|
35
|
+
include BackgroundBunnies::Bunny
|
36
|
+
group :images
|
37
|
+
|
38
|
+
def process(job)
|
39
|
+
image_url = job.payload[:image_url] # https://encrypted.google.com/images/srpr/logo4w.png
|
40
|
+
# perform image transformation here
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
BackgroundBunnies.configure(:main, "amqp://guest:guest@127.0.0.1")
|
45
|
+
BackgroundBunnies.run(:images) # block forever while running the workers
|
46
|
+
|
47
|
+
Example Client:
|
48
|
+
|
49
|
+
BackgroundBunnies.configure(:main, "amqp://guest:guest@127.0.0.1")
|
50
|
+
producer = BackgroundBunnies::Workers::ImageTransform.create_producer :images
|
51
|
+
producer.enqueue(image_path: "https://encrypted.google.com/images/srpr/logo4w.png")
|
52
|
+
|
53
|
+
## Broadcast
|
54
|
+
|
55
|
+
A broadcast client uses AMQP queues to `fanout` the same job across many worker bunnies, bunnies will receive the job when mode `broadcast` is used.
|
56
|
+
|
57
|
+
Example Bunny worker:
|
58
|
+
|
59
|
+
require 'background_bunnies'
|
60
|
+
|
61
|
+
class BackgroundBunnies::Workers::RelyMessage
|
62
|
+
include BackgroundBunnies::Bunny
|
63
|
+
type :broadcast # tell the bunny worker it should use queue as broadcast
|
64
|
+
group :messaging
|
65
|
+
|
66
|
+
def process(job)
|
67
|
+
subject = job.payload[:subject] # "Spread this message across all the worker nodes"
|
68
|
+
# do your thing here
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
BackgroundBunnies.configure(:main, "amqp://guest:guest@127.0.0.1")
|
73
|
+
BackgroundBunnies.run(:messaging) # block forever while running the workers
|
74
|
+
|
75
|
+
Example Client:
|
76
|
+
|
77
|
+
BackgroundBunnies.configure(:main, "amqp://guest:guest@127.0.0.1")
|
78
|
+
producer = BackgroundBunnies::Workers::RelyMessage.create_brodacaster :messaging
|
79
|
+
producer.enqueue(subject: "Spread this message across all the worker nodes")
|
80
|
+
|
81
|
+
## Error Handling
|
82
|
+
|
83
|
+
In the case an exception is raised while executing the method `process`, the job will be put back on the queue so it can be processed in another time or by another worker. Even if the worker crashes, the job will be processed in another time or by another worker eventually.
|
84
|
+
|
85
|
+
Bunnies provide a method you could override to determinate which errors should cause the job to be requeued or skipped.
|
86
|
+
|
87
|
+
Return `true` if you want to skip the job, the default is requeue the job on every error.
|
88
|
+
|
89
|
+
def on_error(job, err)
|
90
|
+
# true and the job will be skipped.
|
91
|
+
# false and the job will be requeued. This is the default.
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
## Configuring Connection Strings
|
96
|
+
|
97
|
+
Bunnies will be executed together under the same configuration group. The default group is `:default`.
|
98
|
+
|
99
|
+
A group share the same connection uri across the producers, broadcasters and bunnies:
|
100
|
+
|
101
|
+
Example:
|
102
|
+
|
103
|
+
BackgroundBunnies.configure(:default, "amqp://guest:guest@127.0.0.1")
|
104
|
+
|
105
|
+
## Executing a group of Workers
|
106
|
+
|
107
|
+
Instead initializing and running a single worker manually, background bunnies executes in groups.
|
108
|
+
|
109
|
+
BackgroundBunnies.run(:default) # block forever while running the workers
|
110
|
+
|
111
|
+
## Workers as custom Rake Tasks
|
112
|
+
|
113
|
+
If you want to run your workers as a rake task in for example, a Rails app, you can create one as follows:
|
114
|
+
|
115
|
+
Create a file in `lib/tasks/images.rb`:
|
116
|
+
|
117
|
+
namespace :mybunnies do
|
118
|
+
task :images=>:environment do
|
119
|
+
BackgroundBunnies.run(:images)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
You can then run from the command line:
|
124
|
+
|
125
|
+
rake mybunnies:images
|
126
|
+
|
127
|
+
## Logging
|
128
|
+
|
129
|
+
In your worker bunnies you can use `log_error`, `log_warn` and `log_info` to log information formatted as part of BackgroundBunnies to `$stderr` and `$stdout`.
|
130
|
+
|
131
|
+
Example:
|
132
|
+
|
133
|
+
def process(job)
|
134
|
+
log_error "An error occurred"
|
135
|
+
log_info "Something Happened"
|
136
|
+
log_warn "Beware of this"
|
137
|
+
end
|
138
|
+
|
139
|
+
Output:
|
140
|
+
|
141
|
+
[error] BackgroundBunnies -> Songs: An error occurred
|
142
|
+
[info] BackgroundBunnies -> Songs: Something Happened
|
143
|
+
[warn] BackgroundBunnies -> Songs: Beware of this
|
144
|
+
|
145
|
+
|
146
|
+
## Examples
|
147
|
+
|
148
|
+
Check `/examples`.
|
149
|
+
|
150
|
+
## LICENSE
|
151
|
+
|
152
|
+
MIT
|
22
153
|
|
23
154
|
## Contributing
|
24
155
|
|
@@ -102,6 +102,7 @@ module BackgroundBunnies
|
|
102
102
|
@exchange = @channel.fanout(BackgroundBunnies.broadcast_exchange_name(queue_name))
|
103
103
|
@queue.bind(@exchange)
|
104
104
|
else
|
105
|
+
queue_options[:durable] = true
|
105
106
|
@queue = @channel.queue(queue_name, queue_options)
|
106
107
|
end
|
107
108
|
@consumer = @queue.subscribe(:ack=>true) do |metadata, payload|
|
@@ -114,8 +115,12 @@ module BackgroundBunnies
|
|
114
115
|
metadata.ack
|
115
116
|
rescue =>err
|
116
117
|
# processing went wrong, requeing message
|
117
|
-
|
118
|
-
|
118
|
+
job = Job.new(nil, info, properties) unless job
|
119
|
+
unless on_error(job, err)
|
120
|
+
metadata.reject(:requeue=>true)
|
121
|
+
else
|
122
|
+
metadata.ack
|
123
|
+
end
|
119
124
|
end
|
120
125
|
end
|
121
126
|
end
|
@@ -128,6 +133,14 @@ module BackgroundBunnies
|
|
128
133
|
BackgroundBunnies.error "#{queue_name}: #{a}"
|
129
134
|
end
|
130
135
|
|
136
|
+
def log_info(a)
|
137
|
+
BackgroundBunnies.info "#{queue_name}: #{a}"
|
138
|
+
end
|
139
|
+
|
140
|
+
def log_warn(a)
|
141
|
+
BackgroundBunnies.warn "#{queue_name}: #{a}"
|
142
|
+
end
|
143
|
+
|
131
144
|
#
|
132
145
|
# Process a Job. Implemented by the class.
|
133
146
|
#
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module BackgroundBunnies
|
2
2
|
|
3
|
-
def self.
|
4
|
-
|
3
|
+
def self.warn(a)
|
4
|
+
$stderr.puts "[warn] BackgroundBunnies -> #{a}"
|
5
5
|
end
|
6
6
|
|
7
7
|
def self.info(a)
|
8
|
-
|
8
|
+
$stdout.puts "[info] BackgroundBunnies -> #{a}"
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.error(a)
|
@@ -11,7 +11,7 @@ module BackgroundBunnies
|
|
11
11
|
@connection = BackgroundBunnies.connect connection_or_group
|
12
12
|
@queue_name = queue_name.to_s
|
13
13
|
@channel = @connection.create_channel
|
14
|
-
@queue = @connection.queue(@queue_name)
|
14
|
+
@queue = @connection.queue(@queue_name, :durable=>true)
|
15
15
|
end
|
16
16
|
|
17
17
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: background_bunnies
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-06-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bunny
|