ruote-resque 0.1.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.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rubocop.yml +4 -0
- data/.travis.yml +14 -0
- data/.yardopts +4 -0
- data/Gemfile +13 -0
- data/LICENSE +22 -0
- data/README.md +156 -0
- data/Rakefile +1 -0
- data/lib/ruote/resque.rb +40 -0
- data/lib/ruote/resque/client.rb +62 -0
- data/lib/ruote/resque/job.rb +47 -0
- data/lib/ruote/resque/participant.rb +86 -0
- data/lib/ruote/resque/participant_registrar.rb +42 -0
- data/lib/ruote/resque/receiver.rb +140 -0
- data/lib/ruote/resque/reply_job.rb +23 -0
- data/lib/ruote/resque/version.rb +7 -0
- data/ruote-resque.gemspec +28 -0
- data/spec/lib/ruote/resque/job_spec.rb +129 -0
- data/spec/lib/ruote/resque/participant_registrar_spec.rb +52 -0
- data/spec/lib/ruote/resque/participant_spec.rb +118 -0
- data/spec/lib/ruote/resque/receiver_spec.rb +208 -0
- data/spec/lib/ruote/resque/reply_job_spec.rb +38 -0
- data/spec/lib/ruote/resque_spec.rb +99 -0
- data/spec/spec_helper.rb +21 -0
- metadata +161 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Ruote
|
4
|
+
module Resque
|
5
|
+
|
6
|
+
# An object to easy Participant registration
|
7
|
+
# @example Register a participant
|
8
|
+
# # Will register a participant be_awesome
|
9
|
+
# # that enqueues the Job MyAwesomeJob to my_queue
|
10
|
+
# Ruote::Resque.register(dashboard) do
|
11
|
+
# be_awesome 'MyAwesomeJob', :my_queue
|
12
|
+
# # or via the participant method
|
13
|
+
# participant 'be_awesome', 'MyAwesomeJob', :my_queue
|
14
|
+
# end
|
15
|
+
class ParticipantRegistrar
|
16
|
+
|
17
|
+
# @param [Ruote::Dashboard] dashboard
|
18
|
+
# @return [Ruote::Resque::ParticipantRegistrar]
|
19
|
+
def initialize(dashboard)
|
20
|
+
@dashboard = dashboard
|
21
|
+
end
|
22
|
+
|
23
|
+
# Implements the dsl to register participants
|
24
|
+
# @see Ruote::Resque::ParticipantRegistrar
|
25
|
+
def method_missing(method_name, *args, &block)
|
26
|
+
participant(method_name.to_s, *args, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Call this method to register a participant (or use method_missing)
|
30
|
+
# @param [#to_s] name the name of the participant
|
31
|
+
# @param [#to_s] klass the class of the Resque job
|
32
|
+
# @param [#to_s] queue the queue of the job
|
33
|
+
# @param [Hash] options options to be passed on to +Ruote::Resque::Participant+
|
34
|
+
# @return [void]
|
35
|
+
def participant(name, klass, queue, options = {})
|
36
|
+
options.merge!({ :class => klass, :queue => queue })
|
37
|
+
@dashboard.register_participant(name, Ruote::Resque::Participant, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Ruote
|
4
|
+
module Resque
|
5
|
+
|
6
|
+
# Raised when a job different from `Ruote::Resque::ReplyJob
|
7
|
+
# is found on the reply_queue.
|
8
|
+
class InvalidJob < RuntimeError
|
9
|
+
end
|
10
|
+
|
11
|
+
# Raised when a reply job has an invalid workitem.
|
12
|
+
class InvalidWorkitem < RuntimeError
|
13
|
+
end
|
14
|
+
|
15
|
+
# The receiver will poll the reply_queue in Resque, waiting for reply jobs.
|
16
|
+
# It does so in a new thread.
|
17
|
+
#
|
18
|
+
# By default it polls the reply_queue every 5 seconds, but this is configurable via
|
19
|
+
# the `interval` configuration option. See {Ruote::Resque}.
|
20
|
+
#
|
21
|
+
# You should launch the Receiver as soon as your engine is set up.
|
22
|
+
#
|
23
|
+
# @example Running a ruote-resque Receiver
|
24
|
+
# Ruote::Resque::Receiver.new(dashboard)
|
25
|
+
#
|
26
|
+
# @example Overriding the handle_error method for custom exception handling
|
27
|
+
# class Ruote::Resque::Receiver
|
28
|
+
# def handle_error(e)
|
29
|
+
# MyErrorHandler.handle(e)
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# Ruote::Resque::Receiver.new(dashboard)
|
34
|
+
#
|
35
|
+
class Receiver < ::Ruote::Receiver
|
36
|
+
|
37
|
+
# Retunrs a new Receiver instance and spawns a worker thread.
|
38
|
+
# @param [Ruote::Dashboard] cwes Accepts context, worker, engine or storage
|
39
|
+
# @param [Hash] options Passed on to Ruote, currently unused.
|
40
|
+
# @return [Receiver]
|
41
|
+
def initialize(cwes, options = {})
|
42
|
+
super
|
43
|
+
@listener = listen
|
44
|
+
end
|
45
|
+
|
46
|
+
# Stops the worker thread.
|
47
|
+
# @return [void]
|
48
|
+
def shutdown
|
49
|
+
@listener.kill
|
50
|
+
end
|
51
|
+
|
52
|
+
# Called when an error is raised during the poll/reserve/process flow of the Receiver.
|
53
|
+
# You should override this method for custom error handling.
|
54
|
+
# By default it just logs the exception.
|
55
|
+
# @param [Exception] e
|
56
|
+
# @return [void]
|
57
|
+
def handle_error(e)
|
58
|
+
Ruote::Resque.logger.error(e)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def listen
|
64
|
+
|
65
|
+
Thread.new do
|
66
|
+
loop do
|
67
|
+
work
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
def work
|
74
|
+
|
75
|
+
reserve
|
76
|
+
|
77
|
+
# handle_error may raise an exception itself
|
78
|
+
# in this case protect the thread
|
79
|
+
rescue => e
|
80
|
+
Ruote::Resque.logger.error('*** UNCAUGHT EXCEPTION IN RUOTE::RESQUE::RECEIVER ***')
|
81
|
+
Ruote::Resque.logger.error(e)
|
82
|
+
end
|
83
|
+
|
84
|
+
def reserve
|
85
|
+
|
86
|
+
if job = ::Resque.reserve(Ruote::Resque.configuration.reply_queue)
|
87
|
+
validate_job(job)
|
88
|
+
process(job)
|
89
|
+
else
|
90
|
+
sleep Ruote::Resque.configuration.interval
|
91
|
+
end
|
92
|
+
|
93
|
+
rescue => e
|
94
|
+
handle_error(e)
|
95
|
+
end
|
96
|
+
|
97
|
+
def process(job)
|
98
|
+
|
99
|
+
job_arguments = job.args
|
100
|
+
item = job_arguments.pop
|
101
|
+
|
102
|
+
if job_arguments.any?
|
103
|
+
flunk(item, *job_arguments)
|
104
|
+
else
|
105
|
+
receive(item)
|
106
|
+
end
|
107
|
+
|
108
|
+
rescue => e
|
109
|
+
# Fail the job on Resque, then raise to let handle_error do it's work
|
110
|
+
job.fail(e)
|
111
|
+
raise
|
112
|
+
end
|
113
|
+
|
114
|
+
def validate_job(job)
|
115
|
+
|
116
|
+
job_class = job.payload_class.to_s
|
117
|
+
unless job_class == 'Ruote::Resque::ReplyJob'
|
118
|
+
raise InvalidJob.new(job_class)
|
119
|
+
end
|
120
|
+
|
121
|
+
item = job.args.last
|
122
|
+
unless item.is_a?(Hash) && item['fields'] && item['fei']
|
123
|
+
raise InvalidWorkitem.new(item.inspect)
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
def flunk(workitem, class_name, message, backtrace)
|
129
|
+
|
130
|
+
error = Ruote::ReceivedError.new(class_name, message, backtrace)
|
131
|
+
args = [error, message, backtrace]
|
132
|
+
|
133
|
+
super(workitem, *args)
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Ruote
|
4
|
+
module Resque
|
5
|
+
|
6
|
+
# An empty job used for message passing between job instances and ruote-resque.
|
7
|
+
module ReplyJob
|
8
|
+
|
9
|
+
# @return [#to_s] The configured queue for message passing.
|
10
|
+
def self.queue
|
11
|
+
Ruote::Resque.configuration.reply_queue
|
12
|
+
end
|
13
|
+
|
14
|
+
# This is a no-op.
|
15
|
+
# @return [void]
|
16
|
+
def self.perform(*args)
|
17
|
+
# noop
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ruote/resque/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ruote-resque"
|
8
|
+
spec.version = Ruote::Resque::VERSION
|
9
|
+
spec.authors = ["Adrien Kohlbecker"]
|
10
|
+
spec.email = ["adrien.kohlbecker@gmail.com"]
|
11
|
+
spec.description = %q{Resque participant/receiver pair for Ruote}
|
12
|
+
spec.summary = %q{Resque participant/receiver pair for Ruote}
|
13
|
+
spec.homepage = "https://github.com/adrienkohlbecker/ruote-resque"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'resque'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency 'mutant'
|
25
|
+
spec.add_development_dependency 'rubocop'
|
26
|
+
spec.add_development_dependency 'yard'
|
27
|
+
spec.add_development_dependency 'redcarpet'
|
28
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Ruote::Resque::Job do
|
6
|
+
|
7
|
+
context '::after_perform_reply_to_ruote' do
|
8
|
+
|
9
|
+
class Job
|
10
|
+
@queue = :rspec
|
11
|
+
extend Ruote::Resque::Job
|
12
|
+
def self.perform(workitem)
|
13
|
+
workitem['is_resque_awesome'] = true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:workitem) { { 'is_rspec_awesome' => true } }
|
18
|
+
let(:enqued_job) { ::Resque.reserve(Ruote::Resque.configuration.reply_queue) }
|
19
|
+
|
20
|
+
context 'enqueues a job' do
|
21
|
+
|
22
|
+
before :each do
|
23
|
+
Job.after_perform_reply_to_ruote(workitem)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'to resque' do
|
27
|
+
expect(enqued_job.class).to eq ::Resque::Job
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'to the configured reply_queue' do
|
31
|
+
expect(enqued_job.queue).to eq Ruote::Resque.configuration.reply_queue
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'with the workitem as arguments' do
|
35
|
+
expect(enqued_job.args).to eq [workitem]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'replies with the mutated workitem' do
|
41
|
+
|
42
|
+
let(:mutated_workitem) { { 'is_rspec_awesome' => true, 'is_resque_awesome' => true } }
|
43
|
+
|
44
|
+
before :each do
|
45
|
+
Resque.inline = true
|
46
|
+
end
|
47
|
+
|
48
|
+
after :each do
|
49
|
+
Resque.inline = false
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'allows the workitem to be mutated' do
|
53
|
+
|
54
|
+
Ruote::Resque::ReplyJob.should_receive(:perform).with(mutated_workitem)
|
55
|
+
Resque.enqueue(Job, workitem)
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
context '::on_failure_reply_to_ruote' do
|
64
|
+
|
65
|
+
class ErrorJob
|
66
|
+
@queue = :rspec
|
67
|
+
extend Ruote::Resque::Job
|
68
|
+
def self.perform(workitem)
|
69
|
+
workitem['is_resque_awesome'] = true
|
70
|
+
raise 'i am a failure'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
let(:workitem) { { 'is_rspec_awesome' => true } }
|
75
|
+
let(:enqued_job) { ::Resque.reserve(Ruote::Resque.configuration.reply_queue) }
|
76
|
+
let(:exception) { RuntimeError.new('i am a failure') }
|
77
|
+
let(:expected_job_args) do
|
78
|
+
[
|
79
|
+
exception.class.name,
|
80
|
+
exception.message,
|
81
|
+
exception.backtrace,
|
82
|
+
workitem
|
83
|
+
]
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'enqueues a job' do
|
87
|
+
|
88
|
+
before :each do
|
89
|
+
ErrorJob.on_failure_reply_to_ruote(exception, workitem)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'to resque' do
|
93
|
+
expect(enqued_job.class).to eq ::Resque::Job
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'to the configured reply_queue' do
|
97
|
+
expect(enqued_job.queue).to eq Ruote::Resque.configuration.reply_queue
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'with the workitem and the error as arguments' do
|
101
|
+
expect(enqued_job.args).to eq expected_job_args
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'replies with the mutated workitem' do
|
107
|
+
|
108
|
+
let(:mutated_workitem) { { 'is_rspec_awesome' => true, 'is_resque_awesome' => true } }
|
109
|
+
|
110
|
+
before :each do
|
111
|
+
Resque.inline = true
|
112
|
+
end
|
113
|
+
|
114
|
+
after :each do
|
115
|
+
Resque.inline = false
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'allows the workitem to be mutated' do
|
119
|
+
|
120
|
+
Ruote::Resque::ReplyJob.should_receive(:perform).with(hash_including(mutated_workitem))
|
121
|
+
Resque.enqueue(Job, workitem)
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
class MyAwesomeJob
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Ruote::Resque::ParticipantRegistrar do
|
9
|
+
|
10
|
+
context '#participant' do
|
11
|
+
|
12
|
+
let(:mock_dashboard) { Object.new }
|
13
|
+
let(:registrar) { Ruote::Resque::ParticipantRegistrar.new(mock_dashboard) }
|
14
|
+
|
15
|
+
it 'registers the participant to the dashboard' do
|
16
|
+
|
17
|
+
mock_dashboard.should_receive(:register_participant).with('be_awesome', Ruote::Resque::Participant, { :class => MyAwesomeJob, :queue => :rspec })
|
18
|
+
registrar.participant('be_awesome', MyAwesomeJob, :rspec)
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'allows more options to be sent' do
|
23
|
+
|
24
|
+
mock_dashboard.should_receive(:register_participant).with('be_awesome', Ruote::Resque::Participant, { :class => MyAwesomeJob, :queue => :rspec, :custom_option => :custom_value })
|
25
|
+
registrar.participant('be_awesome', MyAwesomeJob, :rspec, :custom_option => :custom_value)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
context '#method_missing' do
|
32
|
+
|
33
|
+
let(:mock_dashboard) { Object.new }
|
34
|
+
let(:registrar) { Ruote::Resque::ParticipantRegistrar.new(mock_dashboard) }
|
35
|
+
|
36
|
+
it 'registers the participant to the dashboard' do
|
37
|
+
|
38
|
+
mock_dashboard.should_receive(:register_participant).with('be_awesome', Ruote::Resque::Participant, { :class => MyAwesomeJob, :queue => :rspec })
|
39
|
+
registrar.be_awesome(MyAwesomeJob, :rspec)
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'allows more options to be sent' do
|
44
|
+
|
45
|
+
mock_dashboard.should_receive(:register_participant).with('be_awesome', Ruote::Resque::Participant, { :class => MyAwesomeJob, :queue => :rspec, :custom_option => :custom_value })
|
46
|
+
registrar.be_awesome(MyAwesomeJob, :rspec, :custom_option => :custom_value)
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Ruote::Resque::Participant do
|
6
|
+
|
7
|
+
it 'includes Ruote::LocalParticipant' do
|
8
|
+
expect(Ruote::Resque::Participant.ancestors).to include(Ruote::LocalParticipant)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'does not thread' do
|
12
|
+
expect(Ruote::Resque::Participant.new('class' => Class, 'queue' => :my_queue).do_not_thread).to be_true
|
13
|
+
end
|
14
|
+
|
15
|
+
context '#initialize' do
|
16
|
+
|
17
|
+
it 'takes a job class in options' do
|
18
|
+
|
19
|
+
participant = Ruote::Resque::Participant.new('class' => Class, 'queue' => :my_other_queue)
|
20
|
+
expect(participant.instance_variable_get(:@job_klass)).to eq Class
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'takes a job queue in options' do
|
25
|
+
|
26
|
+
participant = Ruote::Resque::Participant.new('class' => Class, 'queue' => :my_other_queue)
|
27
|
+
expect(participant.instance_variable_get(:@job_queue)).to eq :my_other_queue
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'validates that jobs have a queue' do
|
32
|
+
expect { Ruote::Resque::Participant.new('class' => Class) }.to raise_error ::Resque::NoQueueError
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'validates that jobs have a class' do
|
36
|
+
expect { Ruote::Resque::Participant.new('class' => '', 'queue' => :my_other_queue) }.to raise_error ::Resque::NoClassError
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
context '#on_workitem' do
|
42
|
+
|
43
|
+
let(:workitem) { { 'rspec_is_awesome' => true } }
|
44
|
+
|
45
|
+
before :each do
|
46
|
+
participant.stub(:workitem).and_return Ruote::Workitem.new(workitem)
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with forget set to false' do
|
50
|
+
|
51
|
+
let(:participant) { Ruote::Resque::Participant.new('class' => Class, 'queue' => :my_queue) }
|
52
|
+
|
53
|
+
it 'enqueues the given job to Resque' do
|
54
|
+
participant.on_workitem
|
55
|
+
expected_job = { 'class' => 'Class', 'args' => [workitem] }
|
56
|
+
expect(::Resque.pop(:my_queue)).to eq expected_job
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'does not reply to ruote' do
|
60
|
+
participant.should_not_receive(:reply)
|
61
|
+
participant.on_workitem
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with forget set to true' do
|
67
|
+
|
68
|
+
let(:participant) { Ruote::Resque::Participant.new('class' => Class, 'queue' => :my_queue, 'forget' => true) }
|
69
|
+
|
70
|
+
it 'replies to ruote' do
|
71
|
+
participant.should_receive(:reply)
|
72
|
+
participant.on_workitem
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
context '#on_cancel' do
|
80
|
+
|
81
|
+
let(:workitem) { { 'rspec_is_awesome' => true } }
|
82
|
+
let(:participant) { Ruote::Resque::Participant.new('class' => Class, 'queue' => :my_queue) }
|
83
|
+
|
84
|
+
before :each do
|
85
|
+
participant.stub(:workitem).and_return Ruote::Workitem.new(workitem)
|
86
|
+
participant.stub(:applied_workitem).and_return Ruote::Workitem.new(workitem)
|
87
|
+
participant.on_workitem
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'removes the given job to Resque' do
|
91
|
+
participant.on_cancel
|
92
|
+
expect(::Resque.pop(:my_queue)).to eq nil
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'removes only jobs with the same arguments' do
|
96
|
+
another_participant = Ruote::Resque::Participant.new('class' => Class, 'queue' => :my_queue)
|
97
|
+
another_workitem = { 'im_another_workitem' => true }
|
98
|
+
another_participant.stub(:workitem).and_return Ruote::Workitem.new(another_workitem)
|
99
|
+
another_participant.on_workitem
|
100
|
+
|
101
|
+
participant.on_cancel
|
102
|
+
expect(::Resque.pop(:my_queue)).to eq({ 'class' => 'Class', 'args' => [another_workitem] })
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
context '#encode_workitem' do
|
108
|
+
|
109
|
+
let(:workitem_hash) { { 'rspec_is_awesome' => true } }
|
110
|
+
let(:workitem) { Ruote::Workitem.new(workitem_hash) }
|
111
|
+
|
112
|
+
it 'returns a hash representation of the workitem' do
|
113
|
+
expect(Ruote::Resque::Participant.new('class' => Class, 'queue' => :my_queue).encode_workitem(workitem)).to eq(workitem_hash)
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|