skiplock 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -5
- data/lib/skiplock.rb +5 -4
- data/lib/skiplock/dispatcher.rb +40 -15
- data/lib/skiplock/job.rb +15 -4
- data/lib/skiplock/manager.rb +56 -27
- data/lib/skiplock/version.rb +1 -1
- metadata +2 -3
- data/lib/skiplock/notification.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8155870e392d0172d914c5e10d981560eb05af653603d331ce46cdd3419b2efa
|
4
|
+
data.tar.gz: 940699344273b928820c22307d6cea654d4bdad6debfa80c67fbb28dc8490ea9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa423c44556fb2a31cc2ec6cf9f25d6c9712b460920a0d39d0108ade11fa7738fe24e8f1857236cd0a67042ac6ced5cb0b1c34774e8946b72fe971e3202426f7
|
7
|
+
data.tar.gz: ac5456a0613ad3d94e574de100ee26dd018bee39c2a74c16237c798b873a45798519c33b08cb05a26ab18415e15b87252699e2b4bf1978fffbc521008fccdffe
|
data/README.md
CHANGED
@@ -54,7 +54,11 @@ The library is quite small compared to other PostgreSQL job queues (eg. *delay_j
|
|
54
54
|
min_threads: 1
|
55
55
|
max_threads: 5
|
56
56
|
max_retries: 20
|
57
|
+
notification: auto
|
57
58
|
purge_completion: true
|
59
|
+
queues:
|
60
|
+
default: 200
|
61
|
+
mailers: 100
|
58
62
|
workers: 0
|
59
63
|
```
|
60
64
|
Available configuration options are:
|
@@ -62,8 +66,10 @@ The library is quite small compared to other PostgreSQL job queues (eg. *delay_j
|
|
62
66
|
- **min_threads** (*integer*): sets minimum number of threads staying idle
|
63
67
|
- **max_threads** (*integer*): sets the maximum number of threads allowed to run jobs
|
64
68
|
- **max_retries** (*integer*): sets the maximum attempt a job will be retrying before it is marked expired (see Retry System for more details)
|
69
|
+
- **notification** (*enumeration*): sets the library to be used for notifying errors and exceptions (`auto, airbrake, bugsnag, exception_notification, false`)
|
65
70
|
- **purge_completion** (*boolean*): when set to **true** will delete jobs after they were completed successfully; if set to **false** then the completed jobs should be purged periodically to maximize performance (eg. clean up old jobs after 3 months)
|
66
|
-
- **
|
71
|
+
- **queues** (*hash*): defines the set of queues with priorites; lower priority takes precedence
|
72
|
+
- **workers** (*integer*) sets the maximum number of processes when running in standalone mode using the `skiplock` executable; setting this to **0** will enable **async mode**
|
67
73
|
|
68
74
|
#### Async mode
|
69
75
|
When **workers** is set to **0** then the jobs will be performed in the web server process using separate threads. If using multi-worker cluster web server like Puma, then it should be configured as below:
|
@@ -93,16 +99,22 @@ The library is quite small compared to other PostgreSQL job queues (eg. *delay_j
|
|
93
99
|
```
|
94
100
|
- Skiplock supports all ActiveJob features:
|
95
101
|
```ruby
|
96
|
-
MyJob.set(wait: 5.minutes, priority: 10).perform_later(1,2,3)
|
102
|
+
MyJob.set(queue: 'my_queue', wait: 5.minutes, priority: 10).perform_later(1,2,3)
|
97
103
|
```
|
98
104
|
- Outside of Rails application, queue the jobs by inserting the job records directly to the database table eg:
|
99
105
|
```sql
|
100
106
|
INSERT INTO skiplock.jobs(job_class) VALUES ('MyJob');
|
101
107
|
```
|
102
|
-
- Or with scheduling, priority and arguments:
|
108
|
+
- Or with scheduling, priority, queue and arguments:
|
103
109
|
```sql
|
104
|
-
INSERT INTO skiplock.jobs(job_class,priority,scheduled_at,data) VALUES ('MyJob',10,NOW()+INTERVAL '5 min','{"arguments":[1,2,3]}');
|
110
|
+
INSERT INTO skiplock.jobs(job_class,queue_name,priority,scheduled_at,data) VALUES ('MyJob','my_queue',10,NOW()+INTERVAL '5 min','{"arguments":[1,2,3]}');
|
105
111
|
```
|
112
|
+
## Queues priority vs Job priority
|
113
|
+
*Why do queues have priorities when jobs already have priorities?*
|
114
|
+
- Jobs are only prioritized with other jobs from the same queue
|
115
|
+
- Queues, on the other hand, are prioritized with other queues
|
116
|
+
- Rails has built-in queues that dispatches jobs without priorities (eg. Mail Delivery will queue as **mailers** with no priority)
|
117
|
+
|
106
118
|
## Cron system
|
107
119
|
`Skiplock` provides the capability to setup cron jobs for running tasks periodically. It fully supports the cron syntax to specify the frequency of the jobs. To setup a cron job, simply assign a valid cron schedule to the constant `CRON` for the Job Class.
|
108
120
|
- setup `MyJob` to run as cron job every hour at 30 minutes past
|
@@ -144,7 +156,16 @@ Once the retry attempt limit configured in ActiveJob has been reached, the contr
|
|
144
156
|
If the rescue blocks are not defined, then the built-in retry system of `skiplock` will kick in automatically. The retrying schedule is using an exponential formula (5 + 2**attempt). The `skiplock` configuration `max_retries` determines the the limit of attempts before the failing job is marked as expired. The maximum retry limit can be set as high as 20; this allows up to 12 days of retrying before the job is marked as expired.
|
145
157
|
|
146
158
|
## Notification system
|
147
|
-
|
159
|
+
`Skiplock` can use existing exception notification library to notify errors and exceptions. It supports `airbrake`, `bugsnag`, and `exception_notification`. A customized function can also be called whenever an exception occurs; this can be configured in an initializer as below:
|
160
|
+
```ruby
|
161
|
+
# config/initializers/skiplock.rb
|
162
|
+
Skiplock.on_error = -> (ex, previous = nil) do
|
163
|
+
if ex.backtrace != previous.try(:backtrace)
|
164
|
+
# sends custom email on new exceptions only
|
165
|
+
# the same repeated exceptions will only be sent once to avoid SPAM
|
166
|
+
end
|
167
|
+
end
|
168
|
+
```
|
148
169
|
|
149
170
|
## Contributing
|
150
171
|
|
data/lib/skiplock.rb
CHANGED
@@ -4,22 +4,23 @@ require 'active_record'
|
|
4
4
|
require 'skiplock/cron'
|
5
5
|
require 'skiplock/dispatcher'
|
6
6
|
require 'skiplock/manager'
|
7
|
-
require 'skiplock/notification'
|
8
7
|
require 'skiplock/job'
|
9
8
|
require 'skiplock/worker'
|
10
9
|
require 'skiplock/version'
|
11
10
|
|
12
11
|
module Skiplock
|
13
12
|
Settings = {
|
14
|
-
'logging' =>
|
13
|
+
'logging' => 'timestamp',
|
15
14
|
'min_threads' => 1,
|
16
15
|
'max_threads' => 5,
|
17
16
|
'max_retries' => 20,
|
17
|
+
'notification' => 'auto',
|
18
18
|
'purge_completion' => true,
|
19
19
|
'queues' => {
|
20
|
-
'default' =>
|
21
|
-
'mailers' =>
|
20
|
+
'default' => 200,
|
21
|
+
'mailers' => 100
|
22
22
|
},
|
23
23
|
'workers' => 0
|
24
24
|
}
|
25
|
+
mattr_accessor :on_error
|
25
26
|
end
|
data/lib/skiplock/dispatcher.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Skiplock
|
2
2
|
class Dispatcher
|
3
3
|
def initialize(master: true, worker_num: nil, worker_pids: [])
|
4
|
-
@queues_order_query =
|
4
|
+
@queues_order_query = Settings['queues'].map { |q,v| "WHEN queue_name = '#{q}' THEN #{v}" }.join(' ') if Settings['queues'].is_a?(Hash) && Settings['queues'].count > 0
|
5
5
|
@executor = Concurrent::ThreadPoolExecutor.new(min_threads: Settings['min_threads'], max_threads: Settings['max_threads'], max_queue: Settings['max_threads'], idletime: 60, auto_terminate: true, fallback_policy: :discard)
|
6
6
|
@master = master
|
7
7
|
if @master
|
@@ -17,19 +17,28 @@ module Skiplock
|
|
17
17
|
Thread.new do
|
18
18
|
Rails.application.reloader.wrap do
|
19
19
|
sleep(0.1) while @running && !Rails.application.initialized?
|
20
|
-
Process.setproctitle("skiplock-#{@master ? 'master' : 'worker[' + @worker_num.to_s + ']'}") if Settings['workers'] > 0
|
20
|
+
Process.setproctitle("skiplock-#{@master ? 'master[0]' : 'worker[' + @worker_num.to_s + ']'}") if Settings['workers'] > 0
|
21
21
|
ActiveRecord::Base.connection_pool.with_connection do |connection|
|
22
22
|
connection.exec_query('LISTEN "skiplock::jobs"')
|
23
|
-
hostname = `hostname`.strip
|
23
|
+
hostname = `hostname -f`.strip
|
24
24
|
@worker = Worker.create!(pid: Process.pid, ppid: (@master ? nil : Process.ppid), capacity: Settings['max_threads'], hostname: hostname)
|
25
25
|
if @master
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
if File.exists?('tmp/cache/skiplock')
|
27
|
+
# get performed jobs that could not sync with database
|
28
|
+
job_ids = File.read('tmp/cache/skiplock').split("\n")
|
29
|
+
if Settings['purge_completion']
|
30
|
+
Job.where(id: job_ids, running: true).delete_all
|
31
|
+
else
|
32
|
+
Job.where(id: job_ids, running: true).update_all(running: false, finished_at: File.mtime('tmp/cache/skiplock'))
|
33
|
+
end
|
34
|
+
File.delete('tmp/cache/skiplock')
|
32
35
|
end
|
36
|
+
# get current worker ids
|
37
|
+
worker_ids = Worker.where(hostname: hostname, pid: @worker_pids).ids
|
38
|
+
# reset orphaned jobs of the dead worker ids for retry
|
39
|
+
Job.where(running: true).where.not(worker_id: worker_ids).update_all(running: false, worker_id: nil)
|
40
|
+
# remove workers that were not shutdown properly on the host
|
41
|
+
Worker.where(hostname: hostname).where.not(pid: @worker_pids).delete_all
|
33
42
|
# reset retries schedules on startup
|
34
43
|
Job.where('scheduled_at > NOW() AND executions IS NOT NULL AND expired_at IS NULL AND finished_at IS NULL').update_all(scheduled_at: nil, updated_at: Time.now)
|
35
44
|
Cron.setup
|
@@ -46,6 +55,17 @@ module Skiplock
|
|
46
55
|
end
|
47
56
|
error = false
|
48
57
|
end
|
58
|
+
if Job::Errors.keys.count > 0
|
59
|
+
completed_ids = Job::Errors.keys.map { |k| k if Job::Errors[k] }.compact
|
60
|
+
if Settings['purge_completion'] && completed_ids.count > 0
|
61
|
+
Job.where(id: completed_ids, running: true).delete_all
|
62
|
+
elsif completed_ids.count > 0
|
63
|
+
Job.where(id: completed_ids, running: true).update_all(running: false, finished_at: Time.now)
|
64
|
+
end
|
65
|
+
orphaned_ids = Job::Errors.keys.map { |k| k unless Job::Errors[k] }.compact
|
66
|
+
Job.where(id: orphaned_ids, running: true).update_all(running: false, worker_id: nil, scheduled_at: (Time.now + 10)) if orphaned_ids.count > 0
|
67
|
+
Job::Errors.clear
|
68
|
+
end
|
49
69
|
if Time.now.to_f >= @next_schedule_at && @executor.remaining_capacity > 0
|
50
70
|
@executor.post { do_work }
|
51
71
|
end
|
@@ -59,7 +79,7 @@ module Skiplock
|
|
59
79
|
end
|
60
80
|
notifications.each do |n|
|
61
81
|
op, id, worker_id, queue_name, running, expired_at, finished_at, scheduled_at = n.split(',')
|
62
|
-
next if op == 'DELETE' || running == 'true' || expired_at || finished_at
|
82
|
+
next if op == 'DELETE' || running == 'true' || expired_at.to_s.length > 0 || finished_at.to_s.length > 0
|
63
83
|
if scheduled_at.to_f <= Time.now.to_f
|
64
84
|
@next_schedule_at = Time.now.to_f
|
65
85
|
elsif scheduled_at.to_f < @next_schedule_at
|
@@ -68,15 +88,18 @@ module Skiplock
|
|
68
88
|
end
|
69
89
|
end
|
70
90
|
rescue Exception => ex
|
71
|
-
|
91
|
+
STDERR.puts ex.message
|
92
|
+
STDERR.puts ex.backtrace
|
93
|
+
Skiplock.on_error.call(ex, @last_exception) if Skiplock.on_error.is_a?(Proc)
|
72
94
|
error = true
|
73
95
|
t = Time.now
|
74
96
|
while @running
|
75
97
|
sleep(0.5)
|
76
98
|
break if Time.now - t > 5
|
77
99
|
end
|
100
|
+
@last_exception = ex
|
78
101
|
end
|
79
|
-
sleep(0.
|
102
|
+
sleep(0.2)
|
80
103
|
end
|
81
104
|
connection.exec_query('UNLISTEN *')
|
82
105
|
end
|
@@ -100,9 +123,11 @@ module Skiplock
|
|
100
123
|
@next_schedule_at = result if result.is_a?(Float)
|
101
124
|
break
|
102
125
|
end
|
103
|
-
rescue Exception =>
|
104
|
-
puts
|
105
|
-
|
126
|
+
rescue Exception => ex
|
127
|
+
STDERR.puts ex.message
|
128
|
+
STDERR.puts ex.backtrace
|
129
|
+
Skiplock.on_error.call(ex, @last_exception) if Skiplock.on_error.is_a?(Proc)
|
130
|
+
@last_exception = ex
|
106
131
|
end
|
107
132
|
end
|
108
133
|
end
|
data/lib/skiplock/job.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
module Skiplock
|
2
2
|
class Job < ActiveRecord::Base
|
3
3
|
self.table_name = 'skiplock.jobs'
|
4
|
+
Errors = Concurrent::Map.new
|
4
5
|
|
5
6
|
# Return: Skiplock::Job if it was executed; otherwise returns the next Job's schedule time in FLOAT
|
6
7
|
def self.dispatch(queues_order_query: nil, worker_id: nil)
|
8
|
+
performed = false
|
7
9
|
self.connection.exec_query('BEGIN')
|
8
|
-
job = self.find_by_sql("SELECT id, scheduled_at FROM #{self.table_name} WHERE running = FALSE AND expired_at IS NULL AND finished_at IS NULL ORDER BY scheduled_at ASC NULLS FIRST,#{queues_order_query ? 'CASE ' + queues_order_query + ' ELSE NULL END ASC NULLS LAST,' : ''} priority ASC NULLS LAST, created_at ASC FOR UPDATE SKIP LOCKED LIMIT 1").first
|
10
|
+
job = self.find_by_sql("SELECT id, scheduled_at FROM #{self.table_name} WHERE running = FALSE AND expired_at IS NULL AND finished_at IS NULL ORDER BY scheduled_at ASC NULLS FIRST,#{queues_order_query ? ' CASE ' + queues_order_query + ' ELSE NULL END ASC NULLS LAST,' : ''} priority ASC NULLS LAST, created_at ASC FOR UPDATE SKIP LOCKED LIMIT 1").first
|
9
11
|
if job.nil? || job.scheduled_at.to_f > Time.now.to_f
|
10
12
|
self.connection.exec_query('END')
|
11
13
|
return (job ? job.scheduled_at.to_f : Float::INFINITY)
|
@@ -21,9 +23,9 @@ module Skiplock
|
|
21
23
|
ActiveJob::Base.execute(job_data)
|
22
24
|
rescue Exception => ex
|
23
25
|
end
|
26
|
+
performed = true
|
24
27
|
job.running = false
|
25
28
|
if ex
|
26
|
-
# TODO: report exception
|
27
29
|
job.exception_executions["[#{ex.class.name}]"] = (job.exception_executions["[#{ex.class.name}]"] || 0) + 1 unless job.exception_executions.key?('activejob_retry')
|
28
30
|
if job.executions >= Settings['max_retries'] || job.exception_executions.key?('activejob_retry')
|
29
31
|
job.expired_at = Time.now
|
@@ -32,11 +34,12 @@ module Skiplock
|
|
32
34
|
job.scheduled_at = Time.now + (5 * 2**job.executions)
|
33
35
|
job.save!
|
34
36
|
end
|
37
|
+
Skiplock.on_error.call(ex) if Skiplock.on_error.is_a?(Proc) && (job.executions % 3 == 1)
|
35
38
|
elsif job.exception_executions.key?('activejob_retry')
|
36
39
|
job.save!
|
37
|
-
elsif job
|
40
|
+
elsif job.cron
|
38
41
|
job.data['last_cron_run'] = Time.now.utc.to_s
|
39
|
-
next_cron_at = Cron.next_schedule_at(job
|
42
|
+
next_cron_at = Cron.next_schedule_at(job.cron)
|
40
43
|
if next_cron_at
|
41
44
|
job.executions = 1
|
42
45
|
job.exception_executions = nil
|
@@ -53,6 +56,14 @@ module Skiplock
|
|
53
56
|
job.save!
|
54
57
|
end
|
55
58
|
job
|
59
|
+
rescue Exception => ex
|
60
|
+
if performed
|
61
|
+
Errors[job.id] = true
|
62
|
+
File.write('tmp/cache/skiplock', job.id + "\n", mode: 'a')
|
63
|
+
else
|
64
|
+
Errors[job.id] = false
|
65
|
+
end
|
66
|
+
raise ex
|
56
67
|
ensure
|
57
68
|
Thread.current[:skiplock_dispatch_job] = nil
|
58
69
|
end
|
data/lib/skiplock/manager.rb
CHANGED
@@ -1,7 +1,21 @@
|
|
1
1
|
module Skiplock
|
2
2
|
class Manager
|
3
|
-
def self.start(standalone: false)
|
4
|
-
|
3
|
+
def self.start(standalone: false, workers: nil, max_retries: nil, max_threads: nil, min_threads: nil, logging: nil)
|
4
|
+
unless Settings.frozen?
|
5
|
+
load_settings
|
6
|
+
Settings['logging'] = logging if logging
|
7
|
+
Settings['max_retries'] = max_retries if max_retries
|
8
|
+
Settings['max_threads'] = max_threads if max_threads
|
9
|
+
Settings['min_threads'] = min_threads if min_threads
|
10
|
+
Settings['workers'] = workers if workers
|
11
|
+
Settings['max_retries'] = 20 if Settings['max_retries'] > 20
|
12
|
+
Settings['max_retries'] = 0 if Settings['max_retries'] < 0
|
13
|
+
Settings['max_threads'] = 1 if Settings['max_threads'] < 1
|
14
|
+
Settings['max_threads'] = 20 if Settings['max_threads'] > 20
|
15
|
+
Settings['min_threads'] = 0 if Settings['min_threads'] < 0
|
16
|
+
Settings['workers'] = 0 if Settings['workers'] < 0
|
17
|
+
Settings.freeze
|
18
|
+
end
|
5
19
|
return unless standalone || (caller.any?{|l| l =~ %r{/rack/}} && (Settings['workers'] == 0 || Rails.env.development?))
|
6
20
|
if standalone
|
7
21
|
self.standalone
|
@@ -22,37 +36,37 @@ module Skiplock
|
|
22
36
|
private
|
23
37
|
|
24
38
|
def self.load_settings
|
25
|
-
return if Settings.frozen?
|
26
39
|
config = YAML.load_file('config/skiplock.yml') rescue {}
|
27
40
|
Settings.merge!(config)
|
28
|
-
Settings['
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
41
|
+
Settings['queues'].values.each { |v| raise 'Queue value must be an integer' unless v.is_a?(Integer) } if Settings['queues'].is_a?(Hash)
|
42
|
+
case Settings['notification'].to_s.downcase
|
43
|
+
when 'auto'
|
44
|
+
if defined?(Airbrake)
|
45
|
+
Skiplock.on_error = -> (ex, previous = nil) { Airbrake.notify_sync(ex) unless ex.backtrace == previous.try(:backtrace) }
|
46
|
+
elsif defined?(Bugsnag)
|
47
|
+
Skiplock.on_error = -> (ex, previous = nil) { Bugsnag.notify(ex) unless ex.backtrace == previous.try(:backtrace) }
|
48
|
+
elsif defined?(ExceptionNotifier)
|
49
|
+
Skiplock.on_error = -> (ex, previous = nil) { ExceptionNotifier.notify_exception(ex) unless ex.backtrace == previous.try(:backtrace) }
|
50
|
+
else
|
51
|
+
puts "Unable to detect any known exception notification gem. Please define custom 'on_error' function and disable notification in 'config/skiplock.yml'"
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
when 'airbrake'
|
55
|
+
raise 'airbrake gem not found' unless defined?(Airbrake)
|
56
|
+
Skiplock.on_error = -> (ex, previous = nil) { Airbrake.notify_sync(ex) unless ex.backtrace == previous.try(:backtrace) }
|
57
|
+
when 'bugsnag'
|
58
|
+
raise 'bugsnag gem not found' unless defined?(Bugsnag)
|
59
|
+
Skiplock.on_error = -> (ex, previous = nil) { Bugsnag.notify(ex) unless ex.backtrace == previous.try(:backtrace) }
|
60
|
+
when 'exception_notification'
|
61
|
+
raise 'exception_notification gem not found' unless defined?(ExceptionNotifier)
|
62
|
+
Skiplock.on_error = -> (ex, previous = nil) { ExceptionNotifier.notify_exception(ex) unless ex.backtrace == previous.try(:backtrace) }
|
63
|
+
end
|
36
64
|
rescue Exception => e
|
37
65
|
STDERR.puts "Invalid configuration 'config/skiplock.yml': #{e.message}"
|
38
66
|
exit
|
39
67
|
end
|
40
68
|
|
41
69
|
def self.standalone
|
42
|
-
title = "Skiplock version: #{Skiplock::VERSION} (Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
|
43
|
-
puts "-"*(title.length)
|
44
|
-
puts title
|
45
|
-
puts "-"*(title.length)
|
46
|
-
puts "Additional workers: #{Settings['workers']}"
|
47
|
-
puts " Purge completion: #{Settings['purge_completion']}"
|
48
|
-
puts " Max retries: #{Settings['max_retries']}"
|
49
|
-
puts " Min threads: #{Settings['min_threads']}"
|
50
|
-
puts " Max threads: #{Settings['max_threads']}"
|
51
|
-
puts " Environment: #{Rails.env}"
|
52
|
-
puts " Logging: #{Settings['logging']}"
|
53
|
-
puts " Queues: #{Settings['queues'].map {|k,v| k + '(' + v.to_s + ')'}.join(', ')}"
|
54
|
-
puts " PID: #{Process.pid}"
|
55
|
-
puts "-"*(title.length)
|
56
70
|
if Settings['logging']
|
57
71
|
log_timestamp = (Settings['logging'].to_s == 'timestamp')
|
58
72
|
logfile = File.open('log/skiplock.log', 'a')
|
@@ -66,14 +80,29 @@ module Skiplock
|
|
66
80
|
Rails.logger.reopen('/dev/null')
|
67
81
|
Rails.logger.extend(ActiveSupport::Logger.broadcast(logger))
|
68
82
|
end
|
83
|
+
title = "Skiplock version: #{Skiplock::VERSION} (Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
|
84
|
+
puts "-"*(title.length)
|
85
|
+
puts title
|
86
|
+
puts "-"*(title.length)
|
87
|
+
puts "Purge completion: #{Settings['purge_completion']}"
|
88
|
+
puts " Notification: #{Settings['notification']}"
|
89
|
+
puts " Max retries: #{Settings['max_retries']}"
|
90
|
+
puts " Min threads: #{Settings['min_threads']}"
|
91
|
+
puts " Max threads: #{Settings['max_threads']}"
|
92
|
+
puts " Environment: #{Rails.env}"
|
93
|
+
puts " Logging: #{Settings['logging']}"
|
94
|
+
puts " Workers: #{Settings['workers']}"
|
95
|
+
puts " Queues: #{Settings['queues'].map {|k,v| k + '(' + v.to_s + ')'}.join(', ')}" if Settings['queues'].is_a?(Hash)
|
96
|
+
puts " PID: #{Process.pid}"
|
97
|
+
puts "-"*(title.length)
|
69
98
|
parent_id = Process.pid
|
70
99
|
shutdown = false
|
71
100
|
Signal.trap("INT") { shutdown = true }
|
72
101
|
Signal.trap("TERM") { shutdown = true }
|
73
102
|
worker_pids = []
|
74
|
-
Settings['workers'].times do |n|
|
103
|
+
(Settings['workers']-1).times do |n|
|
75
104
|
worker_pids << fork do
|
76
|
-
dispatcher = Dispatcher.new(master: false, worker_num: n)
|
105
|
+
dispatcher = Dispatcher.new(master: false, worker_num: n+1)
|
77
106
|
thread = dispatcher.run
|
78
107
|
loop do
|
79
108
|
sleep 0.5
|
data/lib/skiplock/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skiplock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tin Vo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-03-
|
11
|
+
date: 2021-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|
@@ -86,7 +86,6 @@ files:
|
|
86
86
|
- lib/skiplock/dispatcher.rb
|
87
87
|
- lib/skiplock/job.rb
|
88
88
|
- lib/skiplock/manager.rb
|
89
|
-
- lib/skiplock/notification.rb
|
90
89
|
- lib/skiplock/version.rb
|
91
90
|
- lib/skiplock/worker.rb
|
92
91
|
homepage: https://github.com/vtt/skiplock
|