quebert 1.12.0 → 2.0.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/.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.