aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2014-05-19 12:06:09 +0200
committerDavid Heinemeier Hansson <david@loudthinking.com>2014-05-19 12:06:09 +0200
commit211ce71400449c7e65cbef8ba9546418a20b3c8f (patch)
tree46715d030772f963621efa600e4a9cf2ee1faf93
parent65bf5f101e1105411afe030887fbe203d08dadbd (diff)
downloadrails-211ce71400449c7e65cbef8ba9546418a20b3c8f.tar.gz
rails-211ce71400449c7e65cbef8ba9546418a20b3c8f.tar.bz2
rails-211ce71400449c7e65cbef8ba9546418a20b3c8f.zip
Add GlobalID support for serialization
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock13
-rw-r--r--README.rdoc29
-rw-r--r--lib/active_job/base.rb6
-rw-r--r--lib/active_job/enqueuing.rb9
-rw-r--r--lib/active_job/job_wrappers/delayed_job_wrapper.rb9
-rw-r--r--lib/active_job/job_wrappers/resque_wrapper.rb4
-rw-r--r--lib/active_job/job_wrappers/sidekiq_wrapper.rb4
-rw-r--r--lib/active_job/job_wrappers/sucker_punch_wrapper.rb2
-rw-r--r--lib/active_job/parameters.rb15
-rw-r--r--lib/active_job/queue_adapters/delayed_job_adapter.rb3
-rw-r--r--lib/active_job/queue_adapters/inline_adapter.rb2
-rw-r--r--test/cases/job_serialization_test.rb15
-rw-r--r--test/cases/parameters_test.rb31
-rw-r--r--test/jobs/gid_job.rb6
-rw-r--r--test/models/person.rb19
16 files changed, 157 insertions, 11 deletions
diff --git a/Gemfile b/Gemfile
index f8c97a8cab..92b0ed1765 100644
--- a/Gemfile
+++ b/Gemfile
@@ -6,3 +6,4 @@ gem 'resque'
gem 'sidekiq'
gem 'sucker_punch'
gem 'delayed_job'
+gem 'activemodel-globalid', github: 'rails/activemodel-globalid' \ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
index 7005cc4d46..e8e8e0eb18 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,3 +1,11 @@
+GIT
+ remote: git://github.com/rails/activemodel-globalid.git
+ revision: c9d4cfa80e9234d178617338b22728e7c08498d1
+ specs:
+ activemodel-globalid (0.1.0)
+ activemodel (>= 4.1.0)
+ activesupport (>= 4.1.0)
+
PATH
remote: .
specs:
@@ -7,12 +15,16 @@ PATH
GEM
remote: https://rubygems.org/
specs:
+ activemodel (4.1.1)
+ activesupport (= 4.1.1)
+ builder (~> 3.1)
activesupport (4.1.1)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.1)
tzinfo (~> 1.1)
+ builder (3.2.2)
celluloid (0.15.2)
timers (~> 1.1.0)
connection_pool (2.0.0)
@@ -60,6 +72,7 @@ PLATFORMS
DEPENDENCIES
activejob!
+ activemodel-globalid!
delayed_job
resque
sidekiq
diff --git a/README.rdoc b/README.rdoc
index c83a5b2986..84d40809f7 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -11,6 +11,35 @@ one of the most common jobs in a modern web application: Sending emails outside
of the request-response cycle, so the user doesn't have to wait on it.
+== GlobalID support
+
+Active Job supports GlobalID serialization for parameters. This makes it possible
+to pass live Active Record objects to your job instead of class/id pairs, which
+you then have to manually deserialize. Before, jobs would look like this:
+
+```ruby
+class TrashableCleanupJob
+ def self.perfom(trashable_class, trashable_id, depth)
+ trashable = trashable_class.constantize.find(trashable_id)
+ trashable.cleanup(depth)
+ end
+end
+```
+
+Now you can simply do:
+
+```ruby
+class TrashableCleanupJob
+ def self.perfom(trashable, depth)
+ trashable.cleanup(depth)
+ end
+end
+```
+
+This works with any class that mixes in ActiveModel::GlobalIdentification, which
+by default has been mixed into Active Record classes.
+
+
== Supported queueing systems
We currently have adapters for:
diff --git a/lib/active_job/base.rb b/lib/active_job/base.rb
index fe3d1677dd..77b929d4af 100644
--- a/lib/active_job/base.rb
+++ b/lib/active_job/base.rb
@@ -1,13 +1,11 @@
require 'active_job/queue_adapter'
require 'active_job/queue_name'
+require 'active_job/enqueuing'
module ActiveJob
class Base
extend QueueAdapter
extend QueueName
-
- def self.enqueue(*args)
- queue_adapter.queue self, *args
- end
+ extend Enqueuing
end
end \ No newline at end of file
diff --git a/lib/active_job/enqueuing.rb b/lib/active_job/enqueuing.rb
new file mode 100644
index 0000000000..94a9dbf8ab
--- /dev/null
+++ b/lib/active_job/enqueuing.rb
@@ -0,0 +1,9 @@
+require 'active_job/parameters'
+
+module ActiveJob
+ module Enqueuing
+ def enqueue(*args)
+ queue_adapter.queue self, *Parameters.serialize(args)
+ end
+ end
+end \ No newline at end of file
diff --git a/lib/active_job/job_wrappers/delayed_job_wrapper.rb b/lib/active_job/job_wrappers/delayed_job_wrapper.rb
new file mode 100644
index 0000000000..0868d7b570
--- /dev/null
+++ b/lib/active_job/job_wrappers/delayed_job_wrapper.rb
@@ -0,0 +1,9 @@
+module ActiveJob
+ module JobWrappers
+ class DelayedJobWrapper
+ def perform(job, *args)
+ job.perform(*ActiveJob::Parameters.deserialize(args))
+ end
+ end
+ end
+end
diff --git a/lib/active_job/job_wrappers/resque_wrapper.rb b/lib/active_job/job_wrappers/resque_wrapper.rb
index cbeee4fb1b..68d9b252ba 100644
--- a/lib/active_job/job_wrappers/resque_wrapper.rb
+++ b/lib/active_job/job_wrappers/resque_wrapper.rb
@@ -3,8 +3,6 @@ require 'resque'
require 'active_support/core_ext/enumerable'
require 'active_support/core_ext/array/access'
-
-
module ActiveJob
module JobWrappers
class ResqueWrapper
@@ -14,7 +12,7 @@ module ActiveJob
end
def perform(job_name, *args)
- job_name.constantize.perform(*args)
+ job_name.constantize.perform(*ActiveJob::Parameters.deserialize(args))
end
end
diff --git a/lib/active_job/job_wrappers/sidekiq_wrapper.rb b/lib/active_job/job_wrappers/sidekiq_wrapper.rb
index fb728ae0fd..e1332b0210 100644
--- a/lib/active_job/job_wrappers/sidekiq_wrapper.rb
+++ b/lib/active_job/job_wrappers/sidekiq_wrapper.rb
@@ -1,10 +1,12 @@
+require 'active_job/parameters'
+
module ActiveJob
module JobWrappers
class SidekiqWrapper
include Sidekiq::Worker
def perform(job_name, *args)
- job_name.constantize.perform(*args)
+ job_name.constantize.perform(*ActiveJob::Parameters.deserialize(args))
end
end
end
diff --git a/lib/active_job/job_wrappers/sucker_punch_wrapper.rb b/lib/active_job/job_wrappers/sucker_punch_wrapper.rb
index 80648792ca..7e9960b44f 100644
--- a/lib/active_job/job_wrappers/sucker_punch_wrapper.rb
+++ b/lib/active_job/job_wrappers/sucker_punch_wrapper.rb
@@ -4,7 +4,7 @@ module ActiveJob
include SuckerPunch::Job
def perform(job_name, *args)
- job_name.perform(*args)
+ job_name.perform(*ActiveJob::Parameters.deserialize(args))
end
end
end
diff --git a/lib/active_job/parameters.rb b/lib/active_job/parameters.rb
new file mode 100644
index 0000000000..a4841abd1e
--- /dev/null
+++ b/lib/active_job/parameters.rb
@@ -0,0 +1,15 @@
+require 'active_model/global_locator'
+require 'active_support/core_ext/object/try'
+
+module ActiveJob
+ class Parameters
+ def self.serialize(params)
+ params.collect { |param| param.try(:global_id) || param }
+ end
+
+ def self.deserialize(params)
+ params.collect { |param| ActiveModel::GlobalLocator.locate(param) || param }
+ end
+ end
+end
+ \ No newline at end of file
diff --git a/lib/active_job/queue_adapters/delayed_job_adapter.rb b/lib/active_job/queue_adapters/delayed_job_adapter.rb
index 33229dece4..4730d97a9a 100644
--- a/lib/active_job/queue_adapters/delayed_job_adapter.rb
+++ b/lib/active_job/queue_adapters/delayed_job_adapter.rb
@@ -1,11 +1,12 @@
require 'delayed_job'
+require 'active_job/job_wrappers/delayed_job_wrapper'
module ActiveJob
module QueueAdapters
class DelayedJobAdapter
class << self
def queue(job, *args)
- job.delay(queue: job.queue_name).perform(*args)
+ JobWrappers::DelayedJobWrapper.new.delay(queue: job.queue_name).perform(job, *args)
end
end
end
diff --git a/lib/active_job/queue_adapters/inline_adapter.rb b/lib/active_job/queue_adapters/inline_adapter.rb
index ac28670a29..0a1526dce7 100644
--- a/lib/active_job/queue_adapters/inline_adapter.rb
+++ b/lib/active_job/queue_adapters/inline_adapter.rb
@@ -3,7 +3,7 @@ module ActiveJob
class InlineAdapter
class << self
def queue(job, *args)
- job.perform(*args)
+ job.perform(*ActiveJob::Parameters.deserialize(args))
end
end
end
diff --git a/test/cases/job_serialization_test.rb b/test/cases/job_serialization_test.rb
new file mode 100644
index 0000000000..b1e24db22e
--- /dev/null
+++ b/test/cases/job_serialization_test.rb
@@ -0,0 +1,15 @@
+require 'helper'
+require 'jobs/gid_job'
+require 'models/person'
+
+class JobSerializationTest < ActiveSupport::TestCase
+ setup do
+ $BUFFER = []
+ @person = Person.find(5)
+ end
+
+ test 'serialize job with gid' do
+ GidJob.enqueue @person
+ assert_equal "Person with ID: 5", $BUFFER.pop
+ end
+end
diff --git a/test/cases/parameters_test.rb b/test/cases/parameters_test.rb
new file mode 100644
index 0000000000..eafa5a052b
--- /dev/null
+++ b/test/cases/parameters_test.rb
@@ -0,0 +1,31 @@
+require 'helper'
+require 'active_job/parameters'
+require 'models/person'
+
+class ParameterSerializationTest < ActiveSupport::TestCase
+ test 'should make no change to regular values' do
+ assert_equal [ 1, "something" ], ActiveJob::Parameters.serialize([ 1, "something" ])
+ end
+
+ test 'should serialize records with global id' do
+ assert_equal [ Person.find(5).gid ], ActiveJob::Parameters.serialize([ Person.find(5) ])
+ end
+
+ test 'should serialize values and records together' do
+ assert_equal [ 3, Person.find(5).gid ], ActiveJob::Parameters.serialize([ 3, Person.find(5) ])
+ end
+end
+
+class ParameterDeserializationTest < ActiveSupport::TestCase
+ test 'should make no change to regular values' do
+ assert_equal [ 1, "something" ], ActiveJob::Parameters.deserialize([ 1, "something" ])
+ end
+
+ test 'should deserialize records with global id' do
+ assert_equal [ Person.find(5) ], ActiveJob::Parameters.deserialize([ Person.find(5).gid ])
+ end
+
+ test 'should serialize values and records together' do
+ assert_equal [ 3, Person.find(5) ], ActiveJob::Parameters.deserialize([ 3, Person.find(5).gid ])
+ end
+end
diff --git a/test/jobs/gid_job.rb b/test/jobs/gid_job.rb
new file mode 100644
index 0000000000..c1bfbb2655
--- /dev/null
+++ b/test/jobs/gid_job.rb
@@ -0,0 +1,6 @@
+class GidJob < ActiveJob::Base
+ def self.perform(person)
+ $BUFFER << "Person with ID: #{person.id}"
+ end
+end
+ \ No newline at end of file
diff --git a/test/models/person.rb b/test/models/person.rb
new file mode 100644
index 0000000000..6e91e8b9a2
--- /dev/null
+++ b/test/models/person.rb
@@ -0,0 +1,19 @@
+require 'active_model/global_identification'
+
+class Person
+ include ActiveModel::GlobalIdentification
+
+ attr_reader :id
+
+ def self.find(id)
+ new(id)
+ end
+
+ def initialize(id)
+ @id = id
+ end
+
+ def ==(other_person)
+ other_person.is_a?(Person) && id = other_person.id
+ end
+end \ No newline at end of file