sneakers 0.0.7 → 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # 0.1.0, Not released yet
2
+
3
+ + Added newrelic stats reporter (@arielze)
4
+ + Added explicit routing_key at queue (@arielze)
5
+ + Depracating self-daemonization (@jondot)
6
+ + updating bunny (@michaelklishin)
7
+ + Fix reference in publisher (@sergei-matheson)
8
+ + Allow binding of multiple routing keys (@SebastianEdwards)
9
+ + added work_with_params for advanced handling of work items with amqp
10
+ headers. (#12)
11
+ + Bunny.not_environmental! will no disable auto-environment discovery.
12
+ (#15)
13
+
14
+
15
+
16
+
17
+ # 0.0.7
18
+
19
+ + Sneakers core.
20
+
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sneakers (0.0.6)
5
- bunny (>= 0.10.0)
4
+ sneakers (0.1.0)
5
+ bunny (~> 1.0.7)
6
6
  serverengine
7
7
  thor
8
8
  thread
@@ -13,12 +13,12 @@ GEM
13
13
  activesupport (3.2.15)
14
14
  i18n (~> 0.6, >= 0.6.4)
15
15
  multi_json (~> 1.0)
16
- amq-protocol (1.8.0)
16
+ amq-protocol (1.9.2)
17
17
  arrayfields (4.9.0)
18
18
  awesome_print (1.2.0)
19
19
  bluff (0.1.0)
20
- bunny (0.10.8)
21
- amq-protocol (>= 1.6.0)
20
+ bunny (1.0.7)
21
+ amq-protocol (>= 1.9.2)
22
22
  cane (2.6.0)
23
23
  parallel
24
24
  celluloid (0.15.2)
@@ -124,7 +124,7 @@ GEM
124
124
  sexp_processor (~> 4.0)
125
125
  ruby_parser (3.2.2)
126
126
  sexp_processor (~> 4.1)
127
- serverengine (1.5.5)
127
+ serverengine (1.5.7)
128
128
  sigdump (~> 0.2.2)
129
129
  sexp_processor (4.3.0)
130
130
  sigdump (0.2.2)
@@ -135,7 +135,7 @@ GEM
135
135
  simplecov-rcov-text (0.0.2)
136
136
  slop (3.4.6)
137
137
  thor (0.18.1)
138
- thread (0.1.1)
138
+ thread (0.1.3)
139
139
  timers (1.1.0)
140
140
 
141
141
  PLATFORMS
data/README.md CHANGED
@@ -12,6 +12,10 @@
12
12
  A high-performance RabbitMQ background processing framework for
13
13
  Ruby.
14
14
 
15
+
16
+ Sneakers is being used in production for both I/O and CPU intensive workloads, and have achieved the goals of high-performance and 0-maintenance, as designed.
17
+
18
+
15
19
  Visit the [wiki](https://github.com/jondot/sneakers/wiki) for
16
20
  complete docs.
17
21
 
@@ -146,6 +150,17 @@ From here, you can continue over to the
146
150
 
147
151
  Fork, implement, add tests, pull request, get my everlasting thanks and a respectable place here :).
148
152
 
153
+
154
+ ### Thanks:
155
+
156
+ * Michael Klishin - @michaelklishin
157
+ * Ariel Zerahia - @arielze
158
+ * @sergei-matheson
159
+ * Sebastian Edwards - @SebastianEdwards
160
+ * Tor Ivry - @torkale
161
+
162
+
163
+
149
164
  # Copyright
150
165
 
151
166
  Copyright (c) 2013 [Dotan Nahum](http://gplus.to/dotan) [@jondot](http://twitter.com/jondot). See MIT-LICENSE for further details.
data/ROADMAP.md ADDED
@@ -0,0 +1,18 @@
1
+ # Roadmap
2
+
3
+ It is essential to keep a clear roadmap.
4
+ In its core, Sneakers is already production-ready. However, it is vital
5
+ to take in feedback and improve what can be improved :)
6
+
7
+ This document will communicate the stages that the next version is at.
8
+ See `CHANGELOG.md` for new features that are in.
9
+
10
+
11
+ # v0.1.0 (next version)
12
+
13
+ - Taking in community pull requests and feedback
14
+ - Verify production readiness and performance
15
+ - Full performance test suite
16
+
17
+
18
+
data/lib/sneakers.rb CHANGED
@@ -65,6 +65,10 @@ module Sneakers
65
65
  @configured = false
66
66
  end
67
67
 
68
+ def self.not_environmental!
69
+ Config[:env] = nil
70
+ end
71
+
68
72
  def self.daemonize!(loglevel=Logger::INFO)
69
73
  Config[:log] = 'sneakers.log'
70
74
  Config[:daemonize] = true
data/lib/sneakers/cli.rb CHANGED
@@ -35,6 +35,10 @@ module Sneakers
35
35
 
36
36
  opts[:log] = opts[:daemonize] ? 'sneakers.log' : STDOUT
37
37
 
38
+ if opts[:daemonize]
39
+ puts "*** DEPRACATED: self-daemonization '--daemonize' is considered a bad practice, which is why this feature will be removed in future versions. Please run Sneakers in front, and use things like upstart, systemd, or supervisor to manage it as a daemon."
40
+ end
41
+
38
42
 
39
43
  Sneakers.configure(opts)
40
44
 
@@ -0,0 +1,37 @@
1
+ module Sneakers
2
+ module Metrics
3
+ class NewrelicMetrics
4
+
5
+ def self.eagent(eagent = nil)
6
+ @eagent = eagent || @eagent
7
+ end
8
+
9
+ def initialize()
10
+ #@connection = conn
11
+ end
12
+
13
+ def increment(metric)
14
+ record_stat metric, 1
15
+ end
16
+
17
+ def record_stat(metric, num)
18
+ stats(metric).record_data_point(num)
19
+ rescue Exception => e
20
+ puts "NewrelicMetrics#record_stat: #{e}"
21
+ end
22
+
23
+ def timing(metric, &block)
24
+ start = Time.now
25
+ block.call
26
+ record_stat(metric, ((Time.now - start)*1000).floor)
27
+ end
28
+
29
+ def stats(metric)
30
+ metric.gsub! "\.", "\/"
31
+ NewrelicMetrics.eagent::Agent.get_stats("Custom/#{metric}")
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+
@@ -28,8 +28,14 @@ class Sneakers::Queue
28
28
 
29
29
  handler = @handler_klass.new(@channel)
30
30
 
31
+ routing_key = @opts[:routing_key] || @name
32
+ routing_keys = [*routing_key]
33
+
31
34
  queue = @channel.queue(@name, :durable => @opts[:durable])
32
- queue.bind(@exchange, :routing_key => @name)
35
+
36
+ routing_keys.each do |key|
37
+ queue.bind(@exchange, :routing_key => key)
38
+ end
33
39
 
34
40
  @consumer = queue.subscribe(:block => false, :ack => @opts[:ack]) do | hdr, props, msg |
35
41
  worker.do_work(hdr, props, msg, handler)
@@ -1,3 +1,3 @@
1
1
  module Sneakers
2
- VERSION = "0.0.7"
2
+ VERSION = "0.1.0.pre"
3
3
  end
@@ -23,6 +23,7 @@ module Sneakers
23
23
  @should_ack = opts[:ack]
24
24
  @timeout_after = opts[:timeout_job_after]
25
25
  @pool = pool || Thread.pool(opts[:threads]) # XXX config threads
26
+ @call_with_params = respond_to?(:work_with_params)
26
27
 
27
28
  @queue = queue || Sneakers::Queue.new(
28
29
  queue_name,
@@ -39,7 +40,7 @@ module Sneakers
39
40
 
40
41
  def publish(msg, routing)
41
42
  return unless routing[:to_queue]
42
- @queue.exchange.publish(msg, :routing_key => QueueName.new(routing[:to_queue], @opts).to_s)
43
+ @queue.exchange.publish(msg, :routing_key => Support::QueueName.new(routing[:to_queue], @opts).to_s)
43
44
  end
44
45
 
45
46
  def do_work(hdr, props, msg, handler)
@@ -53,7 +54,11 @@ module Sneakers
53
54
  metrics.increment("work.#{self.class.name}.started")
54
55
  Timeout.timeout(@timeout_after) do
55
56
  metrics.timing("work.#{self.class.name}.time") do
56
- res = work(msg)
57
+ if @call_with_params
58
+ res = work_with_params(msg, hdr, props)
59
+ else
60
+ res = work(msg)
61
+ end
57
62
  end
58
63
  end
59
64
  rescue Timeout::Error
data/sneakers.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
19
  gem.add_dependency "serverengine"
20
- gem.add_dependency "bunny", ">= 0.10.0"
20
+ gem.add_dependency "bunny", "~> 1.0.7"
21
21
  gem.add_dependency "thread"
22
22
  gem.add_dependency "thor"
23
23
 
@@ -9,8 +9,8 @@ describe Sneakers::Queue do
9
9
  end
10
10
 
11
11
  describe "#subscribe" do
12
- it "should setup a bunny queue according to configuration values" do
13
- q = Sneakers::Queue.new("downloads",
12
+ let :queue_vars do
13
+ {
14
14
  :prefetch => 25,
15
15
  :durable => true,
16
16
  :ack => true,
@@ -18,22 +18,40 @@ describe Sneakers::Queue do
18
18
  :vhost => '/',
19
19
  :exchange => "sneakers",
20
20
  :exchange_type => :direct
21
- )
22
- mkbunny = Object.new
23
- mkchan = Object.new
24
- mkex = Object.new
25
- mkqueue = Object.new
26
-
27
- mock(mkbunny).start {}
28
- mock(mkbunny).create_channel{ mkchan }
29
- mock(Bunny).new(anything, :vhost => '/', :heartbeat => 2){ mkbunny }
30
-
31
- mock(mkchan).prefetch(25)
32
- mock(mkchan).exchange("sneakers", :type => :direct, :durable => true){ mkex }
33
- mock(mkchan).queue("downloads", :durable => true){ mkqueue }
34
-
35
- mock(mkqueue).bind(mkex, :routing_key => "downloads")
36
- mock(mkqueue).subscribe(:block => false, :ack => true)
21
+ }
22
+ end
23
+
24
+ before do
25
+ @mkbunny = Object.new
26
+ @mkchan = Object.new
27
+ @mkex = Object.new
28
+ @mkqueue = Object.new
29
+
30
+ mock(@mkbunny).start {}
31
+ mock(@mkbunny).create_channel{ @mkchan }
32
+ mock(Bunny).new(anything, :vhost => '/', :heartbeat => 2){ @mkbunny }
33
+
34
+ mock(@mkchan).prefetch(25)
35
+ mock(@mkchan).exchange("sneakers", :type => :direct, :durable => true){ @mkex }
36
+ mock(@mkchan).queue("downloads", :durable => true){ @mkqueue }
37
+ end
38
+
39
+ it "should setup a bunny queue according to configuration values" do
40
+ q = Sneakers::Queue.new("downloads", queue_vars)
41
+
42
+ mock(@mkqueue).bind(@mkex, :routing_key => "downloads")
43
+ mock(@mkqueue).subscribe(:block => false, :ack => true)
44
+
45
+ q.subscribe(Object.new)
46
+ end
47
+
48
+ it "supports multiple routing_keys" do
49
+ q = Sneakers::Queue.new("downloads",
50
+ queue_vars.merge(:routing_key => ["alpha", "beta"]))
51
+
52
+ mock(@mkqueue).bind(@mkex, :routing_key => "alpha")
53
+ mock(@mkqueue).bind(@mkex, :routing_key => "beta")
54
+ mock(@mkqueue).subscribe(:block => false, :ack => true)
37
55
 
38
56
  q.subscribe(Object.new)
39
57
  end
@@ -1,6 +1,13 @@
1
1
  require 'spec_helper'
2
2
  require 'sneakers'
3
3
 
4
+ class EnvWorker
5
+ include Sneakers::Worker
6
+ from_queue 'defaults'
7
+
8
+ def work(msg)
9
+ end
10
+ end
4
11
 
5
12
 
6
13
  describe Sneakers do
@@ -33,6 +40,19 @@ describe Sneakers do
33
40
  end
34
41
  end
35
42
 
43
+ describe '.not_environmental!' do
44
+ it 'should ignore environment (RACK_ENV) for all workers' do
45
+ Sneakers.configure(:env => 'production')
46
+ Sneakers.not_environmental!
47
+ EnvWorker.new.queue.name.must_equal('defaults')
48
+ end
49
+
50
+ it 'should ignore environment (RACK_ENV) for all workers' do
51
+ Sneakers.configure(:env => 'production')
52
+ EnvWorker.new.queue.name.must_equal('defaults_production')
53
+ end
54
+ end
55
+
36
56
  describe '.clear!' do
37
57
  it 'must reset dirty configuration to default' do
38
58
  Sneakers::Config[:log].must_equal(STDOUT)
@@ -91,6 +91,16 @@ class MetricsWorker
91
91
  end
92
92
  end
93
93
 
94
+ class WithParamsWorker
95
+ include Sneakers::Worker
96
+ from_queue 'defaults',
97
+ :ack => true,
98
+ :timeout_job_after => 0.5
99
+
100
+ def work_with_params(msg, header, props)
101
+ msg
102
+ end
103
+ end
94
104
 
95
105
 
96
106
  class TestPool
@@ -124,8 +134,10 @@ end
124
134
  describe Sneakers::Worker do
125
135
  before do
126
136
  @queue = Object.new
137
+ @exchange = Object.new
127
138
  stub(@queue).name { 'test-queue' }
128
139
  stub(@queue).opts { {} }
140
+ stub(@queue).exchange { @exchange }
129
141
 
130
142
  Sneakers.configure(:env => 'test', :daemonize => true, :log => 'sneakers.log')
131
143
  Sneakers::Worker.configure_logger(Logger.new('/dev/null'))
@@ -275,9 +287,8 @@ describe Sneakers::Worker do
275
287
  describe 'publish' do
276
288
  it 'should be able to publish a message from working context' do
277
289
  w = PublishingWorker.new(@queue, TestPool.new)
278
- mock(w).publish('msg', :to_queue => 'target').once
290
+ mock(@exchange).publish('msg', :routing_key => 'target_test').once
279
291
  w.do_work(nil, nil, 'msg', nil)
280
-
281
292
  end
282
293
  end
283
294
 
@@ -338,4 +349,27 @@ describe Sneakers::Worker do
338
349
  end
339
350
  end
340
351
 
352
+
353
+
354
+ describe 'With Params' do
355
+ before do
356
+ @handler = Object.new
357
+ stub(@handler).acknowledge("tag")
358
+ stub(@handler).reject("tag")
359
+ stub(@handler).timeout("tag")
360
+ stub(@handler).error("tag", anything)
361
+ stub(@handler).noop("tag")
362
+
363
+ @header = Object.new
364
+ stub(@header).delivery_tag { "tag" }
365
+
366
+ @w = WithParamsWorker.new(@queue, TestPool.new)
367
+ mock(@w.metrics).timing("work.WithParamsWorker.time").yields.once
368
+ end
369
+
370
+ it 'should call work_with_params and not work' do
371
+ mock(@w).work_with_params(:ack, @header, {:foo => 1}).once
372
+ @w.do_work(@header, {:foo => 1 }, :ack, @handler)
373
+ end
374
+ end
341
375
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sneakers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
5
- prerelease:
4
+ version: 0.1.0.pre
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Dotan Nahum
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-03 00:00:00.000000000 Z
12
+ date: 2014-01-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: serverengine
@@ -32,17 +32,17 @@ dependencies:
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
- - - ! '>='
35
+ - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 0.10.0
37
+ version: 1.0.7
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ! '>='
43
+ - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 0.10.0
45
+ version: 1.0.7
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: thread
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -212,11 +212,13 @@ extensions: []
212
212
  extra_rdoc_files: []
213
213
  files:
214
214
  - .gitignore
215
+ - CHANGELOG.md
215
216
  - Gemfile
216
217
  - Gemfile.lock
217
218
  - Guardfile
218
219
  - LICENSE.txt
219
220
  - README.md
221
+ - ROADMAP.md
220
222
  - Rakefile
221
223
  - bin/sneakers
222
224
  - examples/benchmark_worker.rb
@@ -231,6 +233,7 @@ files:
231
233
  - lib/sneakers/concerns/metrics.rb
232
234
  - lib/sneakers/handlers/oneshot.rb
233
235
  - lib/sneakers/metrics/logging_metrics.rb
236
+ - lib/sneakers/metrics/newrelic_metrics.rb
234
237
  - lib/sneakers/metrics/null_metrics.rb
235
238
  - lib/sneakers/metrics/statsd_metrics.rb
236
239
  - lib/sneakers/publisher.rb
@@ -268,9 +271,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
268
271
  required_rubygems_version: !ruby/object:Gem::Requirement
269
272
  none: false
270
273
  requirements:
271
- - - ! '>='
274
+ - - ! '>'
272
275
  - !ruby/object:Gem::Version
273
- version: '0'
276
+ version: 1.3.1
274
277
  requirements: []
275
278
  rubyforge_project:
276
279
  rubygems_version: 1.8.23