sneakers 0.0.1 → 0.0.2
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/.gitignore +6 -17
- data/Gemfile +0 -1
- data/Gemfile.lock +152 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +2 -2
- data/README.md +140 -9
- data/Rakefile +9 -0
- data/bin/sneakers +5 -0
- data/examples/benchmark_worker.rb +21 -0
- data/examples/metrics_worker.rb +28 -0
- data/examples/profiling_worker.rb +55 -0
- data/examples/sneakers.conf.rb.example +10 -0
- data/examples/title_scraper.rb +20 -0
- data/examples/workflow_worker.rb +24 -0
- data/lib/sneakers.rb +80 -1
- data/lib/sneakers/cli.rb +107 -0
- data/lib/sneakers/concerns/logging.rb +34 -0
- data/lib/sneakers/concerns/metrics.rb +34 -0
- data/lib/sneakers/handlers/oneshot.rb +25 -0
- data/lib/sneakers/metrics/logging_metrics.rb +16 -0
- data/lib/sneakers/metrics/null_metrics.rb +13 -0
- data/lib/sneakers/metrics/statsd_metrics.rb +21 -0
- data/lib/sneakers/publisher.rb +35 -0
- data/lib/sneakers/queue.rb +42 -0
- data/lib/sneakers/runner.rb +20 -0
- data/lib/sneakers/runner_config.rb +55 -0
- data/lib/sneakers/support/production_formatter.rb +11 -0
- data/lib/sneakers/support/queue_name.rb +14 -0
- data/lib/sneakers/support/utils.rb +18 -0
- data/lib/sneakers/tasks.rb +34 -0
- data/lib/sneakers/version.rb +1 -1
- data/lib/sneakers/worker.rb +120 -0
- data/lib/sneakers/workergroup.rb +47 -0
- data/sneakers.gemspec +26 -16
- data/spec/fixtures/require_worker.rb +17 -0
- data/spec/sneakers/cli_spec.rb +53 -0
- data/spec/sneakers/concerns/logging.rb +39 -0
- data/spec/sneakers/concerns/metrics.rb +38 -0
- data/spec/sneakers/publisher_spec.rb +37 -0
- data/spec/sneakers/queue_spec.rb +42 -0
- data/spec/sneakers/worker_spec.rb +348 -0
- data/spec/spec_helper.rb +10 -0
- metadata +216 -14
data/.gitignore
CHANGED
@@ -1,17 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
InstalledFiles
|
8
|
-
_yardoc
|
9
|
-
coverage
|
10
|
-
doc/
|
11
|
-
lib/bundler/man
|
12
|
-
pkg
|
13
|
-
rdoc
|
14
|
-
spec/reports
|
15
|
-
test/tmp
|
16
|
-
test/version_tmp
|
17
|
-
tmp
|
1
|
+
sneakers.yaml
|
2
|
+
sneakers.log
|
3
|
+
sneakers.pid
|
4
|
+
pkg/
|
5
|
+
coverage/
|
6
|
+
tmp/
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sneakers (0.0.2)
|
5
|
+
bunny (>= 0.9.0.rc2)
|
6
|
+
serverengine
|
7
|
+
thor
|
8
|
+
thread
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activesupport (3.2.14)
|
14
|
+
i18n (~> 0.6, >= 0.6.4)
|
15
|
+
multi_json (~> 1.0)
|
16
|
+
amq-protocol (1.7.0)
|
17
|
+
arrayfields (4.9.0)
|
18
|
+
awesome_print (1.1.0)
|
19
|
+
bluff (0.1.0)
|
20
|
+
bunny (1.0.0.pre6)
|
21
|
+
amq-protocol (>= 1.7.0)
|
22
|
+
cane (2.6.0)
|
23
|
+
parallel
|
24
|
+
chronic (0.10.2)
|
25
|
+
churn (0.0.33)
|
26
|
+
chronic (>= 0.2.3)
|
27
|
+
hirb
|
28
|
+
json_pure
|
29
|
+
main
|
30
|
+
ruby_parser (~> 3.0)
|
31
|
+
sexp_processor (~> 4.1)
|
32
|
+
code_analyzer (0.4.2)
|
33
|
+
sexp_processor
|
34
|
+
code_metrics (0.1.0)
|
35
|
+
coderay (1.0.9)
|
36
|
+
colored (1.2)
|
37
|
+
erubis (2.7.0)
|
38
|
+
fattr (2.2.1)
|
39
|
+
ffi (1.9.0)
|
40
|
+
flay (2.4.0)
|
41
|
+
ruby_parser (~> 3.0)
|
42
|
+
sexp_processor (~> 4.0)
|
43
|
+
flog (4.1.2)
|
44
|
+
ruby_parser (~> 3.1, > 3.1.0)
|
45
|
+
sexp_processor (~> 4.0)
|
46
|
+
formatador (0.2.4)
|
47
|
+
guard (1.8.2)
|
48
|
+
formatador (>= 0.2.4)
|
49
|
+
listen (>= 1.0.0)
|
50
|
+
lumberjack (>= 1.0.2)
|
51
|
+
pry (>= 0.9.10)
|
52
|
+
thor (>= 0.14.6)
|
53
|
+
guard-minitest (1.3.0)
|
54
|
+
guard (>= 1.8)
|
55
|
+
minitest (>= 2.1)
|
56
|
+
hirb (0.7.1)
|
57
|
+
i18n (0.6.5)
|
58
|
+
json_pure (1.8.0)
|
59
|
+
listen (1.3.1)
|
60
|
+
rb-fsevent (>= 0.9.3)
|
61
|
+
rb-inotify (>= 0.9)
|
62
|
+
rb-kqueue (>= 0.2)
|
63
|
+
lumberjack (1.0.4)
|
64
|
+
main (5.2.0)
|
65
|
+
arrayfields (>= 4.7.4)
|
66
|
+
chronic (>= 0.6.2)
|
67
|
+
fattr (>= 2.2.0)
|
68
|
+
map (>= 5.1.0)
|
69
|
+
map (6.5.1)
|
70
|
+
method_source (0.8.2)
|
71
|
+
metric_fu (4.4.1)
|
72
|
+
bluff
|
73
|
+
cane (~> 2.5, >= 2.5.2)
|
74
|
+
churn (~> 0.0.28)
|
75
|
+
code_metrics (~> 0.1)
|
76
|
+
coderay
|
77
|
+
flay (~> 2.1, >= 2.0.1)
|
78
|
+
flog (~> 4.1, >= 4.1.1)
|
79
|
+
metric_fu-Saikuro (>= 1.1.1.0)
|
80
|
+
multi_json
|
81
|
+
rails_best_practices (~> 1.14, >= 1.14.3)
|
82
|
+
redcard
|
83
|
+
reek (~> 1.3, >= 1.3.3)
|
84
|
+
roodi (~> 3.1)
|
85
|
+
metric_fu-Saikuro (1.1.1.0)
|
86
|
+
mini_portile (0.5.1)
|
87
|
+
minitest (5.0.7)
|
88
|
+
multi_json (1.8.0)
|
89
|
+
nokogiri (1.6.0)
|
90
|
+
mini_portile (~> 0.5.0)
|
91
|
+
parallel (0.8.3)
|
92
|
+
pry (0.9.12.2)
|
93
|
+
coderay (~> 1.0.5)
|
94
|
+
method_source (~> 0.8)
|
95
|
+
slop (~> 3.4)
|
96
|
+
rails_best_practices (1.14.3)
|
97
|
+
activesupport
|
98
|
+
awesome_print
|
99
|
+
code_analyzer (>= 0.4.2)
|
100
|
+
colored
|
101
|
+
erubis
|
102
|
+
i18n
|
103
|
+
require_all
|
104
|
+
ruby-progressbar
|
105
|
+
rake (10.1.0)
|
106
|
+
rb-fsevent (0.9.3)
|
107
|
+
rb-inotify (0.9.2)
|
108
|
+
ffi (>= 0.5.0)
|
109
|
+
rb-kqueue (0.2.0)
|
110
|
+
ffi (>= 0.5.0)
|
111
|
+
redcard (1.1.0)
|
112
|
+
reek (1.3.3)
|
113
|
+
ruby2ruby (~> 2.0.2)
|
114
|
+
ruby_parser (~> 3.1, >= 3.1.1)
|
115
|
+
sexp_processor
|
116
|
+
require_all (1.3.1)
|
117
|
+
roodi (3.1.1)
|
118
|
+
ruby_parser (~> 3.2, >= 3.2.2)
|
119
|
+
rr (1.1.1)
|
120
|
+
ruby-prof (0.13.0)
|
121
|
+
ruby-progressbar (1.2.0)
|
122
|
+
ruby2ruby (2.0.6)
|
123
|
+
ruby_parser (~> 3.1)
|
124
|
+
sexp_processor (~> 4.0)
|
125
|
+
ruby_parser (3.2.2)
|
126
|
+
sexp_processor (~> 4.1)
|
127
|
+
serverengine (1.5.4)
|
128
|
+
sigdump (~> 0.2.2)
|
129
|
+
sexp_processor (4.3.0)
|
130
|
+
sigdump (0.2.2)
|
131
|
+
simplecov (0.7.1)
|
132
|
+
multi_json (~> 1.0)
|
133
|
+
simplecov-html (~> 0.7.1)
|
134
|
+
simplecov-html (0.7.1)
|
135
|
+
simplecov-rcov-text (0.0.2)
|
136
|
+
slop (3.4.6)
|
137
|
+
thor (0.18.1)
|
138
|
+
thread (0.1.1)
|
139
|
+
|
140
|
+
PLATFORMS
|
141
|
+
ruby
|
142
|
+
|
143
|
+
DEPENDENCIES
|
144
|
+
guard-minitest
|
145
|
+
metric_fu
|
146
|
+
nokogiri
|
147
|
+
rake
|
148
|
+
rr
|
149
|
+
ruby-prof
|
150
|
+
simplecov
|
151
|
+
simplecov-rcov-text
|
152
|
+
sneakers!
|
data/Guardfile
ADDED
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2013
|
1
|
+
Copyright (c) 2013 Dotan Nahum
|
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
@@ -1,6 +1,20 @@
|
|
1
1
|
# Sneakers
|
2
2
|
|
3
|
-
|
3
|
+
|
4
|
+
```
|
5
|
+
__
|
6
|
+
,--' >
|
7
|
+
`=====
|
8
|
+
|
9
|
+
```
|
10
|
+
|
11
|
+
|
12
|
+
A high-performance RabbitMQ background processing framework for
|
13
|
+
Ruby.
|
14
|
+
|
15
|
+
Visit the [[wiki]]](https://github.com/jondot/sneakers/wiki) for
|
16
|
+
complete docs.
|
17
|
+
|
4
18
|
|
5
19
|
## Installation
|
6
20
|
|
@@ -16,14 +30,131 @@ Or install it yourself as:
|
|
16
30
|
|
17
31
|
$ gem install sneakers
|
18
32
|
|
19
|
-
## Usage
|
20
33
|
|
21
|
-
|
34
|
+
## Quick start
|
35
|
+
|
36
|
+
Set up a Gemfile
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
source 'https://rubygems.org'
|
40
|
+
gem 'sneakers'
|
41
|
+
gem 'json'
|
42
|
+
gem 'redis'
|
43
|
+
```
|
44
|
+
|
45
|
+
And a worker
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'sneakers'
|
49
|
+
require 'redis'
|
50
|
+
require 'json'
|
51
|
+
|
52
|
+
$redis = Redis.new
|
53
|
+
|
54
|
+
class Processor
|
55
|
+
include Sneakers::Worker
|
56
|
+
from_queue :logs
|
57
|
+
|
58
|
+
|
59
|
+
def work(msg)
|
60
|
+
err = JSON.parse(msg)
|
61
|
+
if err["type"] == "error"
|
62
|
+
$redis.incr "processor:#{err["error"]}"
|
63
|
+
end
|
64
|
+
|
65
|
+
ack!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
|
71
|
+
As an example, make a message look like this:
|
72
|
+
We'll count errors and error types with Redis. Specifically for an error that looks like this:
|
73
|
+
|
74
|
+
```javascript
|
75
|
+
{
|
76
|
+
"type": "error",
|
77
|
+
"message": "HALP!",
|
78
|
+
"error": "CODE001"
|
79
|
+
}
|
80
|
+
```
|
81
|
+
|
82
|
+
|
83
|
+
Let's test it out quickly from the command line:
|
84
|
+
|
85
|
+
|
86
|
+
```bash
|
87
|
+
sneakers work Processor --require boot.rb --front
|
88
|
+
```
|
89
|
+
|
90
|
+
We just told Sneakers to spawn a worker named `Processor`, but first `--require` a file that we dedicate to setting up environment, including workers and what-not.
|
91
|
+
|
92
|
+
For simplicity, we also told Sneakers to *not* daemonize and work at the `--front`.
|
93
|
+
|
94
|
+
If you go to your RabbitMQ admin now, you'll see a new queue named `logs` was created. Push a couple messages, and this is the output you should see at your terminal.
|
95
|
+
|
96
|
+
|
97
|
+
```
|
98
|
+
2013-10-11T19:26:36Z p-4718 t-ovqgyb31o DEBUG: [worker-logs:1:213mmy][#<Thread:0x007fae6b05cc58>][logs][{:prefetch=>10, :durable=>true, :ack=>true, :heartbeat_interval=>2, :exchange=>"sneakers"}] Working off: log log
|
99
|
+
2013-10-11T19:26:36Z p-4718 t-ovqgyrxu4 INFO: log log
|
100
|
+
2013-10-11T19:26:40Z p-4719 t-ovqgyb364 DEBUG: [worker-logs:1:h23iit][#<Thread:0x007fae6b05cd98>][logs][{:prefetch=>10, :durable=>true, :ack=>true, :heartbeat_interval=>2, :exchange=>"sneakers"}] Working off: log log
|
101
|
+
2013-10-11T19:26:40Z p-4719 t-ovqgyrx8g INFO: log log
|
102
|
+
```
|
103
|
+
|
104
|
+
And redis will show this:
|
105
|
+
|
106
|
+
|
107
|
+
```
|
108
|
+
➜ ~ redis-cli monitor
|
109
|
+
1381520329.888581 [0 127.0.0.1:49182] "incr" "processor:CODE001"
|
110
|
+
```
|
111
|
+
|
112
|
+
|
113
|
+
We're basically done with the ceremonies and all is left is to do some real work.
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
### Looking at metrics
|
118
|
+
|
119
|
+
Let's use the `logging_metrics` provider just for the sake of fun of seeing the metrics as they happen.
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
# boot.rb
|
123
|
+
require 'sneakers'
|
124
|
+
require 'redis'
|
125
|
+
require 'json'
|
126
|
+
require 'sneakers/metrics/logging_metrics'
|
127
|
+
Sneakers.configure :metrics => Sneakers::Metrics::LoggingMetrics.new
|
128
|
+
|
129
|
+
# ... rest of code
|
130
|
+
```
|
131
|
+
|
132
|
+
Now push a message again and you'll see:
|
133
|
+
|
134
|
+
```
|
135
|
+
2013-10-11T19:44:37Z p-9219 t-oxh8owywg INFO: INC: work.Processor.started
|
136
|
+
2013-10-11T19:44:37Z p-9219 t-oxh8owywg INFO: TIME: work.Processor.time 0.00242
|
137
|
+
2013-10-11T19:44:37Z p-9219 t-oxh8owywg INFO: INC: work.Processor.handled.ack
|
138
|
+
```
|
139
|
+
|
140
|
+
Which increments start + end, and times the work unit.
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
From here, you can continue over to the
|
145
|
+
[[Wiki]](https://github.com/jondot/sneakers/wiki)
|
146
|
+
|
147
|
+
# Contributing
|
148
|
+
|
149
|
+
Fork, implement, add tests, pull request, get my everlasting thanks and a respectable place here :).
|
150
|
+
|
151
|
+
# Copyright
|
152
|
+
|
153
|
+
Copyright (c) 2013 [Dotan Nahum](http://gplus.to/dotan) [@jondot](http://twitter.com/jondot). See MIT-LICENSE for further details.
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
|
22
159
|
|
23
|
-
## Contributing
|
24
160
|
|
25
|
-
1. Fork it
|
26
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
data/Rakefile
CHANGED
data/bin/sneakers
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$: << File.expand_path('../lib', File.dirname(__FILE__))
|
2
|
+
require 'sneakers'
|
3
|
+
|
4
|
+
class BenchmarkWorker
|
5
|
+
include Sneakers::Worker
|
6
|
+
from_queue 'downloads',
|
7
|
+
:env => 'test',
|
8
|
+
:durable => false,
|
9
|
+
:ack => true,
|
10
|
+
:threads => 50,
|
11
|
+
:prefetch => 50,
|
12
|
+
:timeout_job_after => 1,
|
13
|
+
:exchange => 'dummy',
|
14
|
+
:heartbeat_interval => 5
|
15
|
+
def work(msg)
|
16
|
+
ack!
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
$: << File.expand_path('../lib', File.dirname(__FILE__))
|
2
|
+
require 'sneakers'
|
3
|
+
require 'sneakers/runner'
|
4
|
+
require 'sneakers/metrics/logging_metrics'
|
5
|
+
require 'open-uri'
|
6
|
+
require 'nokogiri'
|
7
|
+
|
8
|
+
|
9
|
+
class MetricsWorker
|
10
|
+
include Sneakers::Worker
|
11
|
+
|
12
|
+
from_queue 'downloads'
|
13
|
+
|
14
|
+
def work(msg)
|
15
|
+
doc = Nokogiri::HTML(open(msg))
|
16
|
+
logger.info "FOUND <#{doc.css('title').text}>"
|
17
|
+
ack!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
Sneakers.configure( :daemonize => false, :log => STDOUT, :metrics => Sneakers::Metrics::LoggingMetrics.new)
|
23
|
+
r = Sneakers::Runner.new([ MetricsWorker ])
|
24
|
+
r.run
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
$: << File.expand_path('../lib', File.dirname(__FILE__))
|
2
|
+
require 'sneakers'
|
3
|
+
require 'sneakers/runner'
|
4
|
+
require 'ruby-prof'
|
5
|
+
|
6
|
+
|
7
|
+
puts "feeding messages in"
|
8
|
+
1000.times {
|
9
|
+
Sneakers.publish("{}", :to_queue => 'downloads')
|
10
|
+
puts "done"
|
11
|
+
|
12
|
+
|
13
|
+
class ProfilingWorker
|
14
|
+
include Sneakers::Worker
|
15
|
+
from_queue 'downloads',
|
16
|
+
:env => '',
|
17
|
+
:durable => false,
|
18
|
+
:ack => true,
|
19
|
+
:threads => 50,
|
20
|
+
:prefetch => 50,
|
21
|
+
:timeout_job_after => 1,
|
22
|
+
:exchange => 'dummy',
|
23
|
+
:heartbeat_interval => 5
|
24
|
+
def work(msg)
|
25
|
+
ack!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
r = Sneakers::Runner.new
|
32
|
+
Sneakers::Worker.configure_logger(Logger.new('/dev/null'))
|
33
|
+
|
34
|
+
# ctrl-c and Ruby 2.0 breaks signal handling
|
35
|
+
# Sidekiq has same issues
|
36
|
+
# https://github.com/mperham/sidekiq/issues/728
|
37
|
+
#
|
38
|
+
# so we use a timeout and a thread that kills profiling
|
39
|
+
puts "profiling start"
|
40
|
+
RubyProf.start
|
41
|
+
|
42
|
+
Thread.new do
|
43
|
+
sleep 10
|
44
|
+
puts "stopping profiler"
|
45
|
+
result = RubyProf.stop
|
46
|
+
|
47
|
+
# Print a flat profile to text
|
48
|
+
printer = RubyProf::FlatPrinter.new(result)
|
49
|
+
printer.print(STDOUT)
|
50
|
+
r.stop
|
51
|
+
exit(0)
|
52
|
+
end
|
53
|
+
|
54
|
+
r.run([ ProfilingWorker ])
|
55
|
+
|