micro_q 0.6.5 → 0.7.0

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  MicroQ is a per-process asynchronous background queue.
4
4
 
5
- It's simple startup and intuitive interface makes it the best choice for new and lagacy apps.
5
+ It's simple startup and intuitive interface makes it the best choice for new and legacy apps.
6
6
 
7
7
  ## Installation
8
8
 
@@ -19,8 +19,10 @@ Or install it:
19
19
  ## Usage
20
20
 
21
21
  ```ruby
22
- # A typical worker
22
+ ## A typical worker class
23
23
  class MyWorker
24
+ worker :update # sets up the dsl and adds additional async_ methods
25
+
24
26
  def perform
25
27
  # do some performing here
26
28
  end
@@ -31,24 +33,30 @@ class MyWorker
31
33
  end
32
34
  ```
33
35
 
34
- ###Simple (default)
36
+ ###Simple
35
37
 
36
38
  ```ruby
37
- # Using the async proxy API
38
- MyWorker.async.perform
39
-
40
- MyWorker.async.update(:user_id => user.id)
41
-
42
- # Through the raw push API
43
- MicroQ.push(:class => 'MyWorker') # Defaults to the perform method
44
-
45
- # With a custom method
46
- MicroQ.push(:class => 'MyWorker', :method => 'update', :args => [{:user_id => user.id}])
39
+ MyWorker.async_perform
40
+ MyWorker.async_update(:user_id => user.id)
47
41
  ```
48
42
 
49
43
  ###Advanced
50
44
 
51
- ###Custom Loaders
45
+ Safely using an ActiveRecord instance via the Custom Loader API
46
+ ```ruby
47
+ # app/models/user.rb
48
+ class User < Activerecord::Base
49
+ def update_social_data
50
+ # Send HTTP requests to Facebook, Twitter, etc
51
+ end
52
+ end
53
+
54
+ # app/controllers/users_controller.rb
55
+ def update
56
+ user = account.users.find(params[:id])
57
+ user.async.update_social_data
58
+ end
59
+ ```
52
60
 
53
61
  ## Contributing
54
62
 
@@ -0,0 +1,28 @@
1
+ module MicroQ
2
+ module DSL
3
+ def worker(*opts)
4
+ self.class_eval do
5
+ def self.microq_options
6
+ @microq_options ||= { :methods => [:perform] }
7
+ end
8
+ end
9
+
10
+ if Hash === opts.last
11
+ self.microq_options.merge!(opts.pop)
12
+ end
13
+
14
+ async_methods = self.microq_options[:methods] |= opts.flatten
15
+
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)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ Object.send(:extend, MicroQ::DSL)
@@ -1,17 +1,17 @@
1
1
  module MicroQ
2
2
  module Methods
3
3
  ##
4
- # Methods that are added to ActionMailer instances
4
+ # Methods that are added to the ActionMailer class
5
5
  #
6
6
  # When mailing asynchronously, the deliver method needs to be
7
7
  # called which means a custom wrapper.
8
8
  #
9
9
  module ActionMailer
10
- def async
11
- MicroQ::Proxy::ActionMailer.new(
10
+ def async(options = {})
11
+ MicroQ::Proxy::ActionMailer.new(options.merge(
12
12
  :class => MicroQ::Wrapper::ActionMailer,
13
13
  :base => self
14
- )
14
+ ))
15
15
  end
16
16
  end
17
17
  end
@@ -14,8 +14,8 @@ module MicroQ
14
14
  # store the id as the argument for find.
15
15
  #
16
16
  module ActiveRecord
17
- def async
18
- options = {
17
+ def async(options = {})
18
+ defaults = {
19
19
  :class => self.class,
20
20
  :loader => {
21
21
  :method => 'find',
@@ -23,7 +23,9 @@ module MicroQ
23
23
  }
24
24
  }
25
25
 
26
- MicroQ::Proxy::Instance.new(options)
26
+ MicroQ::Proxy::Instance.new(
27
+ options.merge(defaults)
28
+ )
27
29
  end
28
30
  end
29
31
  end
@@ -9,8 +9,10 @@ module MicroQ
9
9
  # message invocation
10
10
  #
11
11
  module Class
12
- def async
13
- MicroQ::Proxy::Class.new(:class => self, :loader => {})
12
+ def async(options = {})
13
+ MicroQ::Proxy::Class.new(
14
+ options.merge(:class => self, :loader => {})
15
+ )
14
16
  end
15
17
  end
16
18
  end
@@ -11,8 +11,10 @@ module MicroQ
11
11
  # what the default worker does.
12
12
  #
13
13
  module Instance
14
- def async
15
- MicroQ::Proxy::Instance.new(:class => self.class)
14
+ def async(options = {})
15
+ MicroQ::Proxy::Instance.new(
16
+ options.merge(:class => self.class)
17
+ )
16
18
  end
17
19
  end
18
20
  end
@@ -1,7 +1,7 @@
1
1
  module MicroQ
2
2
  MAJOR = 0
3
- MINOR = 6
4
- POINT = 5
3
+ MINOR = 7
4
+ POINT = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, POINT].join('.')
7
7
  end
data/lib/micro_q.rb CHANGED
@@ -45,6 +45,7 @@ end
45
45
  require 'micro_q/middleware'
46
46
  require 'micro_q/wrappers'
47
47
  require 'micro_q/methods'
48
+ require 'micro_q/dsl'
48
49
  require 'micro_q/proxies'
49
50
  require 'micro_q/worker'
50
51
  require 'micro_q/queue'
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ describe MicroQ::DSL do
4
+ describe '.worker' do
5
+ class OtherWorker
6
+ worker :update
7
+ end
8
+
9
+ it 'should add the method' do
10
+ Object.should be_respond_to(:worker)
11
+ end
12
+
13
+ it 'should include the dsl module' do
14
+ Object.should be_is_a(MicroQ::DSL)
15
+ end
16
+
17
+ it 'should add the async_perform method' do
18
+ OtherWorker.should be_respond_to(:async_perform)
19
+ end
20
+
21
+ it 'should add async_ prefixed method when given them' do
22
+ OtherWorker.should be_respond_to(:async_update)
23
+ end
24
+
25
+ describe 'when calling the async_ method' do
26
+ let(:method) { ->(*args) { OtherWorker.async_perform(*args) } }
27
+
28
+ before do
29
+ @proxy = mock(MicroQ::Proxy::Instance, :perform => nil)
30
+ MicroQ::Proxy::Instance.stub(:new).and_return(@proxy)
31
+ end
32
+
33
+ it 'should create a proxy' do
34
+ MicroQ::Proxy::Instance.should_receive(:new).and_return(@proxy)
35
+
36
+ method.call
37
+ end
38
+
39
+ it 'should have the class' do
40
+ MicroQ::Proxy::Instance.should_receive(:new).with(hash_including(:class => OtherWorker)).and_return(@proxy)
41
+
42
+ method.call
43
+ end
44
+
45
+ it 'should call the perform method' do
46
+ @proxy.should_receive(:perform)
47
+
48
+ method.call
49
+ end
50
+
51
+ it 'should have given arguments' do
52
+ @proxy.should_receive(:perform).with('hey yay', 4)
53
+
54
+ method.call('hey yay', 4)
55
+ end
56
+ end
57
+
58
+ describe 'when calling the async_something method' do
59
+ let(:method) { ->(*args) { OtherWorker.async_update(*args) } }
60
+
61
+ before do
62
+ @proxy = mock(MicroQ::Proxy::Instance, :update => nil)
63
+ MicroQ::Proxy::Instance.stub(:new).and_return(@proxy)
64
+ end
65
+
66
+ it 'should have the class' do
67
+ MicroQ::Proxy::Instance.should_receive(:new).with(hash_including(:class => OtherWorker)).and_return(@proxy)
68
+
69
+ method.call
70
+ end
71
+
72
+ it 'should call the update method' do
73
+ @proxy.should_receive(:update)
74
+
75
+ method.call
76
+ end
77
+
78
+ it 'should have given arguments' do
79
+ @proxy.should_receive(:update).with('hey yay', 12)
80
+
81
+ method.call('hey yay', 12)
82
+ end
83
+ end
84
+
85
+ describe 'when given custom options' do
86
+ class OneWorker; worker :one_method end
87
+ class OptionWorker
88
+ worker :method_name, :queue => 'my-queue', :option => 'value'
89
+ worker :other_method, :queue => 'my-queue', :option => 'value'
90
+ end
91
+
92
+ it 'should have the async_ methods' do
93
+ OptionWorker.should be_respond_to(:async_method_name)
94
+ OptionWorker.should be_respond_to(:async_other_method)
95
+ end
96
+
97
+ it 'should store the options' do
98
+ OptionWorker.microq_options[:queue].should == 'my-queue'
99
+ OptionWorker.microq_options[:option].should == 'value'
100
+ end
101
+
102
+ it 'should merge the given methods' do
103
+ OptionWorker.microq_options[:methods].should == [:perform, :method_name, :other_method]
104
+ end
105
+
106
+ it 'should not bleed methods' do
107
+ OneWorker.microq_options[:methods].should == [:perform, :one_method]
108
+ end
109
+ end
110
+ end
111
+ end
@@ -24,5 +24,15 @@ describe MicroQ::Methods::ActionMailer do
24
24
 
25
25
  async.call
26
26
  end
27
+
28
+ describe 'when given when to run the job' do
29
+ let(:method) { -> { MyMailer.async(:at => "sometime") } }
30
+
31
+ it 'should pass the option' do
32
+ MicroQ::Proxy::ActionMailer.should_receive(:new).with(hash_including(:at => "sometime"))
33
+
34
+ method.call
35
+ end
36
+ end
27
37
  end
28
38
  end
@@ -54,8 +54,18 @@ describe MicroQ::Methods::ActiveRecord, :active_record => true do
54
54
  it_behaves_like 'a_worker', 'process'
55
55
 
56
56
  describe 'when calling to async.method proxy' do
57
- let(:method) { lambda {|*args| subject.async.process(*args) } }
57
+ let(:method) { ->(*args) { subject.async.process(*args) } }
58
58
 
59
59
  it_behaves_like 'an async AR instance'
60
+
61
+ describe 'when given when to run the job' do
62
+ let(:method) { -> { subject.async(:at => "sometime") } }
63
+
64
+ it 'should pass the option' do
65
+ MicroQ::Proxy::Instance.should_receive(:new).with(hash_including(:at => "sometime"))
66
+
67
+ method.call
68
+ end
69
+ end
60
70
  end
61
71
  end
@@ -48,8 +48,18 @@ describe MicroQ::Methods::Class do
48
48
  it_behaves_like 'a_worker', 'seed'
49
49
 
50
50
  describe 'when calling to async.method proxy' do
51
- let(:method) { lambda {|*args| subject.async.seed(*args) } }
51
+ let(:method) { ->(*args) { subject.async.seed(*args) } }
52
52
 
53
53
  it_behaves_like 'an async class'
54
+
55
+ describe 'when given when to run the job' do
56
+ let(:method) { -> { subject.async(:at => "sometime") } }
57
+
58
+ it 'should pass the option' do
59
+ MicroQ::Proxy::Class.should_receive(:new).with(hash_including(:at => "sometime"))
60
+
61
+ method.call
62
+ end
63
+ end
54
64
  end
55
65
  end
@@ -42,8 +42,18 @@ describe MicroQ::Methods::Instance do
42
42
  it_behaves_like 'a_worker', 'process'
43
43
 
44
44
  describe 'when calling to async.method proxy' do
45
- let(:method) { lambda {|*args| subject.async.process(*args) } }
45
+ let(:method) { ->(*args) { subject.async.process(*args) } }
46
46
 
47
47
  it_behaves_like 'an async instance'
48
+
49
+ describe 'when given when to run the job' do
50
+ let(:method) { -> { subject.async(:at => "sometime") } }
51
+
52
+ it 'should pass the option' do
53
+ MicroQ::Proxy::Instance.should_receive(:new).with(hash_including(:at => "sometime"))
54
+
55
+ method.call
56
+ end
57
+ end
48
58
  end
49
59
  end
@@ -17,7 +17,7 @@ describe MicroQ::Middleware::Server::Retry, :middleware => true do
17
17
 
18
18
  describe 'when the block raises an Exception' do
19
19
  let(:exception) { Exception.new }
20
- let(:block) { lambda { raise exception } }
20
+ let(:block) { -> { raise exception } }
21
21
 
22
22
  describe 'when retry is disabled' do
23
23
  before do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe MicroQ::Proxy::ActionMailer do
4
- let(:method) { lambda {|*args| subject.mail_me(*args) } }
4
+ let(:method) { ->(*args) { subject.mail_me(*args) } }
5
5
  let(:options) { { :class => MicroQ::Wrapper::ActionMailer, :base => MyMailer } }
6
6
 
7
7
  class MyMailer < ActionMailer::Base
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: micro_q
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-15 00:00:00.000000000 Z
12
+ date: 2013-02-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: celluloid
@@ -202,6 +202,7 @@ files:
202
202
  - Rakefile
203
203
  - lib/micro_q.rb
204
204
  - lib/micro_q/config.rb
205
+ - lib/micro_q/dsl.rb
205
206
  - lib/micro_q/manager.rb
206
207
  - lib/micro_q/manager/default.rb
207
208
  - lib/micro_q/methods.rb
@@ -232,6 +233,7 @@ files:
232
233
  - spec/helpers/methods_examples.rb
233
234
  - spec/helpers/queues_examples.rb
234
235
  - spec/lib/config_spec.rb
236
+ - spec/lib/dsl_spec.rb
235
237
  - spec/lib/manager/default_spec.rb
236
238
  - spec/lib/methods/action_mailer_spec.rb
237
239
  - spec/lib/methods/active_record_spec.rb
@@ -263,21 +265,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
263
265
  - - ! '>='
264
266
  - !ruby/object:Gem::Version
265
267
  version: '0'
266
- segments:
267
- - 0
268
- hash: -938614876978684754
269
268
  required_rubygems_version: !ruby/object:Gem::Requirement
270
269
  none: false
271
270
  requirements:
272
271
  - - ! '>='
273
272
  - !ruby/object:Gem::Version
274
273
  version: '0'
275
- segments:
276
- - 0
277
- hash: -938614876978684754
278
274
  requirements: []
279
275
  rubyforge_project:
280
- rubygems_version: 1.8.24
276
+ rubygems_version: 1.8.25
281
277
  signing_key:
282
278
  specification_version: 3
283
279
  summary: ''
@@ -285,6 +281,7 @@ test_files:
285
281
  - spec/helpers/methods_examples.rb
286
282
  - spec/helpers/queues_examples.rb
287
283
  - spec/lib/config_spec.rb
284
+ - spec/lib/dsl_spec.rb
288
285
  - spec/lib/manager/default_spec.rb
289
286
  - spec/lib/methods/action_mailer_spec.rb
290
287
  - spec/lib/methods/active_record_spec.rb
@@ -304,3 +301,4 @@ test_files:
304
301
  - spec/lib/worker/standard_spec.rb
305
302
  - spec/lib/wrappers/action_mailer_spec.rb
306
303
  - spec/spec_helper.rb
304
+ has_rdoc: