inst-jobs 2.0.0 → 3.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.
- checksums.yaml +4 -4
- data/db/migrate/20101216224513_create_delayed_jobs.rb +9 -7
- data/db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb +8 -13
- data/db/migrate/20110610213249_optimize_delayed_jobs.rb +8 -8
- data/db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb +25 -25
- data/db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb +4 -8
- data/db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb +1 -3
- data/db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb +11 -15
- data/db/migrate/20120607181141_index_jobs_on_locked_by.rb +1 -1
- data/db/migrate/20120608191051_add_jobs_run_at_index.rb +2 -2
- data/db/migrate/20120927184213_change_delayed_jobs_handler_to_text.rb +1 -1
- data/db/migrate/20140505215510_copy_failed_jobs_original_id.rb +2 -3
- data/db/migrate/20150807133223_add_max_concurrent_to_jobs.rb +9 -13
- data/db/migrate/20151210162949_improve_max_concurrent.rb +4 -8
- data/db/migrate/20161206323555_add_back_default_string_limits_jobs.rb +3 -2
- data/db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb +13 -17
- data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +8 -8
- data/db/migrate/20200824222232_speed_up_max_concurrent_delete_trigger.rb +72 -77
- data/db/migrate/20200825011002_add_strand_order_override.rb +93 -97
- data/db/migrate/20210809145804_add_n_strand_index.rb +12 -0
- data/db/migrate/20210812210128_add_singleton_column.rb +200 -0
- data/db/migrate/20210917232626_add_delete_conflicting_singletons_before_unlock_trigger.rb +27 -0
- data/db/migrate/20210928174754_fix_singleton_condition_in_before_insert.rb +56 -0
- data/db/migrate/20210929204903_update_conflicting_singleton_function_to_use_index.rb +27 -0
- data/exe/inst_jobs +3 -2
- data/lib/delayed/backend/active_record.rb +211 -168
- data/lib/delayed/backend/base.rb +110 -72
- data/lib/delayed/batch.rb +11 -9
- data/lib/delayed/cli.rb +98 -84
- data/lib/delayed/core_ext/kernel.rb +4 -2
- data/lib/delayed/daemon.rb +70 -74
- data/lib/delayed/job_tracking.rb +26 -25
- data/lib/delayed/lifecycle.rb +27 -23
- data/lib/delayed/log_tailer.rb +17 -17
- data/lib/delayed/logging.rb +13 -16
- data/lib/delayed/message_sending.rb +43 -52
- data/lib/delayed/performable_method.rb +6 -8
- data/lib/delayed/periodic.rb +72 -68
- data/lib/delayed/plugin.rb +2 -4
- data/lib/delayed/pool.rb +205 -168
- data/lib/delayed/server/helpers.rb +6 -6
- data/lib/delayed/server.rb +51 -54
- data/lib/delayed/settings.rb +94 -81
- data/lib/delayed/testing.rb +21 -22
- data/lib/delayed/version.rb +1 -1
- data/lib/delayed/work_queue/in_process.rb +21 -17
- data/lib/delayed/work_queue/parent_process/client.rb +55 -53
- data/lib/delayed/work_queue/parent_process/server.rb +245 -207
- data/lib/delayed/work_queue/parent_process.rb +52 -53
- data/lib/delayed/worker/consul_health_check.rb +32 -33
- data/lib/delayed/worker/health_check.rb +34 -26
- data/lib/delayed/worker/null_health_check.rb +3 -1
- data/lib/delayed/worker/process_helper.rb +8 -9
- data/lib/delayed/worker.rb +272 -241
- data/lib/delayed/yaml_extensions.rb +12 -10
- data/lib/delayed_job.rb +37 -37
- data/lib/inst-jobs.rb +1 -1
- data/spec/active_record_job_spec.rb +143 -139
- data/spec/delayed/cli_spec.rb +7 -7
- data/spec/delayed/daemon_spec.rb +10 -9
- data/spec/delayed/message_sending_spec.rb +16 -9
- data/spec/delayed/periodic_spec.rb +14 -21
- data/spec/delayed/server_spec.rb +38 -38
- data/spec/delayed/settings_spec.rb +26 -25
- data/spec/delayed/work_queue/in_process_spec.rb +7 -8
- data/spec/delayed/work_queue/parent_process/client_spec.rb +17 -12
- data/spec/delayed/work_queue/parent_process/server_spec.rb +117 -41
- data/spec/delayed/work_queue/parent_process_spec.rb +21 -23
- data/spec/delayed/worker/consul_health_check_spec.rb +37 -50
- data/spec/delayed/worker/health_check_spec.rb +60 -52
- data/spec/delayed/worker_spec.rb +44 -21
- data/spec/sample_jobs.rb +45 -15
- data/spec/shared/delayed_batch.rb +74 -67
- data/spec/shared/delayed_method.rb +143 -102
- data/spec/shared/performable_method.rb +39 -38
- data/spec/shared/shared_backend.rb +550 -437
- data/spec/shared/testing.rb +14 -14
- data/spec/shared/worker.rb +156 -148
- data/spec/shared_jobs_specs.rb +13 -13
- data/spec/spec_helper.rb +53 -55
- metadata +148 -82
- data/lib/delayed/backend/redis/bulk_update.lua +0 -50
- data/lib/delayed/backend/redis/destroy_job.lua +0 -2
- data/lib/delayed/backend/redis/enqueue.lua +0 -29
- data/lib/delayed/backend/redis/fail_job.lua +0 -5
- data/lib/delayed/backend/redis/find_available.lua +0 -3
- data/lib/delayed/backend/redis/functions.rb +0 -59
- data/lib/delayed/backend/redis/get_and_lock_next_available.lua +0 -17
- data/lib/delayed/backend/redis/includes/jobs_common.lua +0 -203
- data/lib/delayed/backend/redis/job.rb +0 -535
- data/lib/delayed/backend/redis/set_running.lua +0 -5
- data/lib/delayed/backend/redis/tickle_strand.lua +0 -2
- data/spec/gemfiles/42.gemfile +0 -7
- data/spec/gemfiles/50.gemfile +0 -7
- data/spec/gemfiles/51.gemfile +0 -7
- data/spec/gemfiles/52.gemfile +0 -7
- data/spec/gemfiles/60.gemfile +0 -7
- data/spec/redis_job_spec.rb +0 -148
data/lib/delayed/daemon.rb
CHANGED
@@ -1,97 +1,93 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "fileutils"
|
4
4
|
|
5
5
|
module Delayed
|
6
|
-
# Daemon controls the parent proces that runs the Pool and monitors the Worker processes.
|
7
|
-
class Daemon
|
8
|
-
|
6
|
+
# Daemon controls the parent proces that runs the Pool and monitors the Worker processes.
|
7
|
+
class Daemon
|
8
|
+
attr_reader :pid_folder
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
def initialize(pid_folder)
|
11
|
+
@pid_folder = pid_folder
|
12
|
+
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
def status(print: true, pid: self.pid)
|
15
|
+
alive = pid && (Process.kill(0, pid) rescue false) && :running
|
16
|
+
alive ||= :draining if pid && Process.kill(0, -pid) rescue false
|
17
|
+
if alive
|
18
|
+
puts "Delayed jobs #{alive}, pool PID: #{pid}" if print
|
19
|
+
elsif print && print != :alive
|
20
|
+
puts "No delayed jobs pool running"
|
21
|
+
end
|
22
|
+
alive
|
21
23
|
end
|
22
|
-
alive
|
23
|
-
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
def daemonize!
|
26
|
+
FileUtils.mkdir_p(pid_folder)
|
27
|
+
puts "Daemonizing..."
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
exit if fork
|
30
|
+
Process.setsid
|
31
|
+
exit if fork
|
32
|
+
Process.setpgrp
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
lock_file.puts(Process.pid.to_s)
|
42
|
-
lock_file.flush
|
34
|
+
@daemon = true
|
35
|
+
lock_file = File.open(pid_file, "wb")
|
36
|
+
# someone else is already running; just exit
|
37
|
+
exit unless lock_file.flock(File::LOCK_EX | File::LOCK_NB)
|
38
|
+
at_exit { lock_file.flock(File::LOCK_UN) }
|
39
|
+
lock_file.puts(Process.pid.to_s)
|
40
|
+
lock_file.flush
|
43
41
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
# if we blow up so badly that we can't syslog the error, try to send
|
43
|
+
# it somewhere useful
|
44
|
+
last_ditch_logfile = Settings.last_ditch_logfile || "log/delayed_job.log"
|
45
|
+
last_ditch_logfile = Settings.expand_rails_path(last_ditch_logfile) if last_ditch_logfile[0] != "|"
|
46
|
+
$stdin.reopen("/dev/null")
|
47
|
+
$stdout.reopen(open(last_ditch_logfile, "a")) # rubocop:disable Security/Open
|
48
|
+
$stderr.reopen($stdout)
|
49
|
+
$stdout.sync = $stderr.sync = true
|
49
50
|
end
|
50
|
-
STDIN.reopen("/dev/null")
|
51
|
-
STDOUT.reopen(open(last_ditch_logfile, 'a'))
|
52
|
-
STDERR.reopen(STDOUT)
|
53
|
-
STDOUT.sync = STDERR.sync = true
|
54
|
-
end
|
55
51
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
52
|
+
# stop the currently running daemon (not this current process, the one in the pid_file)
|
53
|
+
def stop(kill: false, pid: self.pid)
|
54
|
+
alive = status(pid: pid, print: false)
|
55
|
+
if alive == :running || (kill && alive == :draining)
|
56
|
+
puts "Stopping pool #{pid}..."
|
57
|
+
signal = kill ? "TERM" : "QUIT"
|
58
|
+
begin
|
59
|
+
Process.kill(signal, pid)
|
60
|
+
rescue Errno::ESRCH
|
61
|
+
# ignore if the pid no longer exists
|
62
|
+
end
|
63
|
+
wait(kill)
|
64
|
+
else
|
65
|
+
status
|
66
66
|
end
|
67
|
-
wait(kill)
|
68
|
-
else
|
69
|
-
status
|
70
67
|
end
|
71
|
-
end
|
72
68
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
def wait(kill)
|
70
|
+
if kill
|
71
|
+
sleep(0.5) while status(pid: pid, print: false)
|
72
|
+
else
|
73
|
+
sleep(0.5) while status(pid: pid, print: false) == :running
|
74
|
+
end
|
78
75
|
end
|
79
|
-
end
|
80
76
|
|
81
|
-
|
82
|
-
|
83
|
-
|
77
|
+
def pid_file
|
78
|
+
File.join(pid_folder, "delayed_jobs_pool.pid")
|
79
|
+
end
|
84
80
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
81
|
+
def pid
|
82
|
+
if File.file?(pid_file)
|
83
|
+
pid = File.read(pid_file).to_i
|
84
|
+
pid = nil unless pid.positive?
|
85
|
+
end
|
86
|
+
pid
|
89
87
|
end
|
90
|
-
pid
|
91
|
-
end
|
92
88
|
|
93
|
-
|
94
|
-
|
89
|
+
def daemonized?
|
90
|
+
!!@daemon
|
91
|
+
end
|
95
92
|
end
|
96
93
|
end
|
97
|
-
end
|
data/lib/delayed/job_tracking.rb
CHANGED
@@ -1,33 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Delayed
|
4
|
-
# Used when a block of code wants to track what jobs are created,
|
5
|
-
# for instance in tests.
|
6
|
-
# Delayed::Job.track_jobs { ...block... } returns a JobTracking object
|
7
|
-
# Right now this just tracks created jobs, it could be expanded to track a
|
8
|
-
# lot more about what's going on in Delayed Jobs as it's needed.
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
# Used when a block of code wants to track what jobs are created,
|
5
|
+
# for instance in tests.
|
6
|
+
# Delayed::Job.track_jobs { ...block... } returns a JobTracking object
|
7
|
+
# Right now this just tracks created jobs, it could be expanded to track a
|
8
|
+
# lot more about what's going on in Delayed Jobs as it's needed.
|
9
|
+
JobTracking = Struct.new(:created) do
|
10
|
+
def self.track
|
11
|
+
@current_tracking = new
|
12
|
+
yield
|
13
|
+
tracking = @current_tracking
|
14
|
+
@current_tracking = nil
|
15
|
+
tracking
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def self.job_created(job)
|
19
|
+
@current_tracking.try(:job_created, job)
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
@lock.synchronize { self.created << job }
|
25
|
-
end
|
22
|
+
def job_created(job)
|
23
|
+
return unless job
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
@lock.synchronize { created << job }
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
super
|
30
|
+
self.created = []
|
31
|
+
@lock = Mutex.new
|
32
|
+
end
|
31
33
|
end
|
32
34
|
end
|
33
|
-
end
|
data/lib/delayed/lifecycle.rb
CHANGED
@@ -1,28 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Delayed
|
4
|
-
class InvalidCallback <
|
4
|
+
class InvalidCallback < RuntimeError; end
|
5
5
|
|
6
6
|
class Lifecycle
|
7
7
|
EVENTS = {
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
|
8
|
+
error: %i[worker job exception],
|
9
|
+
exceptional_exit: %i[worker exception],
|
10
|
+
execute: [:worker],
|
11
|
+
invoke_job: [:job],
|
12
|
+
loop: [:worker],
|
13
|
+
perform: %i[worker job],
|
14
|
+
pop: [:worker],
|
15
|
+
retry: %i[worker job exception],
|
16
|
+
work_queue_pop: %i[work_queue worker_config],
|
17
|
+
check_for_work: [:work_queue]
|
18
|
+
}.freeze
|
18
19
|
|
19
20
|
def initialize
|
20
21
|
reset!
|
21
22
|
end
|
22
23
|
|
23
24
|
def reset!
|
24
|
-
@callbacks = EVENTS.keys.
|
25
|
-
|
25
|
+
@callbacks = EVENTS.keys.each_with_object({}) do |e, hash|
|
26
|
+
hash[e] = Callback.new
|
27
|
+
hash
|
28
|
+
end
|
29
|
+
Delayed::Worker.plugins.each(&:reset!)
|
26
30
|
end
|
27
31
|
|
28
32
|
def before(event, &block)
|
@@ -38,7 +42,7 @@ module Delayed
|
|
38
42
|
end
|
39
43
|
|
40
44
|
def run_callbacks(event, *args, &block)
|
41
|
-
missing_callback(event) unless @callbacks.
|
45
|
+
missing_callback(event) unless @callbacks.key?(event)
|
42
46
|
|
43
47
|
unless EVENTS[event].size == args.size
|
44
48
|
raise ArgumentError, "Callback #{event} expects #{EVENTS[event].size} parameter(s): #{EVENTS[event].join(', ')}"
|
@@ -49,15 +53,15 @@ module Delayed
|
|
49
53
|
|
50
54
|
private
|
51
55
|
|
52
|
-
|
53
|
-
|
56
|
+
def add(type, event, &block)
|
57
|
+
missing_callback(event) unless @callbacks.key?(event)
|
54
58
|
|
55
|
-
|
56
|
-
|
59
|
+
@callbacks[event].add(type, &block)
|
60
|
+
end
|
57
61
|
|
58
|
-
|
59
|
-
|
60
|
-
|
62
|
+
def missing_callback(event)
|
63
|
+
raise InvalidCallback, "Unknown callback event: #{event}"
|
64
|
+
end
|
61
65
|
end
|
62
66
|
|
63
67
|
class Callback
|
@@ -66,7 +70,7 @@ module Delayed
|
|
66
70
|
@after = []
|
67
71
|
|
68
72
|
# Identity proc. Avoids special cases when there is no existing around chain.
|
69
|
-
@around =
|
73
|
+
@around = ->(*args, &block) { block.call(*args) }
|
70
74
|
end
|
71
75
|
|
72
76
|
def execute(*args, &block)
|
@@ -84,7 +88,7 @@ module Delayed
|
|
84
88
|
@after << callback
|
85
89
|
when :around
|
86
90
|
chain = @around # use a local variable so that the current chain is closed over in the following lambda
|
87
|
-
@around =
|
91
|
+
@around = ->(*a, &block) { chain.call(*a) { |*b| callback.call(*b, &block) } }
|
88
92
|
else
|
89
93
|
raise InvalidCallback, "Invalid callback type: #{type}"
|
90
94
|
end
|
data/lib/delayed/log_tailer.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Delayed
|
4
|
-
class LogTailer
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
4
|
+
class LogTailer
|
5
|
+
def run
|
6
|
+
if Rails.logger.respond_to?(:log_path)
|
7
|
+
log_path = Rails.logger.log_path
|
8
|
+
elsif Rails.logger.instance_variable_get("@logdev").try(:instance_variable_get, "@dev").try(:path)
|
9
|
+
log_path = Rails.logger.instance_variable_get("@logdev").instance_variable_get("@dev").path
|
10
|
+
else
|
11
|
+
return
|
12
|
+
end
|
13
|
+
Rails.logger.auto_flushing = true if Rails.logger.respond_to?(:auto_flushing=)
|
14
|
+
Thread.new do
|
15
|
+
f = File.open(log_path, "r")
|
16
|
+
f.seek(0, IO::SEEK_END)
|
17
|
+
loop do
|
18
|
+
content = f.read
|
19
|
+
content.present? ? $stdout.print(content) : sleep(0.5)
|
20
|
+
end
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
24
|
-
end
|
data/lib/delayed/logging.rb
CHANGED
@@ -1,30 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "date"
|
4
4
|
|
5
5
|
module Delayed
|
6
6
|
module Logging
|
7
|
-
TIMESTAMP_FORMAT =
|
7
|
+
TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%S.%6N"
|
8
8
|
private_constant :TIMESTAMP_FORMAT
|
9
9
|
|
10
|
-
FORMAT =
|
10
|
+
FORMAT = "%s - %s"
|
11
11
|
private_constant :FORMAT
|
12
12
|
|
13
|
-
|
14
13
|
def self.logger
|
15
14
|
return @logger if @logger
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
15
|
+
|
16
|
+
@logger = if defined?(Rails.logger) && Rails.logger
|
17
|
+
Rails.logger
|
18
|
+
else
|
19
|
+
::Logger.new($stdout).tap do |logger|
|
20
|
+
logger.formatter = lambda { |_, time, _, msg|
|
21
|
+
format(FORMAT, time.strftime(TIMESTAMP_FORMAT), msg)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
28
25
|
end
|
29
26
|
|
30
27
|
def logger
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
if ::Rails.env.test? || ::Rails.env.development?
|
4
|
-
require 'debug_inspector'
|
5
|
-
end
|
3
|
+
require "debug_inspector" if ::Rails.env.test? || ::Rails.env.development?
|
6
4
|
|
7
5
|
module Delayed
|
8
6
|
module MessageSending
|
@@ -14,12 +12,12 @@ module Delayed
|
|
14
12
|
@sender = sender
|
15
13
|
end
|
16
14
|
|
17
|
-
def method_missing(method, *args, **kwargs)
|
15
|
+
def method_missing(method, *args, **kwargs) # rubocop:disable Style/MissingRespondToMissing
|
18
16
|
# method doesn't exist? must be method_missing; assume private access
|
19
17
|
@sender = nil if !@sender.nil? &&
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
@object.methods.exclude?(method) &&
|
19
|
+
@object.protected_methods.exclude?(method) &&
|
20
|
+
@object.private_methods.exclude?(method)
|
23
21
|
|
24
22
|
sender_is_object = @sender == @object
|
25
23
|
sender_is_class = @sender.is_a?(@object.class)
|
@@ -33,51 +31,47 @@ module Delayed
|
|
33
31
|
end
|
34
32
|
|
35
33
|
if @synchronous
|
36
|
-
if @sender.nil? || sender_is_object || sender_is_class && @object.protected_methods.include?(method)
|
37
|
-
if kwargs.empty?
|
38
|
-
|
39
|
-
|
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)
|
34
|
+
if @sender.nil? || sender_is_object || (sender_is_class && @object.protected_methods.include?(method))
|
35
|
+
return @object.send(method, *args) if kwargs.empty?
|
36
|
+
|
37
|
+
return @object.send(method, *args, **kwargs)
|
48
38
|
end
|
39
|
+
|
40
|
+
return @object.public_send(method, *args) if kwargs.empty?
|
41
|
+
|
42
|
+
return @object.public_send(method, *args, **kwargs)
|
49
43
|
end
|
50
44
|
|
51
45
|
ignore_transaction = @enqueue_args.delete(:ignore_transaction)
|
52
46
|
on_failure = @enqueue_args.delete(:on_failure)
|
53
47
|
on_permanent_failure = @enqueue_args.delete(:on_permanent_failure)
|
54
|
-
|
48
|
+
unless ignore_transaction
|
55
49
|
# delay queuing up the job in another database until the results of the current
|
56
50
|
# transaction are visible
|
57
51
|
connection = @object.class.connection if @object.class.respond_to?(:connection)
|
58
52
|
connection ||= @object.connection if @object.respond_to?(:connection)
|
59
53
|
connection ||= ::ActiveRecord::Base.connection
|
60
54
|
|
61
|
-
if
|
55
|
+
if ::Delayed::Job != ::Delayed::Backend::ActiveRecord::Job || connection != ::Delayed::Job.connection
|
62
56
|
connection.after_transaction_commit do
|
63
57
|
::Delayed::Job.enqueue(::Delayed::PerformableMethod.new(@object, method,
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
58
|
+
args: args, kwargs: kwargs,
|
59
|
+
on_failure: on_failure,
|
60
|
+
on_permanent_failure: on_permanent_failure,
|
61
|
+
sender: @sender),
|
62
|
+
**@enqueue_args)
|
69
63
|
end
|
70
64
|
return nil
|
71
65
|
end
|
72
66
|
end
|
73
67
|
|
74
68
|
result = ::Delayed::Job.enqueue(::Delayed::PerformableMethod.new(@object, method,
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
69
|
+
args: args,
|
70
|
+
kwargs: kwargs,
|
71
|
+
on_failure: on_failure,
|
72
|
+
on_permanent_failure: on_permanent_failure,
|
73
|
+
sender: @sender),
|
74
|
+
**@enqueue_args)
|
81
75
|
result = nil unless ignore_transaction
|
82
76
|
result
|
83
77
|
end
|
@@ -85,10 +79,8 @@ module Delayed
|
|
85
79
|
|
86
80
|
def delay(sender: nil, **enqueue_args)
|
87
81
|
# support procs/methods as enqueue arguments
|
88
|
-
enqueue_args.each do |k,v|
|
89
|
-
if v.respond_to?(:call)
|
90
|
-
enqueue_args[k] = v.call(self)
|
91
|
-
end
|
82
|
+
enqueue_args.each do |k, v|
|
83
|
+
enqueue_args[k] = v.call(self) if v.respond_to?(:call)
|
92
84
|
end
|
93
85
|
|
94
86
|
sender ||= __calculate_sender_for_delay
|
@@ -103,33 +95,32 @@ module Delayed
|
|
103
95
|
end
|
104
96
|
|
105
97
|
module ClassMethods
|
106
|
-
KWARG_ARG_TYPES = %i
|
98
|
+
KWARG_ARG_TYPES = %i[key keyreq keyrest].freeze
|
107
99
|
private_constant :KWARG_ARG_TYPES
|
108
100
|
|
109
101
|
def handle_asynchronously(method_name, **enqueue_args)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
if has_kwargs? method_name
|
102
|
+
visibility = if public_method_defined?(method_name)
|
103
|
+
:public
|
104
|
+
elsif private_method_defined?(method_name)
|
105
|
+
:private
|
106
|
+
else
|
107
|
+
:protected
|
108
|
+
end
|
109
|
+
|
110
|
+
if kwargs? method_name
|
121
111
|
generated_delayed_methods.class_eval do
|
122
|
-
define_method(method_name,
|
112
|
+
define_method(method_name, lambda do |*args, synchronous: false, **kwargs|
|
123
113
|
if synchronous
|
124
114
|
super(*args, **kwargs)
|
125
115
|
else
|
126
|
-
delay(sender: __calculate_sender_for_delay, **enqueue_args)
|
116
|
+
delay(sender: __calculate_sender_for_delay, **enqueue_args)
|
117
|
+
.method_missing(method_name, *args, synchronous: true, **kwargs)
|
127
118
|
end
|
128
119
|
end)
|
129
120
|
end
|
130
121
|
else
|
131
122
|
generated_delayed_methods.class_eval do
|
132
|
-
define_method(method_name,
|
123
|
+
define_method(method_name, lambda do |*args, synchronous: false|
|
133
124
|
if synchronous
|
134
125
|
super(*args)
|
135
126
|
else
|
@@ -150,7 +141,7 @@ module Delayed
|
|
150
141
|
end
|
151
142
|
end
|
152
143
|
|
153
|
-
def
|
144
|
+
def kwargs?(method_name)
|
154
145
|
original_arg_types = instance_method(method_name).parameters.map(&:first)
|
155
146
|
original_arg_types.any? { |arg_type| KWARG_ARG_TYPES.include?(arg_type) }
|
156
147
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Delayed
|
4
|
-
|
4
|
+
PerformableMethod = Struct.new(:object, :method, :args, :kwargs, :fail_cb, :permanent_fail_cb, :sender) do # rubocop:disable Lint/StructNewOverride
|
5
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
|
|
@@ -35,18 +35,16 @@ module Delayed
|
|
35
35
|
sender_is_object = sender == object
|
36
36
|
sender_is_class = sender.is_a?(object.class)
|
37
37
|
|
38
|
-
if sender.nil? || sender_is_object || sender_is_class && object.protected_methods.include?(method)
|
38
|
+
if sender.nil? || sender_is_object || (sender_is_class && object.protected_methods.include?(method))
|
39
39
|
if kwargs.empty?
|
40
40
|
object.send(method, *args)
|
41
41
|
else
|
42
42
|
object.send(method, *args, **kwargs)
|
43
43
|
end
|
44
|
+
elsif kwargs.empty?
|
45
|
+
object.public_send(method, *args)
|
44
46
|
else
|
45
|
-
|
46
|
-
object.public_send(method, *args)
|
47
|
-
else
|
48
|
-
object.public_send(method, *args, **kwargs)
|
49
|
-
end
|
47
|
+
object.public_send(method, *args, **kwargs)
|
50
48
|
end
|
51
49
|
end
|
52
50
|
|
@@ -74,7 +72,7 @@ module Delayed
|
|
74
72
|
def full_name
|
75
73
|
obj_name = object.is_a?(ActiveRecord::Base) ? "#{object.class}.find(#{object.id}).#{method}" : display_name
|
76
74
|
kgs = kwargs || {}
|
77
|
-
kwargs_str = kgs.map { |(k, v)| ", #{k}: #{deep_de_ar_ize(v)}"}.join
|
75
|
+
kwargs_str = kgs.map { |(k, v)| ", #{k}: #{deep_de_ar_ize(v)}" }.join
|
78
76
|
"#{obj_name}(#{args.map { |a| deep_de_ar_ize(a) }.join(', ')}#{kwargs_str})"
|
79
77
|
end
|
80
78
|
end
|