micro_q 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/.travis.yml +9 -1
  4. data/README.md +5 -2
  5. data/lib/micro_q/config.rb +1 -0
  6. data/lib/micro_q/dsl.rb +41 -16
  7. data/lib/micro_q/manager/default.rb +53 -7
  8. data/lib/micro_q/middleware/chain.rb +15 -2
  9. data/lib/micro_q/middleware/client/statistics.rb +22 -0
  10. data/lib/micro_q/middleware/server/retry.rb +20 -5
  11. data/lib/micro_q/middleware/server/statistics.rb +22 -0
  12. data/lib/micro_q/middleware/server/timeout.rb +19 -0
  13. data/lib/micro_q/middleware/util.rb +21 -0
  14. data/lib/micro_q/queue/default.rb +25 -18
  15. data/lib/micro_q/queue/redis.rb +2 -2
  16. data/lib/micro_q/statistics/base.rb +15 -0
  17. data/lib/micro_q/statistics/default.rb +18 -0
  18. data/lib/micro_q/statistics/redis.rb +23 -0
  19. data/lib/micro_q/version.rb +1 -1
  20. data/lib/micro_q/worker/standard.rb +20 -10
  21. data/lib/micro_q.rb +25 -3
  22. data/micro_q.gemspec +1 -1
  23. data/spec/helpers/methods_examples.rb +1 -1
  24. data/spec/helpers/queues_examples.rb +4 -4
  25. data/spec/lib/config_spec.rb +4 -0
  26. data/spec/lib/dsl_spec.rb +14 -2
  27. data/spec/lib/manager/default_spec.rb +90 -16
  28. data/spec/lib/methods/action_mailer_spec.rb +2 -2
  29. data/spec/lib/methods/active_record_spec.rb +2 -2
  30. data/spec/lib/methods/class_spec.rb +2 -2
  31. data/spec/lib/methods/instance_spec.rb +2 -2
  32. data/spec/lib/micro_q_spec.rb +13 -2
  33. data/spec/lib/middleware/chain_spec.rb +83 -6
  34. data/spec/lib/middleware/client/statistics_spec.rb +53 -0
  35. data/spec/lib/middleware/server/connection_spec.rb +1 -1
  36. data/spec/lib/middleware/server/retry_spec.rb +33 -4
  37. data/spec/lib/middleware/server/statistics_spec.rb +53 -0
  38. data/spec/lib/middleware/server/timeout_spec.rb +40 -0
  39. data/spec/lib/proxies/base_spec.rb +2 -2
  40. data/spec/lib/proxies/instance_spec.rb +1 -1
  41. data/spec/lib/queue/default_spec.rb +2 -4
  42. data/spec/lib/queue/redis_spec.rb +2 -4
  43. data/spec/lib/statistics/default_spec.rb +73 -0
  44. data/spec/lib/statistics/redis_spec.rb +73 -0
  45. data/spec/lib/util_spec.rb +1 -1
  46. data/spec/lib/worker/standard_spec.rb +26 -11
  47. data/spec/lib/wrappers/action_mailer_spec.rb +2 -2
  48. data/spec/spec_helper.rb +1 -1
  49. metadata +49 -58
  50. data/lib/micro_q/methods.rb +0 -7
  51. data/lib/micro_q/wrappers.rb +0 -1
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5d7397239d88fe8ba5027ca54e052af6ee286e32
4
+ data.tar.gz: e52f3922fd037146a570208025aaf64451aa600c
5
+ SHA512:
6
+ metadata.gz: 2318f4b75ccaaa0412809273013d7d8b563356b3cafd0219ed26b2bad66ccd3fd2c753fa8b36b76dade486182ccb12394c6679b2df4ea5edf734e66dcb2d7805
7
+ data.tar.gz: 9b989f109f14acaea6742c95050701aa81631137923a1896c0b43f88a9f088179bf8826cff482205cbff14e228a8e9aefc2c82a3ead9b7762469006275050a9b
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p0@micro_q
data/.travis.yml CHANGED
@@ -1,7 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
+ - 1.9.2
4
5
  - rbx-19mode
6
+ - rbx-nightly-19mode
5
7
  - 2.0.0
6
8
  branches:
7
9
  only:
@@ -12,5 +14,11 @@ notifications:
12
14
  - brian.nort@gmail.com
13
15
  matrix:
14
16
  allow_failures:
17
+ - rvm: 1.9.3
18
+ - rvm: 1.9.2
15
19
  - rvm: rbx-19mode
16
- - rvm: 2.0.0
20
+ - rvm: rbx-nightly-19mode
21
+ branches:
22
+ only:
23
+ - master
24
+ - /^((feature)|(hotfix))\/.+/
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
- # MicroQ [![Build Status](https://travis-ci.org/bnorton/micro_q.png)](https://travis-ci.org/bnorton/micro_q)
1
+ # MicroQ
2
+
3
+ [![Build Status](https://travis-ci.org/bnorton/micro_q.png)](https://travis-ci.org/bnorton/micro_q)
4
+ [![Code Climate](https://codeclimate.com/github/bnorton/micro_q.png)](https://codeclimate.com/github/bnorton/micro_q)
2
5
 
3
6
  MicroQ is a per-process asynchronous background queue.
4
7
 
@@ -42,7 +45,7 @@ MyWorker.async_update(:user_id => user.id)
42
45
 
43
46
  ###Advanced
44
47
 
45
- Safely using an ActiveRecord instance via the Custom Loader API
48
+ Safely using an ActiveRecord instance via the [Custom Loader](https://github.com/bnorton/micro_q/wiki/Loaders) API
46
49
  ```ruby
47
50
  # app/models/user.rb
48
51
  class User < Activerecord::Base
@@ -17,6 +17,7 @@ module MicroQ
17
17
  'manager' => Manager::Default,
18
18
  'worker' => Worker::Standard,
19
19
  'queue' => Queue::Default,
20
+ 'statistics' => Statistics::Default,
20
21
  'redis_pool' => { :size => 15, :timeout => 1 },
21
22
  'redis' => { :host => 'localhost', :port => 6379 }
22
23
  }
data/lib/micro_q/dsl.rb CHANGED
@@ -1,28 +1,53 @@
1
1
  module MicroQ
2
+ ##
3
+ # Convenience methods for calling methods asynchronously
4
+ # Adds async_perform by default
5
+ #
6
+ # Usage
7
+ # class MyWorker
8
+ # worker :update, :queue => 'non-default'
9
+ #
10
+ # def update
11
+ # end
12
+ # end
13
+ #
14
+ # MyWorker.async_update
15
+ # is the same as
16
+ # MyWorker.new.async(:queue => 'non-default').update
17
+ #
2
18
  module DSL
3
- def worker(*opts)
4
- self.class_eval do
5
- def self.microq_options
6
- @microq_options ||= { :methods => [:perform] }
19
+ ##
20
+ # For each of the methods given to the Object.worker method
21
+ # define the async_ prefixed version for convenience
22
+ #
23
+ def self.attach_async_methods(target, opts)
24
+ target.class_eval do
25
+ (target.microq_options[:methods] |= opts.flatten).each do |method|
26
+ target.define_singleton_method(:"async_#{method}") do |*args|
27
+ MicroQ::Proxy::Instance.new(
28
+ target.microq_options.dup.merge(:class => self)
29
+ ).send(method, *args)
30
+ end unless respond_to?(:"async_#{method}")
7
31
  end
8
32
  end
33
+ end
9
34
 
10
- if Hash === opts.last
11
- self.microq_options.merge!(opts.pop)
12
- end
13
-
14
- async_methods = self.microq_options[:methods] |= opts.flatten
35
+ module ClassMethods
36
+ def worker(*opts)
37
+ self.class_eval do
38
+ def self.microq_options
39
+ @microq_options ||= { :methods => [:perform] }
40
+ end
41
+ end
15
42
 
16
- self.class_eval do
17
- async_methods.each do |method|
18
- async_method = :"async_#{method}"
19
- define_singleton_method(async_method) do |*args|
20
- MicroQ::Proxy::Instance.new(:class => self).send(method, *args)
21
- end unless respond_to?(async_method)
43
+ if Hash === opts.last
44
+ self.microq_options.merge!(opts.pop)
22
45
  end
46
+
47
+ DSL.attach_async_methods(self, opts)
23
48
  end
24
49
  end
25
50
  end
26
51
  end
27
52
 
28
- Object.send(:extend, MicroQ::DSL)
53
+ Object.send(:extend, MicroQ::DSL::ClassMethods)
@@ -17,24 +17,70 @@ module MicroQ
17
17
  class Default
18
18
  include Celluloid
19
19
 
20
- attr_reader :queue, :workers
20
+ # Invoke this when the Queue or Worker pool dies
21
+ exit_handler :reinitialize
21
22
 
22
- def initialize
23
- @queue = MicroQ.config.queue.new
24
- @workers = MicroQ.config.worker.pool(:size => MicroQ.config.workers)
25
- end
23
+ attr_reader :queue, :workers
26
24
 
27
25
  def start
28
- count = workers.idle_size
26
+ count = workers.size
29
27
 
30
28
  if (messages = queue.dequeue(count)).any?
31
29
  messages.each do |message|
32
- workers.perform!(message)
30
+ worker = workers.pop
31
+ @busy << worker
32
+
33
+ worker.perform!(message)
33
34
  end
34
35
  end
35
36
 
36
37
  after(2) { start }
37
38
  end
39
+
40
+ def work_done(worker)
41
+ @busy.delete(worker)
42
+ workers.push(worker)
43
+ end
44
+
45
+ ##
46
+ # Handle init/death of the Queue or the Worker pool
47
+ #
48
+ def reinitialize(*)
49
+ kill_all and return if self.class.shutdown?
50
+
51
+ unless @queue && @queue.alive?
52
+ @queue = MicroQ.config.queue.new_link
53
+ end
54
+
55
+ @busy ||= []
56
+
57
+ build_missing_workers
58
+ end
59
+
60
+ alias initialize reinitialize
61
+
62
+ # Don't shrink the pool if the config changes
63
+ def build_missing_workers
64
+ @workers ||= []
65
+
66
+ workers.reject! {|worker| !worker.alive? }
67
+
68
+ [MicroQ.config.workers - (workers.size + @busy.size), 0].max.times do
69
+ workers << MicroQ.config.worker.new_link(current_actor)
70
+ end
71
+ end
72
+
73
+ def kill_all
74
+ (@workers + @busy).each {|w| w.terminate if w.alive? }
75
+ end
76
+
77
+ def self.shutdown?
78
+ !!@shutdown
79
+ end
80
+
81
+ def self.shutdown!
82
+ @shutdown = true
83
+ end
38
84
  end
39
85
  end
40
86
  end
@@ -1,5 +1,10 @@
1
+ require 'micro_q/middleware/util'
1
2
  require 'micro_q/middleware/server/retry'
2
3
  require 'micro_q/middleware/server/connection'
4
+ require 'micro_q/middleware/server/timeout'
5
+ require 'micro_q/middleware/server/statistics'
6
+
7
+ require 'micro_q/middleware/client/statistics'
3
8
 
4
9
  module MicroQ
5
10
  module Middleware
@@ -35,12 +40,14 @@ module MicroQ
35
40
  end
36
41
 
37
42
  class Base
38
- attr_reader :entries
39
-
40
43
  def initialize
41
44
  clear
42
45
  end
43
46
 
47
+ def entries
48
+ [*@entries, @last].compact
49
+ end
50
+
44
51
  ##
45
52
  # Add any number of entries to the middleware chain
46
53
  #
@@ -90,7 +97,9 @@ module MicroQ
90
97
 
91
98
  class Server < Base
92
99
  def initialize
100
+ @last = MicroQ::Middleware::Server::Statistics
93
101
  @entries = [
102
+ MicroQ::Middleware::Server::Timeout,
94
103
  MicroQ::Middleware::Server::Retry,
95
104
  MicroQ::Middleware::Server::Connection
96
105
  ]
@@ -98,6 +107,10 @@ module MicroQ
98
107
  end
99
108
 
100
109
  class Client < Base
110
+ def initialize
111
+ @last = MicroQ::Middleware::Client::Statistics
112
+ super
113
+ end
101
114
  end
102
115
  end
103
116
  end
@@ -0,0 +1,22 @@
1
+ module MicroQ
2
+ module Middleware
3
+ module Client
4
+ class Statistics
5
+ include MicroQ::Middleware::Util
6
+
7
+ ENQUEUED = proc {|klass| klass ? "messages:#{klass}:enqueued" : 'messages:enqueued' }
8
+
9
+ def call(message, options)
10
+ stats(message)
11
+ yield
12
+ end
13
+
14
+ private
15
+
16
+ def stats(msg)
17
+ stats_incr(msg, ENQUEUED, "queues:#{msg['queue']}:enqueued")
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -11,21 +11,36 @@ module MicroQ
11
11
  # when: The time at which the message will be retried again
12
12
  #
13
13
  class Retry
14
+ include MicroQ::Middleware::Util
15
+
16
+ RETRY = proc {|klass| klass ? "messages:#{klass}:retry" : 'messages:retry' }
17
+
14
18
  def call(worker, message)
15
19
  yield
16
20
  rescue Exception => e
17
21
  raise e unless message['retry']
18
22
 
19
- message['retried'] ||= { 'count' => 0 }
20
-
21
- message['retried']['count'] += 1
22
- message['retried']['at'] = Time.now
23
- message['retried']['when'] = (Time.now + 15).to_f
23
+ retried!(message)
24
+ stats(message)
24
25
 
25
26
  MicroQ.push(message, message['retried'])
26
27
 
27
28
  raise e
28
29
  end
30
+
31
+ private
32
+
33
+ def retried!(msg)
34
+ msg['retried'] ||= { 'count' => 0 }
35
+
36
+ msg['retried']['count'] += 1
37
+ msg['retried']['at'] = Time.now
38
+ msg['retried']['when'] = (Time.now + 15).to_f
39
+ end
40
+
41
+ def stats(msg)
42
+ stats_incr(msg, RETRY, "queues:#{msg['queue']}:retry")
43
+ end
29
44
  end
30
45
  end
31
46
  end
@@ -0,0 +1,22 @@
1
+ module MicroQ
2
+ module Middleware
3
+ module Server
4
+ class Statistics
5
+ include MicroQ::Middleware::Util
6
+
7
+ PERFORMED = proc {|klass| klass ? "messages:#{klass}:performed" : 'messages:performed' }
8
+
9
+ def call(_, message)
10
+ stats(message)
11
+ yield
12
+ end
13
+
14
+ private
15
+
16
+ def stats(msg)
17
+ stats_incr(msg, PERFORMED, "queues:#{msg['queue']}:performed")
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module MicroQ
2
+ module Middleware
3
+ module Server
4
+ class Timeout
5
+ DEFAULT = 10 * 60
6
+
7
+ include ::Timeout
8
+
9
+ def call(_, message)
10
+ time = (time = message['timeout'].to_i) > 0 ? time : DEFAULT
11
+
12
+ timeout(time) do
13
+ yield
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module MicroQ
2
+ module Middleware
3
+ module Util
4
+ def stats_incr(msg, generator, *keys)
5
+ statistics do |stats|
6
+ stats.incr(
7
+ generator.call,
8
+ generator.call(msg['class']),
9
+ *keys.flatten
10
+ )
11
+ end
12
+ end
13
+
14
+ def statistics
15
+ MicroQ::Statistics::Default.stats do |stats|
16
+ yield stats
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -53,9 +53,9 @@ module MicroQ
53
53
  #
54
54
  def sync_push(item, options={})
55
55
  item, options = MicroQ::Util.stringify(item, options)
56
- klass = item['class'] = item['class'].to_s
56
+ item['class'] = item['class'].to_s
57
57
 
58
- MicroQ.middleware.client.call(klass, item, options) do
58
+ MicroQ.middleware.client.call(item, options) do
59
59
  if (time = options['when'])
60
60
  @later.push(
61
61
  'when' => time.to_f,
@@ -74,23 +74,10 @@ module MicroQ
74
74
  def dequeue(limit = 30)
75
75
  return [] if limit == 0
76
76
 
77
- idx = 0
77
+ opts = { :i => 0, :limit => limit}
78
78
  [].tap do |items|
79
- entries.each do |entry|
80
- items << entry unless (idx += 1) > limit
81
- end if entries.any?
82
-
83
- items.each {|i| entries.delete(i) }
84
-
85
- available = later.select {|entry| entry['when'] < Time.now.to_f }
86
-
87
- if available.any?
88
- available.each do |entry|
89
- items << entry['worker'] unless (idx += 1) > limit
90
- end
91
-
92
- available.each {|a| later.delete(a) }
93
- end
79
+ dequeue_entries!(items, opts)
80
+ dequeue_later!(items, opts)
94
81
  end
95
82
  end
96
83
 
@@ -107,6 +94,26 @@ module MicroQ
107
94
 
108
95
  private
109
96
 
97
+ def dequeue_entries!(items, options)
98
+ entries.each do |entry|
99
+ items << entry unless (options[:i] += 1) > options[:limit]
100
+ end if entries.any?
101
+
102
+ items.each {|i| entries.delete(i) }
103
+ end
104
+
105
+ def dequeue_later!(items, options)
106
+ available = later.select {|entry| entry['when'] < Time.now.to_f }
107
+
108
+ if available.any?
109
+ available.each do |entry|
110
+ items << entry['worker'] unless (options[:i] += 1) > options[:limit]
111
+ end
112
+
113
+ available.each {|a| later.delete(a) }
114
+ end
115
+ end
116
+
110
117
  ##
111
118
  # Parse the entries back into the queue from the filesystem
112
119
  #
@@ -41,9 +41,9 @@ module MicroQ
41
41
 
42
42
  def sync_push(item, options = {})
43
43
  item, options = MicroQ::Util.stringify(item, options)
44
- klass = item['class'] = item['class'].to_s
44
+ item['class'] = item['class'].to_s
45
45
 
46
- MicroQ.middleware.client.call(klass, item, options) do
46
+ MicroQ.middleware.client.call(item, options) do
47
47
  json = JSON.dump(item)
48
48
 
49
49
  MicroQ.redis do |r|
@@ -0,0 +1,15 @@
1
+ module MicroQ
2
+ module Statistics
3
+ class Base
4
+ attr_reader :increment
5
+
6
+ def self.stats
7
+ yield instance
8
+ end
9
+
10
+ def self.instance
11
+ @instance ||= new
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ module MicroQ
2
+ module Statistics
3
+ class Default < Base
4
+ def initialize
5
+ @increment = Hash.new { 0 }
6
+ @increment_mutex = Mutex.new
7
+ end
8
+
9
+ def incr(*keys)
10
+ @increment_mutex.synchronize do
11
+ keys.flatten.each do |key|
12
+ @increment[key.to_s] += 1
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ module MicroQ
2
+ module Statistics
3
+ class Redis < Base
4
+ INCR = 'statistics:increment'
5
+
6
+ def increment
7
+ MicroQ.redis do |r|
8
+ r.hgetall(INCR)
9
+ end.each_with_object({}) do |(k, v), hash|
10
+ hash[k] = v.to_i
11
+ end
12
+ end
13
+
14
+ def incr(*keys)
15
+ MicroQ.redis do |r| r.pipelined {
16
+ keys.flatten.each do |key|
17
+ r.hincrby(INCR, key, 1)
18
+ end
19
+ } end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,6 +1,6 @@
1
1
  module MicroQ
2
2
  MAJOR = 0
3
- MINOR = 7
3
+ MINOR = 8
4
4
  POINT = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, POINT].join('.')
@@ -12,28 +12,38 @@ module MicroQ
12
12
  # A minimal message: (Calls the perform method with zero arguments)
13
13
  # { :class => 'MyWorker' }
14
14
  #
15
- # A more complex message: (Calls the update_data with a single paramater as a list of ids)
15
+ # A more complex message: (Calls the update_data with a single parameter as a list of ids)
16
16
  # { :class => 'MyUpdater', 'method' => 'update_data', :args => [[2, 6,74, 198]]}
17
17
  #
18
18
  class Standard
19
19
  include Celluloid
20
20
 
21
- def perform(message)
22
- klass = MicroQ::Util.constantize(message['class'].to_s)
21
+ def initialize(manager)
22
+ @manager = manager
23
+ end
23
24
 
24
- loader = message['loader'] ||= { 'method' => 'new' }
25
- klass = klass.send(loader['method'], *loader['args']) if loader['method']
25
+ def perform(message)
26
+ klass = fetch_klass(message)
26
27
 
27
28
  method = message['method'] || 'perform'
28
29
  args = message['args']
29
30
 
30
- value = nil
31
-
32
- MicroQ.middleware.server.call(klass, message) do
33
- value = klass.send(method, *args)
31
+ defer do
32
+ MicroQ.middleware.server.call(klass, message) do
33
+ klass.send(method, *args)
34
+ end
34
35
  end
35
36
 
36
- value
37
+ @manager.work_done!(current_actor)
38
+ end
39
+
40
+ def fetch_klass(message)
41
+ klass = MicroQ::Util.constantize(message['class'].to_s)
42
+
43
+ loader = message['loader'] ||= { 'method' => 'new' }
44
+ klass = klass.send(loader['method'], *loader['args']) if loader['method']
45
+
46
+ klass
37
47
  end
38
48
  end
39
49
  end
data/lib/micro_q.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'timeout'
1
2
  require 'celluloid'
2
3
  require 'connection_pool'
3
4
  require 'redis'
@@ -19,6 +20,10 @@ module MicroQ
19
20
  config.middleware
20
21
  end
21
22
 
23
+ def self.stats(&block)
24
+ config.statistics.stats(&block)
25
+ end
26
+
22
27
  def self.start
23
28
  manager
24
29
  end
@@ -43,11 +48,28 @@ module MicroQ
43
48
  end
44
49
 
45
50
  require 'micro_q/middleware'
46
- require 'micro_q/wrappers'
47
- require 'micro_q/methods'
48
- require 'micro_q/dsl'
49
51
  require 'micro_q/proxies'
52
+ require 'micro_q/dsl'
50
53
  require 'micro_q/worker'
51
54
  require 'micro_q/queue'
52
55
 
53
56
  require 'micro_q/redis'
57
+
58
+ require 'micro_q/wrappers/action_mailer'
59
+
60
+ # add Class and Instance methods first then
61
+ # override with additional extensions
62
+
63
+ require 'micro_q/methods/class'
64
+ require 'micro_q/methods/instance'
65
+ require 'micro_q/methods/active_record'
66
+ require 'micro_q/methods/action_mailer'
67
+
68
+ require 'micro_q/statistics/base'
69
+ require 'micro_q/statistics/default'
70
+ require 'micro_q/statistics/redis'
71
+
72
+ # There is a better way coming soon 2/18/13
73
+ at_exit do
74
+ MicroQ::Manager::Default.shutdown!
75
+ end
data/micro_q.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^spec/})
18
18
  gem.require_paths = %w(lib)
19
19
 
20
- gem.add_dependency "celluloid"
20
+ gem.add_dependency "celluloid", '~> 0.12.0'
21
21
  gem.add_dependency "redis"
22
22
  gem.add_dependency "connection_pool"
23
23
  gem.add_development_dependency "rake"
@@ -1,4 +1,4 @@
1
- shared_examples_for "a_worker" do |method|
1
+ shared_examples_for 'a_worker' do |method|
2
2
  describe "additions (#{method})" do
3
3
  it 'should add an async proxy' do
4
4
  subject.respond_to?(:async).should == true
@@ -24,14 +24,14 @@ shared_examples_for 'Queue#sync_push' do
24
24
 
25
25
  describe 'client middleware' do
26
26
  it 'should process the middleware chain' do
27
- MicroQ.middleware.client.should_receive(:call) do |w, payload|
28
- w.should == 'MyWorker'
29
-
27
+ MicroQ.middleware.client.should_receive(:call) do |payload, opts|
30
28
  payload['class'].should == 'MyWorker'
31
29
  payload['args'].should == [4]
30
+
31
+ opts['when'].should == 'now'
32
32
  end
33
33
 
34
- subject.sync_push(item)
34
+ subject.sync_push(item, 'when' => 'now')
35
35
  end
36
36
  end
37
37
  end
@@ -63,5 +63,9 @@ describe MicroQ::Config do
63
63
  it 'should have the standard worker' do
64
64
  subject.worker.should == MicroQ::Worker::Standard
65
65
  end
66
+
67
+ it 'should have the default statistics' do
68
+ subject.statistics.should == MicroQ::Statistics::Default
69
+ end
66
70
  end
67
71
  end