inst-jobs 1.0.0 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c754ed71778d5b3f08641e133be947fae204a56dcee71aef08a7780a7d6afa5
4
- data.tar.gz: 10949318e78e8e9d56b92ee7f2d14bfd647da20ff70578d894e4d1e85441d2fe
3
+ metadata.gz: b7018574b89f64cc8e0a8e601ba594b2ae346cd1fed66237a62b02a71cdaa14c
4
+ data.tar.gz: bb5865eb7e5933717394ef47e85904827d4e065a2994de2eb9d7c4a43790da80
5
5
  SHA512:
6
- metadata.gz: 1a014e191bc0d6ccd083340b6d5c4bca0b7e03439aca459f79a5a704d93d16c42dd9e4855ca5985f7b1e4fb1fe62eead160cb6cb356c73b00ac297dc30112d8a
7
- data.tar.gz: 53997c66017cf6db561104054379cb9e7e934fcc56c54d552b7629ff29eeb58de37c8674088661ba683e7e4d8b19234f26021819753ac06a6c738dd435c3f169
6
+ metadata.gz: 9eeed8f4e9f853ed216c1c1817ab499f27ca6fe4c66837ce07b6e54e4d81f5ada261f19180403f9c6cf211f32daec480559ae9566f5d76b5c975196fe7998688
7
+ data.tar.gz: fea866765cec29e00c5b94da17d5ce3f0b432ca6d79111325d5fee2829a33b3bc445896079fe93d0a70537a59abc0dddd45d8869a32ab1c1e0e6ab3c24848482
@@ -0,0 +1,9 @@
1
+ module Kernel
2
+ def sender(i = 0)
3
+ frame_self = nil
4
+ # 3. one for the block, one for this method, one for the method calling this
5
+ # method, and _then_ we get to the self for who sent the message we want
6
+ RubyVM::DebugInspector.open { |dc| frame_self = dc.frame_self(3 + i) }
7
+ frame_self
8
+ end
9
+ end
@@ -1,14 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ if ::Rails.env.test? || ::Rails.env.development?
4
+ require 'debug_inspector'
5
+ end
6
+
3
7
  module Delayed
4
8
  module MessageSending
5
9
  class DelayProxy < BasicObject
6
- def initialize(object, enqueue_args)
10
+ def initialize(object, synchronous: false, sender: nil, **enqueue_args)
7
11
  @object = object
8
12
  @enqueue_args = enqueue_args
13
+ @synchronous = synchronous
14
+ @sender = sender
9
15
  end
10
16
 
11
17
  def method_missing(method, *args, **kwargs)
18
+ # method doesn't exist? must be method_missing; assume private access
19
+ @sender = nil if !@sender.nil? &&
20
+ !@object.methods.include?(method) &&
21
+ !@object.protected_methods.include?(method) &&
22
+ !@object.private_methods.include?(method)
23
+
24
+ sender_is_object = @sender == @object
25
+ sender_is_class = @sender.is_a?(@object.class)
26
+
27
+ # even if the call is async, if the call is _going_ to generate an error, we make it synchronous
28
+ # so that the error is generated immediately, instead of waiting for it to fail in a job,
29
+ # which might go unnoticed
30
+ if !@sender.nil? && !@synchronous
31
+ @synchronous = true if !sender_is_object && @object.private_methods.include?(method)
32
+ @synchronous = true if !sender_is_class && @object.protected_methods.include?(method)
33
+ end
34
+
35
+ if @synchronous
36
+ if @sender.nil? || sender_is_object || sender_is_class && @object.protected_methods.include?(method)
37
+ if kwargs.empty?
38
+ return @object.send(method, *args)
39
+ else
40
+ return @object.send(method, *args, **kwargs)
41
+ end
42
+ end
43
+
44
+ if kwargs.empty?
45
+ return @object.public_send(method, *args)
46
+ else
47
+ return @object.public_send(method, *args, **kwargs)
48
+ end
49
+ end
50
+
12
51
  ignore_transaction = @enqueue_args.delete(:ignore_transaction)
13
52
  on_failure = @enqueue_args.delete(:on_failure)
14
53
  on_permanent_failure = @enqueue_args.delete(:on_permanent_failure)
@@ -24,7 +63,8 @@ module Delayed
24
63
  ::Delayed::Job.enqueue(::Delayed::PerformableMethod.new(@object, method,
25
64
  args: args, kwargs: kwargs,
26
65
  on_failure: on_failure,
27
- on_permanent_failure: on_permanent_failure),
66
+ on_permanent_failure: on_permanent_failure,
67
+ sender: @sender),
28
68
  **@enqueue_args)
29
69
  end
30
70
  return nil
@@ -35,24 +75,31 @@ module Delayed
35
75
  args: args,
36
76
  kwargs: kwargs,
37
77
  on_failure: on_failure,
38
- on_permanent_failure: on_permanent_failure),
78
+ on_permanent_failure: on_permanent_failure,
79
+ sender: @sender),
39
80
  **@enqueue_args)
40
81
  result = nil unless ignore_transaction
41
82
  result
42
83
  end
43
84
  end
44
85
 
45
- def delay(**enqueue_args)
86
+ def delay(sender: nil, **enqueue_args)
46
87
  # support procs/methods as enqueue arguments
47
88
  enqueue_args.each do |k,v|
48
89
  if v.respond_to?(:call)
49
90
  enqueue_args[k] = v.call(self)
50
91
  end
51
92
  end
52
- if enqueue_args.delete(:synchronous)
53
- return self
54
- end
55
- DelayProxy.new(self, enqueue_args)
93
+
94
+ sender ||= __calculate_sender_for_delay
95
+
96
+ DelayProxy.new(self, sender: sender, **enqueue_args)
97
+ end
98
+
99
+ def __calculate_sender_for_delay
100
+ # enforce public send in dev and test, but not prod (since it uses
101
+ # debug APIs, it's expensive)
102
+ return sender(1) if ::Rails.env.test? || ::Rails.env.development?
56
103
  end
57
104
 
58
105
  module ClassMethods
@@ -76,7 +123,7 @@ module Delayed
76
123
  if synchronous
77
124
  super(*args, **kwargs)
78
125
  else
79
- delay(**enqueue_args).method_missing(method_name, *args, synchronous: true, **kwargs)
126
+ delay(sender: __calculate_sender_for_delay, **enqueue_args).method_missing(method_name, *args, synchronous: true, **kwargs)
80
127
  end
81
128
  end)
82
129
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Delayed
4
- class PerformableMethod < Struct.new(:object, :method, :args, :kwargs, :fail_cb, :permanent_fail_cb)
5
- def initialize(object, method, args: [], kwargs: {}, on_failure: nil, on_permanent_failure: nil)
4
+ class PerformableMethod < Struct.new(:object, :method, :args, :kwargs, :fail_cb, :permanent_fail_cb, :sender)
5
+ def initialize(object, method, args: [], kwargs: {}, on_failure: nil, on_permanent_failure: nil, sender: nil)
6
6
  raise NoMethodError, "undefined method `#{method}' for #{object.inspect}" unless object.respond_to?(method, true)
7
7
 
8
8
  self.object = object
@@ -11,6 +11,13 @@ module Delayed
11
11
  self.method = method.to_sym
12
12
  self.fail_cb = on_failure
13
13
  self.permanent_fail_cb = on_permanent_failure
14
+ self.sender = sender
15
+ begin
16
+ YAML.load(YAML.dump(sender))
17
+ rescue
18
+ # if for some reason you can't dump the sender, just drop it
19
+ self.sender = nil
20
+ end
14
21
  end
15
22
 
16
23
  def display_name
@@ -24,10 +31,22 @@ module Delayed
24
31
 
25
32
  def perform
26
33
  kwargs = self.kwargs || {}
27
- if kwargs.empty?
28
- object.send(method, *args)
34
+
35
+ sender_is_object = sender == object
36
+ sender_is_class = sender.is_a?(object.class)
37
+
38
+ if sender.nil? || sender_is_object || sender_is_class && object.protected_methods.include?(method)
39
+ if kwargs.empty?
40
+ object.send(method, *args)
41
+ else
42
+ object.send(method, *args, **kwargs)
43
+ end
29
44
  else
30
- object.send(method, *args, **kwargs)
45
+ if kwargs.empty?
46
+ object.public_send(method, *args)
47
+ else
48
+ object.public_send(method, *args, **kwargs)
49
+ end
31
50
  end
32
51
  end
33
52
 
@@ -54,7 +73,8 @@ module Delayed
54
73
 
55
74
  def full_name
56
75
  obj_name = object.is_a?(ActiveRecord::Base) ? "#{object.class}.find(#{object.id}).#{method}" : display_name
57
- kwargs_str = kwargs.map { |(k, v)| ", #{k}: #{deep_de_ar_ize(v)}"}.join("")
76
+ kgs = kwargs || {}
77
+ kwargs_str = kgs.map { |(k, v)| ", #{k}: #{deep_de_ar_ize(v)}"}.join("")
58
78
  "#{obj_name}(#{args.map { |a| deep_de_ar_ize(a) }.join(', ')}#{kwargs_str})"
59
79
  end
60
80
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Delayed
4
- VERSION = "1.0.0"
4
+ VERSION = "1.0.4"
5
5
  end
@@ -13,7 +13,7 @@ module Delayed
13
13
  DEFAULT_SERVICE_NAME = 'inst-jobs_worker'.freeze
14
14
  attr_reader :agent_client, :catalog_client
15
15
 
16
- def initialize(*args)
16
+ def initialize(*, **)
17
17
  super
18
18
  # Because we don't want the consul client to be a hard dependency we're
19
19
  # only requiring it once it's absolutely needed
data/lib/delayed_job.rb CHANGED
@@ -19,6 +19,8 @@ require 'active_support/core_ext/module/attribute_accessors'
19
19
  require 'active_record'
20
20
  require 'after_transaction_commit'
21
21
 
22
+ require 'delayed/core_ext/kernel'
23
+
22
24
  require 'delayed/settings'
23
25
  require 'delayed/yaml_extensions'
24
26
 
@@ -7,10 +7,6 @@ describe 'Delayed::Backed::ActiveRecord::Job' do
7
7
  Delayed.select_backend(Delayed::Backend::ActiveRecord::Job)
8
8
  end
9
9
 
10
- after :all do
11
- Delayed.send(:remove_const, :Job)
12
- end
13
-
14
10
  before do
15
11
  Delayed::Testing.clear_all!
16
12
  end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'debug_inspector'
5
+
6
+ RSpec.describe Delayed::MessageSending do
7
+ before do
8
+ allow(::Rails.env).to receive(:test?).and_return(true)
9
+ end
10
+
11
+ before (:all) do
12
+ class SpecClass
13
+ def call_private(**enqueue_args)
14
+ delay(**enqueue_args).private_method
15
+ end
16
+
17
+ def call_protected(**enqueue_args)
18
+ other = self.class.new
19
+ other.delay(**enqueue_args).protected_method
20
+ end
21
+
22
+ private
23
+
24
+ def private_method
25
+ end
26
+
27
+ protected
28
+
29
+ def protected_method
30
+ end
31
+ end
32
+ end
33
+
34
+ after(:all) do
35
+ Object.send(:remove_const, :SpecClass)
36
+ end
37
+
38
+ let(:klass) { SpecClass }
39
+
40
+ it "allows an object to send a private message to itself" do
41
+ job = klass.new.call_private(ignore_transaction: true)
42
+ job.invoke_job
43
+ end
44
+
45
+ it "allows an object to send a private message to itself synchronouosly" do
46
+ klass.new.call_private(synchronous: true)
47
+ end
48
+
49
+ it "warns about directly sending a private message asynchronously" do
50
+ expect { klass.new.delay.private_method }.to raise_error(NoMethodError)
51
+ end
52
+
53
+ it "warns about directly sending a private message synchronusly" do
54
+ expect { klass.new.delay(synchronous: true).private_method }.to raise_error(NoMethodError)
55
+ end
56
+
57
+ it "does not warn about directly sending a private message in production" do
58
+ allow(::Rails.env).to receive(:test?).and_return(false)
59
+ allow(::Rails.env).to receive(:development?).and_return(false)
60
+ klass.new.delay.private_method
61
+ end
62
+
63
+ it "does not warn about directly sending a private message synchronously in production" do
64
+ allow(::Rails.env).to receive(:test?).and_return(false)
65
+ allow(::Rails.env).to receive(:development?).and_return(false)
66
+ klass.new.delay(synchronous: true).private_method
67
+ end
68
+
69
+ it "allows an object to send a protected message to itself" do
70
+ job = klass.new.call_protected(ignore_transaction: true)
71
+ job.invoke_job
72
+ end
73
+
74
+ it "allows an object to send a protected message to itself synchronouosly" do
75
+ klass.new.call_protected(synchronous: true)
76
+ end
77
+
78
+ it "warns about directly sending a protected message asynchronously" do
79
+ expect { klass.new.delay.protected_method }.to raise_error(NoMethodError)
80
+ end
81
+
82
+ it "warns about directly sending a protected message synchronusly" do
83
+ expect { klass.new.delay(synchronous: true).protected_method }.to raise_error(NoMethodError)
84
+ end
85
+
86
+ it "doesn't explode if you can't dump the sender" do
87
+ klass = Class.new do
88
+ def delay_something
89
+ Kernel.delay.sleep(1)
90
+ end
91
+
92
+ def encode_with(encoder)
93
+ raise "yaml encoding failed"
94
+ end
95
+ end
96
+
97
+ obj = klass.new
98
+ expect { YAML.dump(obj) }.to raise_error("yaml encoding failed")
99
+ expect { obj.delay_something }.not_to raise_error
100
+ end
101
+ end
@@ -20,10 +20,6 @@ RSpec.describe Delayed::Server, sinatra: true do
20
20
  Delayed.select_backend(Delayed::Backend::ActiveRecord::Job)
21
21
  end
22
22
 
23
- after :all do
24
- Delayed.send(:remove_const, :Job)
25
- end
26
-
27
23
  describe "get '/running'" do
28
24
  before do
29
25
  3.times do |i|
@@ -7,10 +7,6 @@ RSpec.describe Delayed::WorkQueue::InProcess do
7
7
  Delayed.select_backend(Delayed::Backend::ActiveRecord::Job)
8
8
  end
9
9
 
10
- after :all do
11
- Delayed.send(:remove_const, :Job)
12
- end
13
-
14
10
  after :each do
15
11
  Delayed::Worker.lifecycle.reset!
16
12
  end
@@ -16,10 +16,6 @@ RSpec.describe Delayed::WorkQueue::ParentProcess::Client do
16
16
  Delayed.select_backend(Delayed::Backend::ActiveRecord::Job)
17
17
  end
18
18
 
19
- after :all do
20
- Delayed.send(:remove_const, :Job)
21
- end
22
-
23
19
  it 'marshals the given arguments to the server and returns the response' do
24
20
  expect(addrinfo).to receive(:connect).once.and_return(connection)
25
21
  expect(connection).to receive(:eof?).and_return(false)
@@ -31,7 +31,6 @@ RSpec.describe Delayed::WorkQueue::ParentProcess::Server do
31
31
  end
32
32
 
33
33
  after :all do
34
- Delayed.send(:remove_const, :Job)
35
34
  Delayed::Settings.parent_process = {}
36
35
  end
37
36
 
@@ -13,7 +13,6 @@ RSpec.describe Delayed::WorkQueue::ParentProcess do
13
13
  end
14
14
 
15
15
  after :all do
16
- Delayed.send(:remove_const, :Job)
17
16
  Delayed::Settings.parent_process = {}
18
17
  end
19
18
 
@@ -17,7 +17,7 @@ RSpec.describe Delayed::Worker::ConsulHealthCheck do
17
17
 
18
18
  describe '#initialize' do
19
19
  it 'must use the default agent client when the config is mostly empty' do
20
- check = Delayed::Worker::ConsulHealthCheck.new({worker_name: 'foobar'})
20
+ check = Delayed::Worker::ConsulHealthCheck.new(worker_name: 'foobar')
21
21
  expect(check.agent_client).to eq Imperium::Agent.default_client
22
22
  end
23
23
 
@@ -7,10 +7,6 @@ describe 'Delayed::Backend::Redis::Job' do
7
7
  Delayed.select_backend(Delayed::Backend::Redis::Job)
8
8
  end
9
9
 
10
- after :all do
11
- Delayed.send(:remove_const, :Job)
12
- end
13
-
14
10
  before do
15
11
  Delayed::Testing.clear_all!
16
12
  end
@@ -82,11 +82,11 @@ shared_examples_for 'random ruby objects' do
82
82
  obj = klass.new
83
83
  method = double()
84
84
 
85
- expect(Delayed::PerformableMethod).to receive(:new).with(obj, :test_method, args: [1,2,3], kwargs: {synchronous: true}, on_failure: nil, on_permanent_failure: nil).and_return(method)
85
+ expect(Delayed::PerformableMethod).to receive(:new).with(obj, :test_method, args: [1,2,3], kwargs: {synchronous: true}, on_failure: nil, on_permanent_failure: nil, sender: obj).and_return(method)
86
86
  expect(Delayed::Job).to receive(:enqueue).with(method, :enqueue_arg_1 => :thing)
87
87
  obj.test_method(1,2,3)
88
88
 
89
- expect(Delayed::PerformableMethod).to receive(:new).with(obj, :test_method, args: [4], kwargs: {:synchronous=>true}, on_failure: nil, on_permanent_failure: nil).and_return(method)
89
+ expect(Delayed::PerformableMethod).to receive(:new).with(obj, :test_method, args: [4], kwargs: {:synchronous=>true}, on_failure: nil, on_permanent_failure: nil, sender: obj).and_return(method)
90
90
  expect(Delayed::Job).to receive(:enqueue).with(method, :enqueue_arg_1 => :thing)
91
91
  obj.test_method(4)
92
92
 
@@ -65,4 +65,10 @@ shared_examples_for 'Delayed::PerformableMethod' do
65
65
  p.send(:on_permanent_failure, 'fail_frd')
66
66
  story.text.should == 'fail_frd'
67
67
  end
68
+
69
+ it "can still generate a name with no kwargs" do
70
+ story = Story.create :text => 'wat'
71
+ p = Delayed::PerformableMethod.new(story, :tell, kwargs: nil)
72
+ expect(p.full_name).to eq("Story.find(#{story.id}).tell()")
73
+ end
68
74
  end
data/spec/spec_helper.rb CHANGED
@@ -35,6 +35,15 @@ RSpec.configure do |config|
35
35
  end
36
36
  end
37
37
 
38
+ module NoYamlDump
39
+ def encode_with(coder)
40
+ end
41
+ end
42
+ # example groups are often the sender, and if we try to serialize them,
43
+ # the resultant object is then encoded in the sender, and then we serialize
44
+ # again, and it just keeps getting bigger and bigger and bigger...
45
+ RSpec::Core::ExampleGroup.include(NoYamlDump)
46
+
38
47
  ENV['TEST_ENV_NUMBER'] ||= '1'
39
48
  ENV['TEST_DB_HOST'] ||= 'localhost'
40
49
  ENV['TEST_DB_DATABASE'] ||= "inst-jobs-test-#{ENV['TEST_ENV_NUMBER']}"
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inst-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
8
8
  - Brian Palmer
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-10-26 00:00:00.000000000 Z
12
+ date: 2020-11-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -115,6 +115,20 @@ dependencies:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
117
  version: '1.3'
118
+ - !ruby/object:Gem::Dependency
119
+ name: debug_inspector
120
+ requirement: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.0.3
125
+ type: :runtime
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.0.3
118
132
  - !ruby/object:Gem::Dependency
119
133
  name: bump
120
134
  requirement: !ruby/object:Gem::Requirement
@@ -311,7 +325,7 @@ dependencies:
311
325
  - - "~>"
312
326
  - !ruby/object:Gem::Version
313
327
  version: 1.4.0
314
- description:
328
+ description:
315
329
  email:
316
330
  - brianp@instructure.com
317
331
  executables:
@@ -361,6 +375,7 @@ files:
361
375
  - lib/delayed/backend/redis/tickle_strand.lua
362
376
  - lib/delayed/batch.rb
363
377
  - lib/delayed/cli.rb
378
+ - lib/delayed/core_ext/kernel.rb
364
379
  - lib/delayed/daemon.rb
365
380
  - lib/delayed/engine.rb
366
381
  - lib/delayed/job_tracking.rb
@@ -396,6 +411,7 @@ files:
396
411
  - spec/active_record_job_spec.rb
397
412
  - spec/delayed/cli_spec.rb
398
413
  - spec/delayed/daemon_spec.rb
414
+ - spec/delayed/message_sending_spec.rb
399
415
  - spec/delayed/server_spec.rb
400
416
  - spec/delayed/settings_spec.rb
401
417
  - spec/delayed/work_queue/in_process_spec.rb
@@ -406,15 +422,10 @@ files:
406
422
  - spec/delayed/worker/health_check_spec.rb
407
423
  - spec/delayed/worker_spec.rb
408
424
  - spec/gemfiles/42.gemfile
409
- - spec/gemfiles/42.gemfile.lock
410
425
  - spec/gemfiles/50.gemfile
411
- - spec/gemfiles/50.gemfile.lock
412
426
  - spec/gemfiles/51.gemfile
413
- - spec/gemfiles/51.gemfile.lock
414
427
  - spec/gemfiles/52.gemfile
415
- - spec/gemfiles/52.gemfile.lock
416
428
  - spec/gemfiles/60.gemfile
417
- - spec/gemfiles/60.gemfile.lock
418
429
  - spec/migrate/20140924140513_add_story_table.rb
419
430
  - spec/redis_job_spec.rb
420
431
  - spec/sample_jobs.rb
@@ -429,7 +440,7 @@ files:
429
440
  homepage: https://github.com/instructure/inst-jobs
430
441
  licenses: []
431
442
  metadata: {}
432
- post_install_message:
443
+ post_install_message:
433
444
  rdoc_options: []
434
445
  require_paths:
435
446
  - lib
@@ -444,23 +455,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
444
455
  - !ruby/object:Gem::Version
445
456
  version: '0'
446
457
  requirements: []
447
- rubygems_version: 3.1.4
448
- signing_key:
458
+ rubygems_version: 3.0.3
459
+ signing_key:
449
460
  specification_version: 4
450
461
  summary: Instructure-maintained fork of delayed_job
451
462
  test_files:
452
463
  - spec/sample_jobs.rb
453
464
  - spec/spec_helper.rb
454
465
  - spec/redis_job_spec.rb
455
- - spec/gemfiles/51.gemfile.lock
456
- - spec/gemfiles/60.gemfile.lock
457
- - spec/gemfiles/42.gemfile.lock
458
- - spec/gemfiles/50.gemfile.lock
459
466
  - spec/gemfiles/60.gemfile
460
467
  - spec/gemfiles/42.gemfile
461
468
  - spec/gemfiles/52.gemfile
462
469
  - spec/gemfiles/50.gemfile
463
- - spec/gemfiles/52.gemfile.lock
464
470
  - spec/gemfiles/51.gemfile
465
471
  - spec/shared_jobs_specs.rb
466
472
  - spec/shared/performable_method.rb
@@ -474,6 +480,7 @@ test_files:
474
480
  - spec/delayed/cli_spec.rb
475
481
  - spec/delayed/daemon_spec.rb
476
482
  - spec/delayed/worker_spec.rb
483
+ - spec/delayed/message_sending_spec.rb
477
484
  - spec/delayed/settings_spec.rb
478
485
  - spec/delayed/work_queue/in_process_spec.rb
479
486
  - spec/delayed/work_queue/parent_process_spec.rb