sneakers 2.3.5 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b0d4672a260de0253f534bfd74c49588df84d56
4
- data.tar.gz: e8d4eee7b40b2624b2fb99f24a210305d9dff64a
3
+ metadata.gz: 681e186272e780e4a969428ad17b2cef7e2f2a17
4
+ data.tar.gz: e26f11fd1c1282784a2b362d8e263f7b54cb9790
5
5
  SHA512:
6
- metadata.gz: da994869c06cc5c0fdb8d12c7c3b23f3969ab93db70200d7ffdf67ff4001d7aedc86eb2587ff11a7152683fb87222f500827c7f70bc2c42496eac7b22dc03b77
7
- data.tar.gz: fc60b50180bb952c197c3bf553cb9fff63db09bb8bdd86a5dbf7335cce2ef49ba01ea669276601023b56379f2d97bcdc3d3a027490402c8781a8b7073b58f234
6
+ metadata.gz: 33b0a1d5f160771d38b3a8613a8f5b6022709bd1188e73cf2258a130389769bbec744867c76663182b737177718116ed88742e9a61285e61b3b3e4c99ebe2187
7
+ data.tar.gz: a6d4f4c557c7af9a01863b9b95ab3fd02bf4cb0a6670fe15dcd2e3c0f152839b0dba5a52b67271a83be1044f9b8e80a513f4f365343cc254ee5fb1ab22882719
data/.travis.yml CHANGED
@@ -6,12 +6,10 @@ cache: bundler
6
6
  language: ruby
7
7
  rvm:
8
8
  - ruby-head
9
- - 2.2
10
- - 2.1
11
- - 2.0.0
9
+ - 2.2.5
12
10
  matrix:
13
11
  include:
14
- - rvm: 2.2
12
+ - rvm: 2.2.5
15
13
  env: INTEGRATION_LOG=1 INTEGRATION=1
16
14
 
17
15
 
data/Dockerfile ADDED
@@ -0,0 +1,13 @@
1
+ FROM ruby:2.3-alpine
2
+
3
+ RUN apk add --no-cache git
4
+ RUN apk --update add --virtual build_deps \
5
+ build-base ruby-dev libc-dev linux-headers \
6
+ openssl-dev
7
+
8
+ ADD . /sneakers
9
+ WORKDIR /sneakers
10
+
11
+ RUN bundle --jobs=4 --retry=3
12
+
13
+ CMD rake test
data/Dockerfile.slim ADDED
@@ -0,0 +1,13 @@
1
+ FROM ruby:2.3-alpine
2
+
3
+ RUN apk add --no-cache git
4
+ ADD . /sneakers
5
+ WORKDIR /sneakers
6
+
7
+ RUN apk --update add --virtual build_deps \
8
+ build-base ruby-dev libc-dev linux-headers \
9
+ openssl-dev && \
10
+ bundle --jobs=4 --retry=3 && \
11
+ apk del build_deps
12
+
13
+ CMD rake test
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013-2014 Dotan Nahum
1
+ Copyright (c) 2013-2016 Dotan Nahum
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Sneakers
2
2
 
3
+ [![Build Status](https://travis-ci.org/jondot/sneakers.svg?branch=master)](https://travis-ci.org/jondot/sneakers)
3
4
 
4
5
  ```
5
6
  __
@@ -153,6 +154,29 @@ Which increments `started` and `handled.ack`, and times the work unit.
153
154
  From here, you can continue over to the
154
155
  [Wiki](https://github.com/jondot/sneakers/wiki)
155
156
 
157
+ # Docker
158
+
159
+ If you use Docker, there's some benefits to be had and you can use both
160
+ `docker` and `docker-compose` with this project, in order to run tests,
161
+ integration tests or a sample worker without setting up RabbitMQ or the
162
+ environment needed locally on your development box.
163
+
164
+ * To build a container run `docker build .`
165
+ * To run non-integration tests within a docker container, run `docker run --rm
166
+ sneakers_sneakers:latest`
167
+ * To run full integration tests within a docker topology including RabbitMQ,
168
+ Redis (for integration worker) run `scripts/local_integration`, which will
169
+ use docker-compose to orchestrate the topology and the sneakers Docker image
170
+ to run the tests
171
+ * To run a sample worker within Docker, try the `TitleScraper` example by
172
+ running `script/local_worker`. This will use docker-compose as well. It will
173
+ also help you get a feeling for how to run Sneakers in a Docker based
174
+ production environment
175
+ * User `Dockerfile.slim` instead of `Dockerfile` for production docker builds.
176
+ It generates a more compact image, while the "regular" `Dockerfile` generates
177
+ a fatter image - yet faster to iterate when developing
178
+
179
+
156
180
  # Compatibility
157
181
 
158
182
  * Sneakers 1.1.x and up (using the new generation Bunny 2.x) - Ruby 2.x.x
data/Rakefile CHANGED
@@ -5,6 +5,7 @@ require 'rake/testtask'
5
5
  Rake::TestTask.new do |t|
6
6
  t.libs << "spec"
7
7
  t.test_files = FileList['spec/**/*_spec.rb']
8
+ t.warning = false
8
9
  end
9
10
 
10
11
  task default: :test
@@ -0,0 +1,17 @@
1
+ version: '2'
2
+ services:
3
+ sneakers:
4
+ build: .
5
+ depends_on:
6
+ - rabbitmq
7
+ - redis
8
+ rabbitmq:
9
+ image: rabbitmq:management
10
+ ports:
11
+ - "5672:5672"
12
+ - "15672:15672"
13
+ redis:
14
+ image: redis
15
+ ports:
16
+ - "6379:6379"
17
+
@@ -3,7 +3,6 @@ require 'sneakers'
3
3
  require 'sneakers/runner'
4
4
  require 'sneakers/metrics/logging_metrics'
5
5
  require 'open-uri'
6
- require 'nokogiri'
7
6
 
8
7
 
9
8
  class MetricsWorker
@@ -12,10 +11,17 @@ class MetricsWorker
12
11
  from_queue 'downloads'
13
12
 
14
13
  def work(msg)
15
- doc = Nokogiri::HTML(open(msg))
16
- logger.info "FOUND <#{doc.css('title').text}>"
14
+ title = extract_title(open(msg))
15
+ logger.info "FOUND <#{title}>"
17
16
  ack!
18
17
  end
18
+
19
+ private
20
+
21
+ def extract_title(html)
22
+ html =~ /<title>(.*?)<\/title>/
23
+ $1
24
+ end
19
25
  end
20
26
 
21
27
 
@@ -3,7 +3,6 @@ require 'sneakers'
3
3
  require 'sneakers/runner'
4
4
  require 'sneakers/metrics/newrelic_metrics'
5
5
  require 'open-uri'
6
- require 'nokogiri'
7
6
  require 'newrelic_rpm'
8
7
 
9
8
  # With this configuration will send two types of data to newrelic server:
@@ -22,13 +21,19 @@ class MetricsWorker
22
21
  from_queue 'downloads'
23
22
 
24
23
  def work(msg)
25
- doc = Nokogiri::HTML(open(msg))
26
- logger.info "FOUND <#{doc.css('title').text}>"
24
+ title = extract_title(open(msg))
25
+ logger.info "FOUND <#{title}>"
27
26
  ack!
28
27
  end
29
28
 
30
29
  add_transaction_tracer :work, name: 'MetricsWorker', params: 'args[0]'
31
30
 
31
+ private
32
+
33
+ def extract_title(html)
34
+ html =~ /<title>(.*?)<\/title>/
35
+ $1
36
+ end
32
37
  end
33
38
 
34
39
 
@@ -1,10 +1,16 @@
1
1
  require "sneakers"
2
2
  require 'open-uri'
3
- require 'nokogiri'
4
-
5
3
  require 'logger'
6
4
 
7
- Sneakers.configure :log => STDOUT
5
+ def compose_or_localhost(key)
6
+ Resolv::DNS.new.getaddress(key)
7
+ rescue
8
+ "localhost"
9
+ end
10
+
11
+ rmq_addr = compose_or_localhost("rabbitmq")
12
+
13
+ Sneakers.configure :log => STDOUT, :amqp => "amqp://guest:guest@#{rmq_addr}:5672"
8
14
  Sneakers.logger.level = Logger::INFO
9
15
 
10
16
  class TitleScraper
@@ -13,10 +19,17 @@ class TitleScraper
13
19
  from_queue 'downloads'
14
20
 
15
21
  def work(msg)
16
- doc = Nokogiri::HTML(open(msg))
17
- worker_trace "FOUND <#{doc.css('title').text}>"
22
+ title = extract_title(open(msg))
23
+ logger.info "FOUND <#{title}>"
18
24
  ack!
19
25
  end
26
+
27
+ private
28
+
29
+ def extract_title(html)
30
+ html =~ /<title>(.*?)<\/title>/
31
+ $1
32
+ end
20
33
  end
21
34
 
22
35
 
data/lib/sneakers.rb CHANGED
@@ -75,6 +75,16 @@ module Sneakers
75
75
  yield self if server?
76
76
  end
77
77
 
78
+ # Register a proc to handle any error which occurs within the Sneakers process.
79
+ #
80
+ # Sneakers.error_reporters << proc {|ex,ctx_hash| MyErrorService.notify(ex, ctx_hash) }
81
+ #
82
+ # The default error handler logs errors to Sneakers.logger.
83
+ # Ripped off from https://github.com/mperham/sidekiq/blob/6ad6a3aa330deebd76c6cf0d353f66abd3bef93b/lib/sidekiq.rb#L165-L174
84
+ def error_reporters
85
+ CONFIG[:error_reporters]
86
+ end
87
+
78
88
  private
79
89
 
80
90
  def setup_general_logger!
data/lib/sneakers/cli.rb CHANGED
@@ -25,6 +25,8 @@ module Sneakers
25
25
 
26
26
  method_option :debug
27
27
  method_option :daemonize
28
+ method_option :log
29
+ method_option :pid_path
28
30
  method_option :require
29
31
 
30
32
  desc "work FirstWorker,SecondWorker ... ,NthWorker", "Run workers"
@@ -33,7 +35,8 @@ module Sneakers
33
35
  :daemonize => !!options[:daemonize]
34
36
  }
35
37
 
36
- opts[:log] = opts[:daemonize] ? 'sneakers.log' : STDOUT
38
+ opts[:log] = options[:log] || (opts[:daemonize] ? 'sneakers.log' : STDOUT)
39
+ opts[:pid_path] = options[:pid_path] if options[:pid_path]
37
40
 
38
41
  if opts[:daemonize]
39
42
  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."
@@ -1,3 +1,4 @@
1
+ require 'sneakers/error_reporter'
1
2
  require 'forwardable'
2
3
 
3
4
  module Sneakers
@@ -21,6 +22,10 @@ module Sneakers
21
22
  }.freeze
22
23
 
23
24
  DEFAULTS = {
25
+ # Set up default handler which just logs the error.
26
+ # Remove this in production if you don't want sensitive data logged.
27
+ :error_reporters => [Sneakers::ErrorReporter::DefaultLogger.new],
28
+
24
29
  # runner
25
30
  :runner_config_file => nil,
26
31
  :metrics => nil,
@@ -29,7 +34,7 @@ module Sneakers
29
34
  :workers => 4,
30
35
  :log => STDOUT,
31
36
  :pid_path => 'sneakers.pid',
32
- :amqp_heartbeat => 10,
37
+ :amqp_heartbeat => 30,
33
38
 
34
39
  # workers
35
40
  :timeout_job_after => 5,
@@ -37,7 +42,7 @@ module Sneakers
37
42
  :threads => 10,
38
43
  :share_threads => false,
39
44
  :ack => true,
40
- :heartbeat => 2,
45
+ :heartbeat => 30,
41
46
  :hooks => {},
42
47
  :exchange => 'sneakers',
43
48
  :exchange_options => EXCHANGE_OPTION_DEFAULTS,
@@ -0,0 +1,27 @@
1
+ # Ripped off from https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/exception_handler.rb
2
+ module Sneakers
3
+ module ErrorReporter
4
+ class DefaultLogger
5
+ def call(exception, context_hash)
6
+ Sneakers.logger.warn(context_hash) unless context_hash.empty?
7
+ log_string = ''
8
+ log_string += "[Exception error=#{exception.message.inspect} error_class=#{exception.class}" unless exception.nil?
9
+ log_string += " backtrace=#{exception.backtrace.take(50).join(',')}" unless exception.nil? || exception.backtrace.nil?
10
+ log_string += ']'
11
+ Sneakers.logger.error log_string
12
+ end
13
+ end
14
+
15
+ def worker_error(exception, context_hash = {})
16
+ Sneakers.error_reporters.each do |handler|
17
+ begin
18
+ handler.call(exception, context_hash)
19
+ rescue => inner_exception
20
+ Sneakers.logger.error '!!! ERROR REPORTER THREW AN ERROR !!!'
21
+ Sneakers.logger.error inner_exception
22
+ Sneakers.logger.error inner_exception.backtrace.join("\n") unless inner_exception.backtrace.nil?
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -140,7 +140,7 @@ module Sneakers
140
140
  payload: Base64.encode64(msg.to_s)
141
141
  }.tap do |hash|
142
142
  if reason.is_a?(Exception)
143
- hash[:error_class] = reason.class
143
+ hash[:error_class] = reason.class.to_s
144
144
  hash[:error_message] = "#{reason}"
145
145
  if reason.backtrace
146
146
  hash[:backtrace] = reason.backtrace.take(10).join(', ')
@@ -13,8 +13,10 @@ module Sneakers
13
13
  @exec_string = "bundle exec rake sneakers:run"
14
14
  worker_config = YAML.load(File.read(worker_group_config_file))
15
15
  worker_config.keys.each do |group_name|
16
+ workers = worker_config[group_name]['classes']
17
+ workers = workers.join "," if workers.is_a?(Array)
16
18
  @pids << fork do
17
- @exec_hash = {"WORKERS"=> worker_config[group_name]['classes'], "WORKER_COUNT" => worker_config[group_name]["workers"].to_s}
19
+ @exec_hash = {"WORKERS"=> workers, "WORKER_COUNT" => worker_config[group_name]["workers"].to_s}
18
20
  Kernel.exec(@exec_hash, @exec_string)
19
21
  end
20
22
  end
@@ -24,4 +26,4 @@ module Sneakers
24
26
  Process.waitall
25
27
  end
26
28
  end
27
- end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module Sneakers
2
- VERSION = "2.3.5"
2
+ VERSION = "2.4.0"
3
3
  end
@@ -10,6 +10,7 @@ module Sneakers
10
10
  # (because it uses methods from them directly.)
11
11
  include Concerns::Logging
12
12
  include Concerns::Metrics
13
+ include Sneakers::ErrorReporter
13
14
 
14
15
  def initialize(queue = nil, pool = nil, opts = {})
15
16
  opts = opts.merge(self.class.queue_opts || {})
@@ -59,13 +60,13 @@ module Sneakers
59
60
  end
60
61
  end
61
62
  end
62
- rescue Timeout::Error
63
+ rescue Timeout::Error => ex
63
64
  res = :timeout
64
- worker_error('timeout')
65
+ worker_error(ex, log_msg: log_msg(msg), message: msg)
65
66
  rescue => ex
66
67
  res = :error
67
68
  error = ex
68
- worker_error('unexpected error', ex)
69
+ worker_error(ex, log_msg: log_msg(msg), message: msg)
69
70
  end
70
71
 
71
72
  if @should_ack
@@ -92,6 +93,8 @@ module Sneakers
92
93
  end
93
94
 
94
95
  def stop
96
+ worker_trace "Stopping worker: shutting down thread pool."
97
+ @pool.shutdown
95
98
  worker_trace "Stopping worker: unsubscribing."
96
99
  @queue.unsubscribe
97
100
  worker_trace "Stopping worker: I'm gone."
@@ -108,17 +111,6 @@ module Sneakers
108
111
  "[#{@id}][#{Thread.current}][#{@queue.name}][#{@queue.opts}] #{msg}"
109
112
  end
110
113
 
111
- # Helper to log an error message with an optional exception
112
- def worker_error(msg, exception = nil)
113
- s = log_msg(msg)
114
- if exception
115
- s += " [Exception error=#{exception.message.inspect} error_class=#{exception.class}"
116
- s += " backtrace=#{exception.backtrace.take(50).join(',')}" unless exception.backtrace.nil?
117
- s += "]"
118
- end
119
- logger.error(s)
120
- end
121
-
122
114
  def worker_trace(msg)
123
115
  logger.debug(log_msg(msg))
124
116
  end
@@ -146,7 +138,7 @@ module Sneakers
146
138
  private
147
139
 
148
140
  def publisher
149
- @publisher ||= Sneakers::Publisher.new
141
+ @publisher ||= Sneakers::Publisher.new(queue_opts)
150
142
  end
151
143
  end
152
144
  end
@@ -23,7 +23,13 @@ module Sneakers
23
23
  # when used with many workers.
24
24
  pool = config[:share_threads] ? Thread.pool(config[:threads]) : nil
25
25
 
26
- @workers = config[:worker_classes].map{|w| w.new(nil, pool) }
26
+ worker_classes = config[:worker_classes]
27
+
28
+ if worker_classes.respond_to? :call
29
+ worker_classes = worker_classes.call
30
+ end
31
+
32
+ @workers = worker_classes.map{|w| w.new(nil, pool) }
27
33
  # if more than one worker this should be per worker
28
34
  # accumulate clients and consumers as well
29
35
  @workers.each do |worker|
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ docker-compose run -e INTEGRATION=1 -e INTEGRATION_LOG=1 sneakers rake test
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ docker-compose run sneakers sneakers work TitleScraper --require examples/title_scraper.rb
3
+
data/sneakers.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(/^(test|spec|features)\//)
19
19
  gem.require_paths = ['lib']
20
20
  gem.add_dependency 'serverengine', '~> 1.5.11'
21
- gem.add_dependency 'bunny', '~> 2.2.0'
21
+ gem.add_dependency 'bunny', '~> 2.6'
22
22
  gem.add_dependency 'thread', '~> 0.1.7'
23
23
  gem.add_dependency 'thor'
24
24
 
@@ -27,8 +27,8 @@ Gem::Specification.new do |gem|
27
27
  gem.add_development_dependency 'redis'
28
28
 
29
29
  gem.add_development_dependency 'rr'
30
+ gem.add_development_dependency 'unparser', '0.2.2' # keep below 0.2.5 for ruby 2.0 compat.
30
31
  gem.add_development_dependency 'ruby-prof'
31
- gem.add_development_dependency 'nokogiri'
32
32
  gem.add_development_dependency 'guard-minitest'
33
33
  gem.add_development_dependency 'metric_fu'
34
34
  gem.add_development_dependency 'simplecov'
@@ -2,7 +2,10 @@ require 'sneakers'
2
2
  require 'thread'
3
3
  require 'redis'
4
4
 
5
- $redis = Redis.new
5
+
6
+ redis_addr = compose_or_localhost("redis")
7
+ puts "REDIS is at #{redis_addr}"
8
+ $redis = Redis.new(:host => redis_addr)
6
9
 
7
10
  class IntegrationWorker
8
11
  include Sneakers::Worker
@@ -1,6 +1,5 @@
1
1
  require 'sneakers'
2
2
  require 'open-uri'
3
- require 'nokogiri'
4
3
 
5
4
 
6
5
  class TitleScraper
@@ -9,9 +8,16 @@ class TitleScraper
9
8
  from_queue 'downloads'
10
9
 
11
10
  def work(msg)
12
- doc = Nokogiri::HTML(open(msg))
13
- worker_trace "FOUND <#{doc.css('title').text}>"
11
+ title = extract_title(open(msg))
12
+ logger.info "FOUND <#{title}>"
14
13
  ack!
15
14
  end
15
+
16
+ private
17
+
18
+ def extract_title(html)
19
+ html =~ /<title>(.*?)<\/title>/
20
+ $1
21
+ end
16
22
  end
17
23
 
@@ -20,8 +20,10 @@ describe "integration" do
20
20
  def prepare
21
21
  # clean up all integration queues; admin interface must be installed
22
22
  # in integration env
23
+ rmq_addr = compose_or_localhost("rabbitmq")
24
+ puts "RABBITMQ is at #{rmq_addr}"
23
25
  begin
24
- admin = RabbitMQ::HTTP::Client.new("http://127.0.0.1:15672/", username: "guest", password: "guest")
26
+ admin = RabbitMQ::HTTP::Client.new("http://#{rmq_addr}:15672/", username: "guest", password: "guest")
25
27
  qs = admin.list_queues
26
28
  qs.each do |q|
27
29
  name = q.name
@@ -35,13 +37,14 @@ describe "integration" do
35
37
  end
36
38
 
37
39
  Sneakers.clear!
38
- Sneakers.configure
40
+ Sneakers.configure(:amqp => "amqp://guest:guest@#{rmq_addr}:5672")
39
41
  Sneakers.logger.level = Logger::ERROR
40
42
 
41
43
  # configure integration worker on a random generated queue
42
44
  random_queue = "integration_#{rand(10**36).to_s(36)}"
43
45
 
44
- @redis = Redis.new
46
+ redis_addr = compose_or_localhost("redis")
47
+ @redis = Redis.new(:host => redis_addr)
45
48
  @redis.del(random_queue)
46
49
  IntegrationWorker.from_queue(random_queue)
47
50
  end
@@ -38,7 +38,10 @@ describe Sneakers::Queue do
38
38
 
39
39
  mock(@mkbunny).start {}
40
40
  mock(@mkbunny).create_channel{ @mkchan }
41
- mock(Bunny).new(anything, :vhost => '/', :heartbeat => 2){ @mkbunny }
41
+ mock(Bunny).new(
42
+ anything,
43
+ hash_including(:vhost => '/', :heartbeat => 2)
44
+ ){ @mkbunny }
42
45
  end
43
46
 
44
47
  describe "#subscribe with sneakers exchange" do
@@ -101,7 +104,10 @@ describe Sneakers::Queue do
101
104
  before do
102
105
  # expect default exchange
103
106
  queue_vars[:exchange] = ""
104
- mock(@mkchan).exchange("", :type => :direct, :durable => true){ @mkex }
107
+ mock(@mkchan).exchange("",
108
+ :type => :direct,
109
+ :durable => true,
110
+ :arguments => {"x-arg" => "value"}){ @mkex }
105
111
  end
106
112
 
107
113
  it "does not bind to exchange" do
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
  require 'sneakers'
3
3
  require 'timeout'
4
4
 
5
-
6
5
  class DummyWorker
7
6
  include Sneakers::Worker
8
7
  from_queue 'downloads',
@@ -167,9 +166,12 @@ describe Sneakers::Worker do
167
166
  msg.must_equal(message)
168
167
  opts.must_equal(:to_queue => "defaults")
169
168
  end
169
+ end
170
170
 
171
- stub(Sneakers::Publisher).new { mock }
172
- DefaultsWorker.enqueue(message)
171
+ it "passes the configuration to the publisher" do
172
+ opts = DummyWorker.queue_opts
173
+ mock(Sneakers::Publisher).new(opts) { mock(Object.new).publish(anything, anything) }
174
+ DummyWorker.enqueue(message)
173
175
  end
174
176
  end
175
177
 
@@ -179,6 +181,7 @@ describe Sneakers::Worker do
179
181
  @defaults_q = DefaultsWorker.new.queue
180
182
  @defaults_q.name.must_equal('defaults')
181
183
  @defaults_q.opts.to_hash.must_equal(
184
+ :error_reporters => [Sneakers.error_reporters.last],
182
185
  :runner_config_file => nil,
183
186
  :metrics => nil,
184
187
  :daemonize => true,
@@ -208,8 +211,8 @@ describe Sneakers::Worker do
208
211
  },
209
212
  :hooks => {},
210
213
  :handler => Sneakers::Handlers::Oneshot,
211
- :heartbeat => 2,
212
- :amqp_heartbeat => 10
214
+ :heartbeat => 30,
215
+ :amqp_heartbeat => 30
213
216
  )
214
217
  end
215
218
 
@@ -217,6 +220,7 @@ describe Sneakers::Worker do
217
220
  @dummy_q = DummyWorker.new.queue
218
221
  @dummy_q.name.must_equal('downloads')
219
222
  @dummy_q.opts.to_hash.must_equal(
223
+ :error_reporters => [Sneakers.error_reporters.last],
220
224
  :runner_config_file => nil,
221
225
  :metrics => nil,
222
226
  :daemonize => true,
@@ -247,7 +251,7 @@ describe Sneakers::Worker do
247
251
  :hooks => {},
248
252
  :handler => Sneakers::Handlers::Oneshot,
249
253
  :heartbeat => 5,
250
- :amqp_heartbeat => 10
254
+ :amqp_heartbeat => 30
251
255
  )
252
256
  end
253
257
 
@@ -255,6 +259,7 @@ describe Sneakers::Worker do
255
259
  @deprecated_exchange_opts_q = WithDeprecatedExchangeOptionsWorker.new.queue
256
260
  @deprecated_exchange_opts_q.name.must_equal('defaults')
257
261
  @deprecated_exchange_opts_q.opts.to_hash.must_equal(
262
+ :error_reporters => [Sneakers.error_reporters.last],
258
263
  :runner_config_file => nil,
259
264
  :metrics => nil,
260
265
  :daemonize => true,
@@ -284,8 +289,8 @@ describe Sneakers::Worker do
284
289
  },
285
290
  :hooks => {},
286
291
  :handler => Sneakers::Handlers::Oneshot,
287
- :heartbeat => 2,
288
- :amqp_heartbeat => 10
292
+ :heartbeat => 30,
293
+ :amqp_heartbeat => 30
289
294
  )
290
295
  end
291
296
  end
@@ -334,7 +339,7 @@ describe Sneakers::Worker do
334
339
  handler = Object.new
335
340
  header = Object.new
336
341
  mock(handler).error(header, nil, "msg", anything)
337
- mock(w.logger).error(/unexpected error \[Exception error="foo" error_class=RuntimeError backtrace=.*/)
342
+ mock(w.logger).error(/\[Exception error="foo" error_class=RuntimeError backtrace=.*/)
338
343
  w.do_work(header, nil, "msg", handler)
339
344
  end
340
345
 
@@ -356,7 +361,7 @@ describe Sneakers::Worker do
356
361
  header = Object.new
357
362
 
358
363
  mock(handler).timeout(header, nil, "msg")
359
- mock(w.logger).error(/timeout/)
364
+ mock(w.logger).error(/error="execution expired" error_class=Timeout::Error backtrace=/)
360
365
 
361
366
  w.do_work(header, nil, "msg", handler)
362
367
  end
@@ -454,8 +459,9 @@ describe Sneakers::Worker do
454
459
  describe '#worker_error' do
455
460
  it 'only logs backtraces if present' do
456
461
  w = DummyWorker.new(@queue, TestPool.new)
457
- mock(w.logger).error(/cuz \[Exception error="boom!" error_class=RuntimeError\]/)
458
- w.worker_error('cuz', RuntimeError.new('boom!'))
462
+ mock(w.logger).warn('cuz')
463
+ mock(w.logger).error(/\[Exception error="boom!" error_class=RuntimeError\]/)
464
+ w.worker_error(RuntimeError.new('boom!'), 'cuz')
459
465
  end
460
466
  end
461
467
 
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'bundler/setup'
2
2
  require 'simplecov'
3
+ require 'resolv'
3
4
  SimpleCov.start do
4
5
  add_filter "/spec/"
5
6
  end
@@ -8,6 +9,11 @@ require 'minitest/autorun'
8
9
 
9
10
  require 'rr'
10
11
 
12
+ def compose_or_localhost(key)
13
+ Resolv::DNS.new.getaddress(key)
14
+ rescue
15
+ "localhost"
16
+ end
11
17
 
12
18
 
13
19
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sneakers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.5
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dotan Nahum
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-13 00:00:00.000000000 Z
11
+ date: 2016-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: serverengine
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.2.0
33
+ version: '2.6'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.2.0
40
+ version: '2.6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: thread
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -109,21 +109,21 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: ruby-prof
112
+ name: unparser
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: 0.2.2
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: 0.2.2
125
125
  - !ruby/object:Gem::Dependency
126
- name: nokogiri
126
+ name: ruby-prof
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
@@ -244,6 +244,8 @@ extra_rdoc_files: []
244
244
  files:
245
245
  - ".gitignore"
246
246
  - ".travis.yml"
247
+ - Dockerfile
248
+ - Dockerfile.slim
247
249
  - Gemfile
248
250
  - Guardfile
249
251
  - LICENSE.txt
@@ -251,6 +253,7 @@ files:
251
253
  - ROADMAP.md
252
254
  - Rakefile
253
255
  - bin/sneakers
256
+ - docker-compose.yaml
254
257
  - examples/benchmark_worker.rb
255
258
  - examples/max_retry_handler.rb
256
259
  - examples/metrics_worker.rb
@@ -264,6 +267,7 @@ files:
264
267
  - lib/sneakers/concerns/logging.rb
265
268
  - lib/sneakers/concerns/metrics.rb
266
269
  - lib/sneakers/configuration.rb
270
+ - lib/sneakers/error_reporter.rb
267
271
  - lib/sneakers/handlers/maxretry.rb
268
272
  - lib/sneakers/handlers/oneshot.rb
269
273
  - lib/sneakers/metrics/logging_metrics.rb
@@ -280,6 +284,8 @@ files:
280
284
  - lib/sneakers/version.rb
281
285
  - lib/sneakers/worker.rb
282
286
  - lib/sneakers/workergroup.rb
287
+ - scripts/local_integration
288
+ - scripts/local_worker
283
289
  - sneakers.gemspec
284
290
  - spec/fixtures/integration_worker.rb
285
291
  - spec/fixtures/require_worker.rb
@@ -315,7 +321,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
315
321
  version: '0'
316
322
  requirements: []
317
323
  rubyforge_project:
318
- rubygems_version: 2.4.5.1
324
+ rubygems_version: 2.5.1
319
325
  signing_key:
320
326
  specification_version: 4
321
327
  summary: Fast background processing framework for Ruby and RabbitMQ