cuetip 1.4.1 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cuetip/config.rb +2 -1
- data/lib/cuetip/models/job.rb +64 -59
- data/lib/cuetip/version.rb +1 -1
- data/lib/cuetip/worker_group.rb +26 -19
- metadata +26 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 846dd406c3144f1548c2385b57854e02fc58a28c198557fbac1e5525390c4851
|
4
|
+
data.tar.gz: 4ccc211f14f69ebe8828ef6089bc5a4179672cdff7e8c91bf1199f30c9ab7893
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21def25a628be5d6698b8254093acc612fa68dc549a674e0b495f9c91dfcc82bb2d1bfa2a863830caf3009c8d41fd35724f66f1ec10a6c2a75d15a31688053f5
|
7
|
+
data.tar.gz: 073ad3cfca0e29f854df84bffbba65120302aa29ad6a2e3d0c258fa8c24ef648764e808f25e4bce9693a63016a8062a16c578606e40073b79df4283aba95af63
|
data/lib/cuetip/config.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'klogger'
|
3
4
|
require 'active_support'
|
4
5
|
require 'active_support/core_ext/numeric/bytes'
|
5
6
|
require 'active_support/core_ext/numeric/time'
|
@@ -20,7 +21,7 @@ module Cuetip
|
|
20
21
|
|
21
22
|
# Return the logger
|
22
23
|
def logger
|
23
|
-
@logger ||=
|
24
|
+
@logger ||= Klogger.new(:cuetip)
|
24
25
|
end
|
25
26
|
attr_writer :logger
|
26
27
|
|
data/lib/cuetip/models/job.rb
CHANGED
@@ -49,11 +49,11 @@ module Cuetip
|
|
49
49
|
def remove_from_queue
|
50
50
|
queued_job&.destroy
|
51
51
|
self.queued_job = nil
|
52
|
-
|
52
|
+
Cuetip.logger.debug 'Removed from queue'
|
53
53
|
|
54
54
|
if delete_after_execution?
|
55
55
|
destroy
|
56
|
-
|
56
|
+
Cuetip.logger.debug 'Removed job from database'
|
57
57
|
end
|
58
58
|
|
59
59
|
end
|
@@ -61,74 +61,78 @@ module Cuetip
|
|
61
61
|
# Log some text about this job
|
62
62
|
#
|
63
63
|
# @param text [String]
|
64
|
-
def log(text)
|
65
|
-
Cuetip.logger.info
|
64
|
+
def log(text, **tags)
|
65
|
+
Cuetip.logger.info text, **tags
|
66
66
|
end
|
67
67
|
|
68
68
|
# Execute the job
|
69
69
|
#
|
70
70
|
# @return [Boolean] whether the job executed successfully or not
|
71
71
|
def execute(&block)
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
72
|
+
Klogger.tagged(job_id: id, job_class: class_name) do
|
73
|
+
begin
|
74
|
+
Cuetip.logger.info "Executing"
|
75
|
+
# Initialize a new instance of the job we wish to execute
|
76
|
+
job_klass = class_name.constantize.new(self)
|
77
|
+
|
78
|
+
# If the job has expired, we should not be executing this so we'll just
|
79
|
+
# remove it from the queue and mark it as expired.
|
80
|
+
if expired?
|
81
|
+
Cuetip.logger.warn 'Job has expired, removed from queue'
|
82
|
+
self.status = 'Expired'
|
83
|
+
remove_from_queue
|
84
|
+
Cuetip.config.emit(:expired, self, job_klass)
|
85
|
+
return false
|
86
|
+
end
|
85
87
|
|
86
|
-
|
88
|
+
Cuetip.config.emit(:before_perform, self, job_klass)
|
87
89
|
|
88
|
-
|
89
|
-
|
90
|
-
|
90
|
+
# If we have a block, call this so we can manipulate our actual job class
|
91
|
+
# before execution if needed (mostly for testing)
|
92
|
+
block.call(job_klass) if block_given?
|
91
93
|
|
92
|
-
|
93
|
-
|
94
|
+
# Mark the job as runnign
|
95
|
+
update!(status: 'Running', started_at: Time.now, executions: executions + 1)
|
94
96
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
# Mark the job as complete and remove it from the queue
|
101
|
-
self.status = 'Complete'
|
102
|
-
log 'Job completed successfully'
|
103
|
-
remove_from_queue
|
104
|
-
|
105
|
-
Cuetip.config.emit(:completed, self, job_klass)
|
106
|
-
|
107
|
-
true
|
108
|
-
rescue Exception, Timeout::TimeoutError => e
|
109
|
-
log "Job failed with #{e.class} (#{e.message})"
|
110
|
-
|
111
|
-
# If there's an error, mark the job as failed and copy exception
|
112
|
-
# data into the job
|
113
|
-
self.status = 'Failed'
|
114
|
-
self.exception_class = e.class.name
|
115
|
-
self.exception_message = e.message
|
116
|
-
self.exception_backtrace = e.backtrace.join("\n")
|
117
|
-
|
118
|
-
# Handle requeing the job if needed.
|
119
|
-
if requeue_on_failure?
|
120
|
-
# Requeue this job for execution again after the retry interval.
|
121
|
-
new_job = queued_job.requeue(run_after: Time.now + retry_interval.to_i)
|
122
|
-
log "Requeing job to run after #{new_job.run_after.to_s(:long)}"
|
123
|
-
self.status = 'Pending'
|
124
|
-
else
|
125
|
-
# We're done with this job. We can't do any more retries.
|
126
|
-
remove_from_queue
|
127
|
-
end
|
97
|
+
begin
|
98
|
+
# Perform the job within a timeout
|
99
|
+
Timeout.timeout(maximum_execution_time || 1.year) do
|
100
|
+
job_klass.perform
|
101
|
+
end
|
128
102
|
|
129
|
-
|
103
|
+
# Mark the job as complete and remove it from the queue
|
104
|
+
self.status = 'Complete'
|
105
|
+
Cuetip.logger.info 'Execution complete'
|
106
|
+
remove_from_queue
|
130
107
|
|
131
|
-
|
108
|
+
Cuetip.config.emit(:completed, self, job_klass)
|
109
|
+
|
110
|
+
true
|
111
|
+
rescue Exception, Timeout::TimeoutError => e
|
112
|
+
Cuetip.logger.exception(e, "Job failed")
|
113
|
+
|
114
|
+
# If there's an error, mark the job as failed and copy exception
|
115
|
+
# data into the job
|
116
|
+
self.status = 'Failed'
|
117
|
+
self.exception_class = e.class.name
|
118
|
+
self.exception_message = e.message
|
119
|
+
self.exception_backtrace = e.backtrace.join("\n")
|
120
|
+
|
121
|
+
# Handle requeing the job if needed.
|
122
|
+
if requeue_on_failure?
|
123
|
+
# Requeue this job for execution again after the retry interval.
|
124
|
+
new_job = queued_job.requeue(run_after: Time.now + retry_interval.to_i)
|
125
|
+
Cuetip.logger.info "Requeueing job", run_after: new_job.run_after.to_s(:long)
|
126
|
+
self.status = 'Pending'
|
127
|
+
else
|
128
|
+
# We're done with this job. We can't do any more retries.
|
129
|
+
remove_from_queue
|
130
|
+
end
|
131
|
+
|
132
|
+
Cuetip.config.emit(:exception, e, self, job_klass)
|
133
|
+
|
134
|
+
false
|
135
|
+
end
|
132
136
|
end
|
133
137
|
ensure
|
134
138
|
unless destroyed?
|
@@ -136,8 +140,9 @@ module Cuetip
|
|
136
140
|
save!
|
137
141
|
end
|
138
142
|
Cuetip.config.emit(:finished, self, job_klass)
|
139
|
-
|
143
|
+
Cuetip.logger.debug 'Finished processing'
|
140
144
|
end
|
141
145
|
end
|
146
|
+
end
|
142
147
|
end
|
143
148
|
end
|
data/lib/cuetip/version.rb
CHANGED
data/lib/cuetip/worker_group.rb
CHANGED
@@ -6,6 +6,7 @@ module Cuetip
|
|
6
6
|
class WorkerGroup
|
7
7
|
include ActiveSupport::Callbacks
|
8
8
|
|
9
|
+
define_callbacks :run_worker_group
|
9
10
|
define_callbacks :run_worker
|
10
11
|
|
11
12
|
attr_reader :quantity
|
@@ -20,30 +21,36 @@ module Cuetip
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def start
|
23
|
-
|
24
|
-
|
25
|
-
@queues.
|
26
|
-
|
27
|
-
|
28
|
-
exit_trap = proc do
|
29
|
-
@workers.each { |_, worker| worker.request_exit! }
|
30
|
-
puts 'Exiting...'
|
31
|
-
end
|
24
|
+
Klogger.tagged(pid: Process.pid) do
|
25
|
+
Cuetip.logger.info "Starting workers", quantity: @quantity
|
26
|
+
if @queues.any?
|
27
|
+
@queues.each { |q| Cuetip.logger.info "Joined queue", queue: q }
|
28
|
+
end
|
32
29
|
|
33
|
-
|
34
|
-
|
30
|
+
exit_trap = proc do
|
31
|
+
@workers.each { |_, worker| worker.request_exit! }
|
32
|
+
puts 'Exiting...'
|
33
|
+
end
|
35
34
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
trap('INT', &exit_trap)
|
36
|
+
trap('TERM', &exit_trap)
|
37
|
+
|
38
|
+
run_callbacks :run_worker_group do
|
39
|
+
@quantity.times do |i|
|
40
|
+
@workers[i] = Worker.new(self, i, @queues)
|
41
|
+
Klogger.tagged worker_index: i do
|
42
|
+
Cuetip.logger.info "Starting worker"
|
43
|
+
@threads[i] = Thread.new(@workers[i]) do |worker|
|
44
|
+
run_callbacks :run_worker do
|
45
|
+
worker.run
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
@threads[i].abort_on_exception = true
|
42
50
|
end
|
51
|
+
@threads.values.each(&:join)
|
43
52
|
end
|
44
|
-
@threads[i].abort_on_exception = true
|
45
53
|
end
|
46
|
-
@threads.values.each(&:join)
|
47
54
|
end
|
48
55
|
|
49
56
|
def set_process_name
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuetip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Cooke
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -38,6 +38,26 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: klogger-logger
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
- - "<"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '2.0'
|
51
|
+
type: :runtime
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '1.3'
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2.0'
|
41
61
|
description: An ActiveRecord job queueing system
|
42
62
|
email:
|
43
63
|
- me@adamcooke.io
|
@@ -66,7 +86,7 @@ homepage: https://github.com/adamcooke/cuetip
|
|
66
86
|
licenses:
|
67
87
|
- MIT
|
68
88
|
metadata: {}
|
69
|
-
post_install_message:
|
89
|
+
post_install_message:
|
70
90
|
rdoc_options: []
|
71
91
|
require_paths:
|
72
92
|
- lib
|
@@ -81,8 +101,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
101
|
- !ruby/object:Gem::Version
|
82
102
|
version: '0'
|
83
103
|
requirements: []
|
84
|
-
rubygems_version: 3.
|
85
|
-
signing_key:
|
104
|
+
rubygems_version: 3.4.6
|
105
|
+
signing_key:
|
86
106
|
specification_version: 4
|
87
107
|
summary: An ActiveRecord job queueing system
|
88
108
|
test_files: []
|