sneakers 0.0.7 → 0.1.0.pre

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/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