micro_q 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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: