quebert 1.12.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ script: bundle exec rspec
2
+ language: ruby
3
+ rvm:
4
+ - 2.0.0
5
+ - 1.9.3
6
+ - 1.8.7
data/Gemfile CHANGED
@@ -10,7 +10,7 @@ end
10
10
  group :test do
11
11
  # gem 'ruby-debug', :platform => :ruby_18
12
12
  # gem 'ruby-debug19', :platform => :ruby_19
13
- gem 'activerecord', '2.3.5'
13
+ gem 'activerecord', '~> 2.3.0'
14
14
  gem 'sqlite3-ruby'
15
15
  gem 'guard-rspec'
16
16
  gem 'rb-fsevent'
data/LICENSE.md ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Brad Gessler
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -1,16 +1,18 @@
1
- = Quebert
1
+ # Quebert
2
+
3
+ [![Build Status](https://travis-ci.org/polleverywhere/quebert.png?branch=master)](https://travis-ci.org/polleverywhere/quebert)
2
4
 
3
5
  async_observer is great, but is dated and doesn't really support running jobs outside of the async_send idiom. Quebert is an attempt to mix how jobs are run in other popular worker queue frameworks, like resque and dj, with async_observer so that you can have it both ways.
4
6
 
5
- = Why Quebert (or how is it different from DJ and Resque)?
7
+ # Why Quebert (or how is it different from DJ and Resque)?
6
8
 
7
9
  Because it has really low latency. Other Ruby queuing frameworks, like DJ or Resque, have to poll their queue servers periodicly. You could think of it as a "pull" queue. Quebert is a "push" queue. It maintains a persistent connection with beanstalkd and when is enqueud, its instantly pushed to the workers and executed.
8
10
 
9
- = Who uses it?
11
+ # Who uses it?
10
12
 
11
13
  Quebert is a serious project. Its used in a production environment at Poll Everywhere to handle everything from SMS message processing to account downgrades.
12
14
 
13
- = Features
15
+ # Features
14
16
 
15
17
  * Multiple back-ends (InProcess, Sync, and Beanstalk)
16
18
  * Rails/ActiveRecord integration similar to async_observer
@@ -22,11 +24,11 @@ Some features that are currently missing that I will soon add include:
22
24
  * Rails plugin support (The AR integrations have to be done manually today)
23
25
  * Auto-detecting serializers. Enhanced ClassRegistry to more efficiently look up serializers for objects.
24
26
 
25
- = How to use
27
+ # How to use
26
28
 
27
29
  There are two ways to enqueue jobs with Quebert: through the Job itself, provided you set a default back-end for the job, or put it on the backend.
28
30
 
29
- == Jobs
31
+ ## Jobs
30
32
 
31
33
  Quebert includes a Job class so you can implement how you want certain types of Jobs performed.
32
34
 
@@ -51,14 +53,14 @@ Then perform the jobs!
51
53
  Quebert.backend.reserve.perform # => 6
52
54
  Quebert.backend.reserve.perform # => 15
53
55
 
54
- == Async Sender
56
+ ## Async Sender
55
57
 
56
58
  Take any ol' class and include the Quebert::AsyncSender.
57
59
 
58
60
  Quebert.backend = Quebert::Backend::InProcess.new
59
61
 
60
62
  class Greeter
61
- include Quebert::AsyncSender
63
+ include Quebert::AsyncSender::Class
62
64
 
63
65
  def initialize(name)
64
66
  @name = name
@@ -82,9 +84,9 @@ Remember the send method in ruby?
82
84
  # ... time passes, you wait as greeter snores obnoxiously ...
83
85
  # => "Oh! Hi Brad! Good morning."
84
86
 
85
- What if the method takes a long time to run and you want to queue it? async_send it!
87
+ What if the method takes a long time to run and you want to queue it? async.send it!
86
88
 
87
- walmart_greeter.async_send(:sleep_and_greet, "morning")
89
+ walmart_greeter.async.sleep_and_greet("morning")
88
90
  # ... do some shopping and come back later when the dude wakes up
89
91
 
90
92
  Quebert figures out how to *serialize the class, throw it on a worker queue, re-instantiate it on the other side, and finish up the work.
@@ -94,29 +96,7 @@ Quebert figures out how to *serialize the class, throw it on a worker queue, re-
94
96
 
95
97
  Does it work on Class methods? Yeah, that was easier than making instance methods work:
96
98
 
97
- Quebert.async_send(:budweiser_greeting, "Corey")
99
+ Quebert.async.budweiser_greeting("Corey")
98
100
  Quebert.backend.reserve.perform # => "waazup Corey!"
99
101
 
100
102
  * Only basic data types are included for serialization. Serializers may be customized to include support for different types.
101
-
102
- = License
103
-
104
- Copyright (c) 2010 Brad Gessler
105
-
106
- Permission is hereby granted, free of charge, to any person obtaining a copy
107
- of this software and associated documentation files (the "Software"), to deal
108
- in the Software without restriction, including without limitation the rights
109
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
110
- copies of the Software, and to permit persons to whom the Software is
111
- furnished to do so, subject to the following conditions:
112
-
113
- The above copyright notice and this permission notice shall be included in
114
- all copies or substantial portions of the Software.
115
-
116
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
117
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
118
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
119
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
120
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
121
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
122
- THE SOFTWARE.
data/lib/quebert.rb CHANGED
@@ -32,6 +32,12 @@ module Quebert
32
32
  def logger
33
33
  config.logger
34
34
  end
35
+
36
+ # Deprecation notice for code within block.
37
+ def deprecate(message, &block)
38
+ logger.warn "Quebert Deprecation Notice: #{message}"
39
+ block.call
40
+ end
35
41
  end
36
42
 
37
43
  # Register built-in Quebert backends
@@ -4,5 +4,6 @@ module Quebert
4
4
  autoload :Instance, 'quebert/async_sender/instance'
5
5
  autoload :Class, 'quebert/async_sender/class'
6
6
  autoload :ActiveRecord, 'quebert/async_sender/active_record'
7
+ autoload :Promise, 'quebert/async_sender/promise'
7
8
  end
8
9
  end
@@ -1,6 +1,5 @@
1
1
  module Quebert
2
2
  module AsyncSender
3
-
4
3
  # I'm not sure if I want to do this or build serializers per type of object...
5
4
  module ActiveRecord
6
5
  class RecordJob < Job
@@ -10,17 +9,16 @@ module Quebert
10
9
  end
11
10
 
12
11
  def self.included(base)
13
- base.send(:include, InstanceMethods)
12
+ base.send(:include, AsyncSender::Promise::DSL)
14
13
  base.send(:include, AsyncSender::Object)
14
+ base.send(:include, InstanceMethods)
15
15
  end
16
-
16
+
17
17
  module InstanceMethods
18
- # The meat of dealing with ActiveRecord instances.
19
- def async_send(meth, *args)
20
- RecordJob.new(self, meth, *args).enqueue
18
+ def build_job(meth, *args)
19
+ RecordJob.new(self, meth, *args)
21
20
  end
22
21
  end
23
22
  end
24
-
25
23
  end
26
24
  end
@@ -3,16 +3,18 @@ module Quebert
3
3
  # Perform jobs on instances of classes
4
4
  module Instance
5
5
  class InstanceJob < Job
6
- def perform(klass, init_args, meth, *args)
7
- Support.constantize(klass).new(*init_args).send(meth, *args)
6
+ def perform(klass, initialize_args, meth, *args)
7
+ Support.constantize(klass).new(*initialize_args).send(meth, *args)
8
8
  end
9
9
  end
10
-
10
+
11
11
  def self.included(base)
12
12
  # Its not as simple as including initialize in a class, we
13
13
  # have to do some tricks to make it work so we can put the include
14
14
  # before the initialize method as opposed to after. Ah, and thanks PivotalLabs for this.
15
- base.extend ClassMethods
15
+ base.send(:include, AsyncSender::Promise::DSL)
16
+ base.send(:include, InstanceMethods)
17
+ base.send(:extend, ClassMethods)
16
18
  base.overwrite_initialize
17
19
  base.instance_eval do
18
20
  def method_added(name)
@@ -21,12 +23,24 @@ module Quebert
21
23
  end
22
24
  end
23
25
  end
24
-
25
- def initialize_with_async_sender(*args)
26
- initialize_without_async_sender(*(@_init_args = args))
26
+
27
+ module InstanceMethods
28
+ # Build a job that uses the @__initialize_args
29
+ def build_job(meth, *args)
30
+ InstanceJob.new(self.class.name, @__initialize_args, meth, *args)
31
+ end
32
+
33
+ # Remember the args used to initialize the class so that
34
+ # we can serialize them into a Job.
35
+ def initialize_with_async_sender(*args)
36
+ initialize_without_async_sender(*(@__initialize_args = args))
37
+ end
27
38
  end
28
39
 
29
40
  module ClassMethods
41
+ # Hack into the class initialize method so that we can grab
42
+ # the arguments used to create an instance of the class that
43
+ # we can serialize into a job.
30
44
  def overwrite_initialize
31
45
  class_eval do
32
46
  unless method_defined?(:initialize_with_async_sender)
@@ -42,10 +56,6 @@ module Quebert
42
56
  end
43
57
  end
44
58
  end
45
-
46
- def async_send(meth, *args)
47
- InstanceJob.new(self.class.name, @_init_args, meth, *args).enqueue
48
- end
49
59
  end
50
60
  end
51
61
  end
@@ -9,12 +9,13 @@ module Quebert
9
9
  end
10
10
 
11
11
  def self.included(base)
12
+ base.send(:extend, AsyncSender::Promise::DSL)
12
13
  base.send(:extend, ClassMethods)
13
14
  end
14
15
 
15
16
  module ClassMethods
16
- def async_send(meth, *args)
17
- ObjectJob.new(self.name, meth, *args).enqueue
17
+ def build_job(meth, *args)
18
+ ObjectJob.new(self.name, meth, *args)
18
19
  end
19
20
  end
20
21
  end
@@ -0,0 +1,54 @@
1
+ module Quebert
2
+ module AsyncSender
3
+ # Decorates AsyncSender classes with an #async() proxy. This seperates
4
+ # the concern of configuring job specific parameters, like :ttr, :delay, etc.
5
+ # from calling the method.
6
+ class Promise
7
+ attr_reader :target, :opts, :job
8
+
9
+ def initialize(target, opts={}, &block)
10
+ @target, @opts, @block = target, opts, block
11
+ self
12
+ end
13
+
14
+ # Proxies the method call from async to the target, then tries
15
+ # to build a job with the targets `build_job` function.
16
+ def method_missing(meth, *args)
17
+ if @target.respond_to? meth, true # The second `true` argument checks private methods.
18
+ # Create an instance of the job through the proxy and
19
+ # configure it with the options given to the proxy.
20
+ @block.call configure @target.build_job(meth, *args)
21
+ else
22
+ super
23
+ end
24
+ end
25
+
26
+ # Configures a job with the options provied to the Promise
27
+ # upon initialization.
28
+ def configure(job)
29
+ @opts.each do |attr, val|
30
+ job.send("#{attr}=", val)
31
+ end
32
+ job
33
+ end
34
+
35
+ # Methods/DSL that we mix into classes, objects, etc. so that we
36
+ # can easily enqueue jobs to these.
37
+ module DSL
38
+ def async(opts={})
39
+ Promise.new(self, opts) { |job| job.enqueue }
40
+ end
41
+
42
+ # Legacy way of enqueueing jobs.
43
+ def async_send(*args)
44
+ meth = args.shift
45
+ beanstalk = args.last.delete(:beanstalk) if args.last.is_a?(::Hash)
46
+
47
+ Quebert.deprecate "#async_send should be called via #{self.class.name}.async(#{beanstalk.inspect}).#{args.first}(#{args.map(&:inspect).join(', ')})" do
48
+ async(beanstalk || {}).send(meth, *args)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
data/lib/quebert/job.rb CHANGED
@@ -14,7 +14,10 @@ module Quebert
14
14
  HIGH = 0
15
15
  end
16
16
 
17
+ # Delay a job for 0 seconds on the jobqueue
17
18
  DEFAULT_JOB_DELAY = 0
19
+
20
+ # By default, the job should live for 10 seconds tops.
18
21
  DEFAULT_JOB_TTR = 10
19
22
 
20
23
  # A buffer time in seconds added to the Beanstalk TTR for Quebert to do its own job cleanup
@@ -22,10 +25,10 @@ module Quebert
22
25
  # little longer so that Quebert can bury the job or schedule a retry with the appropriate delay
23
26
  QUEBERT_TTR_BUFFER = 5
24
27
 
28
+ # Exceptions are used for signaling job status... ewww. Yank this out and
29
+ # replace with a more well thought out controller.
25
30
  NotImplemented = Class.new(StandardError)
26
-
27
31
  Action = Class.new(Exception)
28
-
29
32
  Bury = Class.new(Action)
30
33
  Delete = Class.new(Action)
31
34
  Release = Class.new(Action)
@@ -33,24 +36,11 @@ module Quebert
33
36
  Retry = Class.new(Action)
34
37
 
35
38
  def initialize(*args)
36
- opts = args.last.is_a?(::Hash) ? args.pop : nil
37
-
38
39
  @priority = Job::Priority::MEDIUM
39
- @delay = DEFAULT_JOB_DELAY
40
- @ttr = DEFAULT_JOB_TTR
41
-
42
- if opts
43
- beanstalk_opts = opts.delete(:beanstalk)
44
- args << opts unless opts.empty?
45
-
46
- if beanstalk_opts
47
- @priority = beanstalk_opts[:priority] if beanstalk_opts[:priority]
48
- @delay = beanstalk_opts[:delay] if beanstalk_opts[:delay]
49
- @ttr = beanstalk_opts[:ttr] if beanstalk_opts[:ttr]
50
- end
51
- end
52
-
53
- @args = args.dup.freeze
40
+ @delay = DEFAULT_JOB_DELAY
41
+ @ttr = DEFAULT_JOB_TTR
42
+ @args = args.dup.freeze
43
+ self
54
44
  end
55
45
 
56
46
  def perform(*args)
@@ -1,3 +1,3 @@
1
1
  module Quebert
2
- VERSION = "1.12.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -22,18 +22,50 @@ describe AsyncSender::Class do
22
22
  def self.hi(name)
23
23
  "hi #{name}!"
24
24
  end
25
+
26
+ private
27
+ def bye(desc)
28
+ "bye #{@name}, you look #{desc}"
29
+ end
30
+
31
+ def self.bye(name)
32
+ "bye #{name}!"
33
+ end
25
34
  end
26
35
 
27
- it "should async send class methods" do
28
- Greeter.async_send(:hi, 'Jeannette')
29
- @q.reserve.perform.should eql(Greeter.send(:hi, 'Jeannette'))
36
+ describe "#async_send" do
37
+ it "should async send class methods" do
38
+ Greeter.async_send(:hi, 'Jeannette')
39
+ @q.reserve.perform.should eql(Greeter.send(:hi, 'Jeannette'))
40
+ end
41
+
42
+ it "should async send instance methods" do
43
+ Greeter.new("brad").async_send(:hi, 'stunning')
44
+ @q.reserve.perform.should eql(Greeter.new("brad").hi('stunning'))
45
+ end
30
46
  end
31
-
32
- it "should async send instance methods" do
33
- Greeter.new("brad").async_send(:hi, 'stunning')
34
- @q.reserve.perform.should eql(Greeter.new("brad").hi('stunning'))
47
+
48
+ describe "#async() promise" do
49
+ it "should async send class methods" do
50
+ Greeter.async.hi('Jeannette')
51
+ @q.reserve.perform.should eql(Greeter.send(:hi, 'Jeannette'))
52
+ end
53
+
54
+ it "should async send instance methods" do
55
+ Greeter.new("brad").async.hi('stunning')
56
+ @q.reserve.perform.should eql(Greeter.new("brad").hi('stunning'))
57
+ end
58
+
59
+ it "should async send private instance methods" do
60
+ Greeter.new("brad").async.send(:bye, 'stunning')
61
+ @q.reserve.perform.should eql(Greeter.new("brad").send(:bye, 'stunning'))
62
+ end
63
+
64
+ it "should async send private class methods" do
65
+ Greeter.async.send(:bye, 'Jeannette')
66
+ @q.reserve.perform.should eql(Greeter.send(:bye, 'Jeannette'))
67
+ end
35
68
  end
36
-
37
69
  end
38
70
 
39
71
  describe AsyncSender::ActiveRecord do
@@ -62,27 +94,27 @@ describe AsyncSender::ActiveRecord do
62
94
  end
63
95
 
64
96
  context "unpersisted" do
65
- it "should async_send instance method" do
97
+ it "should async instance method" do
66
98
  user = User.new do |u|
67
99
  u.email = 'barf@jones.com'
68
100
  u.first_name = "Barf"
69
101
  u.send(:write_attribute, :last_name, "Jones")
70
102
  end
71
- user.async_send(:name)
103
+ user.async.name
72
104
  @q.reserve.perform.should eql("Barf Jones")
73
105
  end
74
106
  end
75
107
 
76
- it "should async_send class method" do
108
+ it "should async class method" do
77
109
  email = "brad@bradgessler.com"
78
- User.async_send(:emailizer, email)
110
+ User.async.emailizer(email)
79
111
  @q.reserve.perform.should eql(email)
80
112
  end
81
113
 
82
114
  it "should async_send and successfully serialize param object" do
83
115
  user = User.new(:first_name => 'Brad')
84
116
  user2 = User.new(:first_name => 'Steel')
85
- user.async_send(:email, user2)
117
+ user.async.email(user2)
86
118
  @q.reserve.perform.first_name.should eql('Steel')
87
119
  end
88
120
  end
data/spec/job_spec.rb CHANGED
@@ -83,21 +83,42 @@ describe Quebert::Job do
83
83
  @q.drain!
84
84
  end
85
85
 
86
- it "should enqueue and honor beanstalk options" do
87
- user = User.new(:first_name => "Steel")
88
- user.async_send(:email, "somebody", nil, nil, :beanstalk => {:priority => 1, :delay => 2, :ttr => 300})
89
- job = @q.reserve
90
- job.beanstalk_job.pri.should eql(1)
91
- job.beanstalk_job.delay.should eql(2)
92
- job.beanstalk_job.ttr.should eql(300 + Job::QUEBERT_TTR_BUFFER)
86
+ describe "async promise DSL" do
87
+ it "should enqueue and honor beanstalk options" do
88
+ user = User.new(:first_name => "Steel")
89
+ user.async(:priority => 1, :delay => 2, :ttr => 300).email("somebody", nil, nil)
90
+ job = @q.reserve
91
+ job.beanstalk_job.pri.should eql(1)
92
+ job.beanstalk_job.delay.should eql(2)
93
+ job.beanstalk_job.ttr.should eql(300 + Job::QUEBERT_TTR_BUFFER)
94
+ end
95
+
96
+ it "should enqueue and honor beanstalk options" do
97
+ User.async(:priority => 1, :delay => 2, :ttr => 300).emailizer("somebody", nil, nil)
98
+ job = @q.reserve
99
+ job.beanstalk_job.pri.should eql(1)
100
+ job.beanstalk_job.delay.should eql(2)
101
+ job.beanstalk_job.ttr.should eql(300 + Job::QUEBERT_TTR_BUFFER)
102
+ end
93
103
  end
94
104
 
95
- it "should enqueue and honor beanstalk options" do
96
- User.async_send(:emailizer, "somebody", nil, nil, :beanstalk => {:priority => 1, :delay => 2, :ttr => 300})
97
- job = @q.reserve
98
- job.beanstalk_job.pri.should eql(1)
99
- job.beanstalk_job.delay.should eql(2)
100
- job.beanstalk_job.ttr.should eql(300 + Job::QUEBERT_TTR_BUFFER)
105
+ describe "legacy async_send" do
106
+ it "should enqueue and honor beanstalk options" do
107
+ user = User.new(:first_name => "Steel")
108
+ user.async_send(:email, "somebody", nil, nil, :beanstalk => {:priority => 1, :delay => 2, :ttr => 300})
109
+ job = @q.reserve
110
+ job.beanstalk_job.pri.should eql(1)
111
+ job.beanstalk_job.delay.should eql(2)
112
+ job.beanstalk_job.ttr.should eql(300 + Job::QUEBERT_TTR_BUFFER)
113
+ end
114
+
115
+ it "should enqueue and honor beanstalk options" do
116
+ User.async_send(:emailizer, "somebody", nil, nil, :beanstalk => {:priority => 1, :delay => 2, :ttr => 300})
117
+ job = @q.reserve
118
+ job.beanstalk_job.pri.should eql(1)
119
+ job.beanstalk_job.delay.should eql(2)
120
+ job.beanstalk_job.ttr.should eql(300 + Job::QUEBERT_TTR_BUFFER)
121
+ end
101
122
  end
102
123
  end
103
124
  end
@@ -2,66 +2,92 @@ require 'spec_helper'
2
2
 
3
3
  describe Serializer::ActiveRecord do
4
4
  context "persisted" do
5
- before(:all) do
6
- @user = User.create!(:first_name => 'Tom', :last_name => 'Jones')
7
- end
8
-
5
+ let(:user) { User.create!(:first_name => 'Tom', :last_name => 'Jones') }
6
+
9
7
  it "should serialize" do
10
- h = Serializer::ActiveRecord.serialize(@user)
8
+ h = Serializer::ActiveRecord.serialize(user)
11
9
  h['model'].should eql('User')
12
10
  h['attributes']['first_name'].should eql('Tom')
13
- h['attributes']['id'].should eql(@user.id)
11
+ h['attributes']['id'].should eql(user.id)
14
12
  end
15
13
 
16
14
  it "should deserialize" do
17
- u = Serializer::ActiveRecord.deserialize(Serializer::ActiveRecord.serialize(@user))
15
+ u = Serializer::ActiveRecord.deserialize(Serializer::ActiveRecord.serialize(user))
18
16
  u.first_name.should eql('Tom')
19
- u.id.should eql(@user.id)
17
+ u.id.should eql(user.id)
20
18
  end
21
19
  end
22
20
 
23
21
  context "unpersisted" do
24
- before(:all) do
25
- @user = User.new(:first_name => 'brad')
26
- end
27
-
22
+ let(:user) { User.new(:first_name => 'brad') }
23
+
28
24
  it "should serialize" do
29
- h = Serializer::ActiveRecord.serialize(@user)
25
+ h = Serializer::ActiveRecord.serialize(user)
30
26
  h['model'].should eql('User')
31
27
  h['attributes']['first_name'].should eql('brad')
32
28
  h['attributes']['id'].should be_nil
33
29
  end
34
30
 
35
31
  it "should deserialize" do
36
- u = Serializer::ActiveRecord.deserialize(Serializer::ActiveRecord.serialize(@user))
32
+ u = Serializer::ActiveRecord.deserialize(Serializer::ActiveRecord.serialize(user))
37
33
  u.first_name.should eql('brad')
38
34
  end
39
35
  end
40
36
  end
41
37
 
42
38
  describe Serializer::Job do
43
- before(:all) do
44
- @args = [100, User.new(:first_name => 'Brad'), {:beanstalk => {:priority => 1, :delay => 2, :ttr => 300}}]
45
- @job = Job.new(*@args)
39
+ let(:user) { User.new(:first_name => 'Brad') }
40
+ let(:args) { [100, user] }
41
+ let(:job) do
42
+ job = Job.new(*args)
43
+ job.priority = 1
44
+ job.delay = 2
45
+ job.ttr = 300
46
+ job
46
47
  end
47
-
48
- it "should serialize job" do
49
- h = Serializer::Job.serialize(@job)
50
- h['job'].should eql('Quebert::Job')
51
- h['args'][0]['payload'].should eql(100)
52
- h['args'][1]['payload'].should eql(Serializer::ActiveRecord.serialize(@args[1]))
53
- h['args'][1]['serializer'].should eql('Quebert::Serializer::ActiveRecord')
54
- h['priority'].should eql(1)
55
- h['delay'].should eql(2)
56
- h['ttr'].should eql(300)
48
+ let(:serialized) { Serializer::Job.serialize(job) }
49
+ let(:deserialized) { Serializer::Job.deserialize(serialized) }
50
+
51
+ describe "#serialize" do
52
+ it "shold have job" do
53
+ serialized['job'].should eql('Quebert::Job')
54
+ end
55
+
56
+ it "should have args" do
57
+ serialized['args'][0]['payload'].should eql(100)
58
+ serialized['args'][1]['payload'].should eql(Serializer::ActiveRecord.serialize(args[1]))
59
+ serialized['args'][1]['serializer'].should eql('Quebert::Serializer::ActiveRecord')
60
+ end
61
+
62
+ it "should have priority" do
63
+ serialized['priority'].should eql(1)
64
+ end
65
+
66
+ it "should have delay" do
67
+ serialized['delay'].should eql(2)
68
+ end
69
+
70
+ it "should have ttr" do
71
+ serialized['ttr'].should eql(300)
72
+ end
57
73
  end
58
-
59
- it "should deserialize job" do
60
- job = Serializer::Job.deserialize(Serializer::Job.serialize(@job))
61
- job.args[0].should eql(100)
62
- job.args[1].first_name.should eql('Brad')
63
- job.delay.should eql(2)
64
- job.priority.should eql(1)
65
- job.ttr.should eql(300)
74
+
75
+ describe "#deserialize" do
76
+ it "should have args" do
77
+ deserialized.args[0].should eql(100)
78
+ deserialized.args[1].first_name.should eql('Brad')
79
+ end
80
+
81
+ it "should have delay" do
82
+ deserialized.delay.should eql(2)
83
+ end
84
+
85
+ it "should have priority" do
86
+ deserialized.priority.should eql(1)
87
+ end
88
+
89
+ it "should have ttr" do
90
+ deserialized.ttr.should eql(300)
91
+ end
66
92
  end
67
93
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quebert
3
3
  version: !ruby/object:Gem::Version
4
- hash: 39
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
- - 1
8
- - 12
7
+ - 2
9
8
  - 0
10
- version: 1.12.0
9
+ - 0
10
+ version: 2.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brad Gessler
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2013-03-20 00:00:00 Z
20
+ date: 2013-04-27 00:00:00 Z
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
23
  name: json
@@ -77,10 +77,11 @@ files:
77
77
  - .gitignore
78
78
  - .rbenv-version
79
79
  - .rspec
80
+ - .travis.yml
80
81
  - Gemfile
81
82
  - Guardfile
82
- - LICENSE
83
- - README.rdoc
83
+ - LICENSE.md
84
+ - README.md
84
85
  - Rakefile
85
86
  - bin/quebert
86
87
  - lib/quebert.rb
@@ -89,6 +90,7 @@ files:
89
90
  - lib/quebert/async_sender/class.rb
90
91
  - lib/quebert/async_sender/instance.rb
91
92
  - lib/quebert/async_sender/object.rb
93
+ - lib/quebert/async_sender/promise.rb
92
94
  - lib/quebert/backend.rb
93
95
  - lib/quebert/backend/beanstalk.rb
94
96
  - lib/quebert/backend/in_process.rb
data/LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright (c) 2009 Brad Gessler
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.