gi_job 0.1.3
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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +34 -0
- data/LICENSE.txt +21 -0
- data/README.md +69 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/gi_job.gemspec +29 -0
- data/lib/generators/gi_job/install/install_generator.rb +49 -0
- data/lib/generators/gi_job/install/templates/models/gi_job_file.rb +28 -0
- data/lib/generators/gi_job/install/templates/models/gi_job_log.rb +29 -0
- data/lib/generators/gi_job/install/templates/models/gi_job_transaction.rb +39 -0
- data/lib/generators/gi_job/install/templates/schemas/gi_job_files.schema +11 -0
- data/lib/generators/gi_job/install/templates/schemas/gi_job_logs.schema +10 -0
- data/lib/generators/gi_job/install/templates/schemas/gi_job_transactions.schema +18 -0
- data/lib/generators/gi_job/install/templates/uploaders/gi_log_file_carrier_wave_uploader.rb +25 -0
- data/lib/gi_job.rb +32 -0
- data/lib/gi_job/jobs/concerns/job_constructor.rb +185 -0
- data/lib/gi_job/jobs/concerns/job_runner.rb +549 -0
- data/lib/gi_job/jobs/concerns/jobable.rb +28 -0
- data/lib/gi_job/jobs/job_command_suspended.rb +11 -0
- data/lib/gi_job/jobs/job_utils.rb +22 -0
- data/lib/gi_job/models/concerns/gi_job_fileable.rb +79 -0
- data/lib/gi_job/models/concerns/gi_job_loggable.rb +26 -0
- data/lib/gi_job/models/concerns/gi_job_ownerble.rb +20 -0
- data/lib/gi_job/models/concerns/gi_job_transactionable.rb +220 -0
- data/lib/gi_job/tasks/gi_job_task.rake +176 -0
- data/lib/gi_job/version.rb +3 -0
- metadata +78 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require "gi_job/jobs/concerns/job_constructor"
|
|
2
|
+
require "gi_job/jobs/concerns/job_runner"
|
|
3
|
+
|
|
4
|
+
module GiJob
|
|
5
|
+
module Jobs
|
|
6
|
+
module Concerns
|
|
7
|
+
module Jobable
|
|
8
|
+
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
included do # begin included
|
|
11
|
+
include GiJob::Jobs::Concerns::JobConstructor
|
|
12
|
+
include GiJob::Jobs::Concerns::JobRunner
|
|
13
|
+
|
|
14
|
+
def abc()
|
|
15
|
+
puts "abc!"
|
|
16
|
+
end
|
|
17
|
+
end # end included
|
|
18
|
+
|
|
19
|
+
class_methods do # begin class_methods
|
|
20
|
+
def abcd()
|
|
21
|
+
puts "abc!"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module GiJob
|
|
2
|
+
module Jobs
|
|
3
|
+
class JobUtils
|
|
4
|
+
|
|
5
|
+
def logging_fatal(execption)
|
|
6
|
+
GiJob.logger.fatal(execption.message)
|
|
7
|
+
GiJob.logger.fatal(execption.backtrace.join("\n"))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.check_job_suspended(gi_job_transaction)
|
|
11
|
+
if gi_job_transaction.process_status_suspended?
|
|
12
|
+
# 一時停止の場合は解除する
|
|
13
|
+
gi_job_transaction.append_log_info(division: "job再開", description: "ジョブを再開しました")
|
|
14
|
+
gi_job_transaction.process_status_none!
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end # end JobUtils
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Commons::GemUtils.reload("/gems/gi_job/lib/gi_job") && reload! && ConsoleTest.new.test_c
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module GiJob
|
|
2
|
+
module Models
|
|
3
|
+
module Concerns
|
|
4
|
+
module GiJobFileable
|
|
5
|
+
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do # begin included
|
|
9
|
+
|
|
10
|
+
mount_uploader :file, GiLogFileCarrierWaveUploader
|
|
11
|
+
|
|
12
|
+
belongs_to :gi_job_transaction
|
|
13
|
+
|
|
14
|
+
end # end included
|
|
15
|
+
|
|
16
|
+
class_methods do # begin class_methods
|
|
17
|
+
|
|
18
|
+
def create_file!(
|
|
19
|
+
gi_job_transaction:,
|
|
20
|
+
file_path: nil,
|
|
21
|
+
uploaded_file: nil,
|
|
22
|
+
rows: 0
|
|
23
|
+
)
|
|
24
|
+
file = nil
|
|
25
|
+
name = nil
|
|
26
|
+
size = 0
|
|
27
|
+
|
|
28
|
+
if file_path.present?
|
|
29
|
+
name = File.basename(file_path)
|
|
30
|
+
file = File.open(file_path)
|
|
31
|
+
size = File.size(file_path)
|
|
32
|
+
|
|
33
|
+
elsif uploaded_file.present?
|
|
34
|
+
GiJob.logger.ap(uploaded_file: uploaded_file)
|
|
35
|
+
name = File.basename(uploaded_file.original_filename)
|
|
36
|
+
file = uploaded_file
|
|
37
|
+
size = uploaded_file.size
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
self.create!({
|
|
41
|
+
gi_job_transaction: gi_job_transaction,
|
|
42
|
+
name: name,
|
|
43
|
+
file: file,
|
|
44
|
+
rows: rows,
|
|
45
|
+
size: size,
|
|
46
|
+
})
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def create_action_dispatch_uploaded_file(file, file_name)
|
|
51
|
+
params = {
|
|
52
|
+
:filename => "#{file_name}",
|
|
53
|
+
:type => File.extname(file_name).delete('.'),
|
|
54
|
+
:tempfile => file
|
|
55
|
+
}
|
|
56
|
+
# logger.ap({"method": "base64_conversion", params: params})
|
|
57
|
+
ActionDispatch::Http::UploadedFile.new(params)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end # end class_methods
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def data_source
|
|
65
|
+
self.file.force_encoding('utf-8')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def delete_data_source!
|
|
69
|
+
self.update!({file: nil})
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def has_file?
|
|
73
|
+
self.file_blob.present? || self.file.present?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end # end GiJobFileable
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module GiJob
|
|
2
|
+
module Models
|
|
3
|
+
module Concerns
|
|
4
|
+
module GiJobLoggable
|
|
5
|
+
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do # begin included
|
|
9
|
+
|
|
10
|
+
belongs_to :gi_job_transaction
|
|
11
|
+
|
|
12
|
+
enum level: {
|
|
13
|
+
info: 100,
|
|
14
|
+
warning: 200,
|
|
15
|
+
error: 300,
|
|
16
|
+
}, _prefix: true
|
|
17
|
+
|
|
18
|
+
end # end included
|
|
19
|
+
|
|
20
|
+
class_methods do # begin class_methods
|
|
21
|
+
end # end class_methods
|
|
22
|
+
|
|
23
|
+
end # end GiJobLoggable
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module GiJob
|
|
2
|
+
module Models
|
|
3
|
+
module Concerns
|
|
4
|
+
module GiJobOwnerble
|
|
5
|
+
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do # begin included
|
|
9
|
+
|
|
10
|
+
has_many :gi_job_transaction, as: :owner
|
|
11
|
+
|
|
12
|
+
end # end included
|
|
13
|
+
|
|
14
|
+
class_methods do # begin class_methods
|
|
15
|
+
end # end class_methods
|
|
16
|
+
|
|
17
|
+
end # end GiJobLoggable
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
module GiJob
|
|
2
|
+
module Models
|
|
3
|
+
module Concerns
|
|
4
|
+
module GiJobTransactionable
|
|
5
|
+
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do # begin included
|
|
9
|
+
|
|
10
|
+
serialize :parameter
|
|
11
|
+
serialize :process_progress
|
|
12
|
+
|
|
13
|
+
belongs_to :owner, polymorphic: true, optional: true
|
|
14
|
+
has_many :gi_job_logs, dependent: :destroy
|
|
15
|
+
has_many :gi_job_files, dependent: :destroy
|
|
16
|
+
|
|
17
|
+
enum status: {
|
|
18
|
+
registerd: 100,
|
|
19
|
+
running: 200,
|
|
20
|
+
completed: 300,
|
|
21
|
+
error: 400,
|
|
22
|
+
}, _prefix: true
|
|
23
|
+
|
|
24
|
+
enum process_status: {
|
|
25
|
+
none: 100,
|
|
26
|
+
suspended: 200,
|
|
27
|
+
terminated: 300,
|
|
28
|
+
}, _prefix: true
|
|
29
|
+
|
|
30
|
+
enum command: {
|
|
31
|
+
none: 100,
|
|
32
|
+
stop: 200,
|
|
33
|
+
}, _prefix: true
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
scope :search_jobs, -> (params) {
|
|
37
|
+
search_by_id(params[:id])
|
|
38
|
+
.search_by_name(params[:name])
|
|
39
|
+
.search_by_status(params[:status])
|
|
40
|
+
.order_by(params[:order_by])
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
scope :search_by_id, -> (value) {
|
|
44
|
+
where(id: value) if value.present?
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
scope :search_by_name, -> (value) {
|
|
48
|
+
where(name: value) if value.present?
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
scope :search_by_status, -> (value) {
|
|
52
|
+
v = value.is_a?(String) ? GiJobTransaction.statuses[value] : value
|
|
53
|
+
where(status: v) if v.present?
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
scope :order_by, -> (order_by = nil){
|
|
57
|
+
if order_by.present?
|
|
58
|
+
order("#{order_by}")
|
|
59
|
+
else
|
|
60
|
+
order("gi_job_transactions.updated_at desc")
|
|
61
|
+
end
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
scope :ghosts, -> (no_reaction_minutes) {
|
|
65
|
+
# TODO 更新が無いjobを検出する
|
|
66
|
+
# 本来であればちゃんとprocessキルがされる際にstatusを更新する
|
|
67
|
+
# これは、何らかの原因で jobレコードが更新さずに jobプロセスが死んでしまった場合の暫定的な救済処置である
|
|
68
|
+
|
|
69
|
+
to_datetime = Time.zone.now - no_reaction_minutes.minutes
|
|
70
|
+
where(process_status: :none)
|
|
71
|
+
.where(status: [GiJobTransaction.statuses[:registerd], GiJobTransaction.statuses[:running]])
|
|
72
|
+
.where("gi_job_transactions.updated_at < ?", to_datetime)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
scope :suspended, -> () {
|
|
76
|
+
where(process_status: :suspended)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
scope :ended, -> () {
|
|
80
|
+
where(status: [GiJobTransaction.statuses[:completed], GiJobTransaction.statuses[:error]])
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
scope :old_ended, -> (time_limit = 14.days) {
|
|
84
|
+
# 既に終了して2週間起つjobを検出する
|
|
85
|
+
time_now = Time.now
|
|
86
|
+
to_datetime = time_now - time_limit
|
|
87
|
+
Rails.logger.ap("delete_old_file #{time_now} - #{time_limit} = to_datetime: #{to_datetime}")
|
|
88
|
+
where(process_status: :none)
|
|
89
|
+
.ended
|
|
90
|
+
.where("gi_job_transactions.updated_at < ?", to_datetime)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
scope :has_job_file_data_sources, -> () {
|
|
94
|
+
# 有効なdata_sourcesを持っているジョブを検出する
|
|
95
|
+
eager_load(:gi_job_files)
|
|
96
|
+
.where("gi_job_files.file is not null")
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
scope :past_ended_same_type_jobs, -> (gi_job_transaction) {
|
|
100
|
+
where(
|
|
101
|
+
owner: gi_job_transaction.owner,
|
|
102
|
+
name: gi_job_transaction.name
|
|
103
|
+
).where(
|
|
104
|
+
"gi_job_transactions.created_at < ?", gi_job_transaction.created_at
|
|
105
|
+
).ended.where.not(
|
|
106
|
+
id: gi_job_transaction.id
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
end # end included
|
|
111
|
+
|
|
112
|
+
class_methods do # begin class_methods
|
|
113
|
+
|
|
114
|
+
def delete_old_for_one_shot(gi_job_transaction)
|
|
115
|
+
# 単発ジョブ向け。過去のjob_transactionを削除する。
|
|
116
|
+
self.past_ended_same_type_jobs(gi_job_transaction).destroy_all
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end # end class_methods
|
|
120
|
+
|
|
121
|
+
def append_log_info(**args) append_log(level: :info, **args) end
|
|
122
|
+
def append_log_warning(**args) append_log(level: :warning, **args) end
|
|
123
|
+
def append_log_error(**args) append_log(level: :error, **args) end
|
|
124
|
+
|
|
125
|
+
def append_log(level: :info, position: nil, division: :none, description: nil)
|
|
126
|
+
GiJobLog.create!({
|
|
127
|
+
gi_job_transaction: self,
|
|
128
|
+
level: GiJobLog.levels[level],
|
|
129
|
+
position: position,
|
|
130
|
+
division: division,
|
|
131
|
+
description: description
|
|
132
|
+
})
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def append_log(level: :info, position: nil, division: :none, description: nil)
|
|
136
|
+
GiJobLog.create!({
|
|
137
|
+
gi_job_transaction: self,
|
|
138
|
+
level: GiJobLog.levels[level],
|
|
139
|
+
position: position,
|
|
140
|
+
division: division,
|
|
141
|
+
description: description
|
|
142
|
+
})
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def create_job_logs_hash
|
|
146
|
+
hash = {
|
|
147
|
+
info: [],
|
|
148
|
+
warning: [],
|
|
149
|
+
error: [],
|
|
150
|
+
}
|
|
151
|
+
self.gi_job_logs.each {|job_log| hash[job_log.level.to_sym] << job_log}
|
|
152
|
+
hash
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def counts_ended
|
|
156
|
+
(counts_completed || 0) + (counts_errord || 0)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def has_error_log?
|
|
160
|
+
gi_job_logs.any?{|job_log| job_log.error?}
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def to_simple
|
|
164
|
+
job_logs_hash = create_job_logs_hash
|
|
165
|
+
{
|
|
166
|
+
id: self.id,
|
|
167
|
+
name: self.name,
|
|
168
|
+
status: self.status,
|
|
169
|
+
counts_all: self.counts_all,
|
|
170
|
+
counts_progress: self.counts_progress,
|
|
171
|
+
counts_completed: self.counts_completed,
|
|
172
|
+
counts_errord: self.counts_errord,
|
|
173
|
+
process_status: self.process_status,
|
|
174
|
+
created_at: self.created_at,
|
|
175
|
+
updated_at: self.updated_at,
|
|
176
|
+
gi_job_logs: self.gi_job_logs,
|
|
177
|
+
job_logs_hash: job_logs_hash,
|
|
178
|
+
has_error_log: job_logs_hash[:error].present?,
|
|
179
|
+
}
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def status_ended?
|
|
183
|
+
status_completed? || status_error?
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def create_file!(**params)
|
|
187
|
+
GiJobFile.create_file!(gi_job_transaction: self, **params)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def log_files_filter_common_warns
|
|
191
|
+
gi_job_log_files.filter do |gi_job_log_file|
|
|
192
|
+
gi_job_log_file.file_name.start_with?("警告")
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def log_files_filter_common_errors
|
|
197
|
+
gi_job_log_files.filter do |gi_job_log_file|
|
|
198
|
+
gi_job_log_file.file_name.start_with?("エラー")
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
### for displays
|
|
204
|
+
def to_string_line
|
|
205
|
+
[
|
|
206
|
+
"#{self.id}",
|
|
207
|
+
"#{self.updated_at}",
|
|
208
|
+
"#{self.owner_type}(#{self.owner_id})",
|
|
209
|
+
"#{self.name}",
|
|
210
|
+
"#{self.status}",
|
|
211
|
+
"#{self.counts_progress}/#{self.counts_all}",
|
|
212
|
+
"errord: #{self.counts_errord}",
|
|
213
|
+
].join(", ")
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
end # end GiJobTransactionable
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
require 'sidekiq/api'
|
|
2
|
+
|
|
3
|
+
namespace :gi_job_task do
|
|
4
|
+
desc "job_status が更新されずにプロセスが無くなってしまったジョブの job_status を errorにする"
|
|
5
|
+
task :terminate_ghost_jobs => :environment do
|
|
6
|
+
# puts "start terminate_ghost_jobs"
|
|
7
|
+
time_now = Time.now
|
|
8
|
+
no_reaction_minutes = 30 # 30分間更新されていない未完了のジョブ
|
|
9
|
+
jobs = Job.ghosts(no_reaction_minutes)
|
|
10
|
+
counts_target_jobs = jobs.size
|
|
11
|
+
counts_terminated = 0
|
|
12
|
+
jobs.each do |job|
|
|
13
|
+
# Rails.logger.ap({job: job})
|
|
14
|
+
|
|
15
|
+
# ジョブステータスを更新
|
|
16
|
+
job.append_error("強制停止", "ジョブが停止されました。再度実行してください。")
|
|
17
|
+
job.update_columns({job_status: Job.job_statuses[:error]})
|
|
18
|
+
counts_terminated += 1
|
|
19
|
+
|
|
20
|
+
Rails.logger.fatal("terminate_ghost_job: job_id: #{job.id}")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
puts "#{time_now.strftime('%Y/%m/%d %H:%M:%S')} end terminate_ghost_jobs #{counts_terminated}/#{counts_target_jobs}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
task :delete_old_tmp_files => :environment do
|
|
27
|
+
time_now = Time.now
|
|
28
|
+
# 一時ディレクトリ内の古いファイルを削除
|
|
29
|
+
# クラスタ環境下では一時ディレクトリのファイルはdistでは作成されないが、
|
|
30
|
+
# materialize_job_files で作成されたファイルを削除するために動かしている
|
|
31
|
+
paths = Jobable.delete_old_files
|
|
32
|
+
local_deleted_counts = 0
|
|
33
|
+
paths.each do |path|
|
|
34
|
+
Rails.logger.info("delete_old_files: path: #{path}")
|
|
35
|
+
local_deleted_counts += 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# 終了している古い job_files の file を削除する
|
|
39
|
+
old_ended_has_data_sources_jobs = Job.old_ended.has_job_file_data_sources
|
|
40
|
+
db_deleted_counts = 0
|
|
41
|
+
old_ended_has_data_sources_jobs.each do |job|
|
|
42
|
+
job.job_files.each do |job_file|
|
|
43
|
+
Rails.logger.info("job_file.delete_data_source: job_id: #{job.id}, job_file_id: #{job_file.id}")
|
|
44
|
+
job_file.delete_data_source!
|
|
45
|
+
db_deleted_counts += 1
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
puts "#{time_now.strftime('%Y/%m/%d %H:%M:%S')} end delete_old_tmp_files local: #{local_deleted_counts}, db: #{db_deleted_counts}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
##### 状況確認のための task
|
|
53
|
+
desc "job / sidekiq の状態を表示する"
|
|
54
|
+
task :status => :environment do
|
|
55
|
+
Rake::Task["gi_job_task:show_recently_jobs"].invoke
|
|
56
|
+
Rake::Task["gi_job_task:show_job_statuses"].invoke
|
|
57
|
+
Rake::Task["gi_job_task:show_sidekiq_statuses"].invoke
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
desc "直近10ジョブを表示する"
|
|
61
|
+
task :show_recently_jobs => :environment do
|
|
62
|
+
puts "- show recentry jobs"
|
|
63
|
+
gi_job_transaction = GiJobTransaction.preload(:owner, :gi_job_logs).order(updated_at: :desc).limit(10)
|
|
64
|
+
strings = gi_job_transaction.map(&:to_string_line)
|
|
65
|
+
puts strings.join("\n")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
desc "全ジョブのステータス集計を表示する"
|
|
69
|
+
task :show_job_statuses => :environment do
|
|
70
|
+
puts "- show jobs statuses"
|
|
71
|
+
grouped = GiJobTransaction.group(:status, :process_status).count
|
|
72
|
+
Rails.logger.ap({grouped: grouped})
|
|
73
|
+
display = grouped.map do |keys, counts|
|
|
74
|
+
"#{sprintf("%-12s", keys[0])} | #{sprintf("%-12s", keys[1])}: #{sprintf("%12d", counts)}"
|
|
75
|
+
end.join("\n")
|
|
76
|
+
puts display
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
desc "sidekiqの状況を表示する"
|
|
80
|
+
task :show_sidekiq_statuses => :environment do
|
|
81
|
+
puts "- show sidekiq statuses"
|
|
82
|
+
# Rails.logger.ap({task: "show sidekiq statuses"})
|
|
83
|
+
|
|
84
|
+
puts "実行中: #{Sidekiq::Workers.new.size} 件"
|
|
85
|
+
Sidekiq::Workers.new.each do |process_id, thread_id, sidekiq_job|
|
|
86
|
+
Rails.logger.ap({
|
|
87
|
+
process_id: process_id,
|
|
88
|
+
thread_id: thread_id,
|
|
89
|
+
sidekiq_job: sidekiq_job
|
|
90
|
+
})
|
|
91
|
+
payload = sidekiq_job["payload"]
|
|
92
|
+
payload_args = payload["args"][0]
|
|
93
|
+
job_argument = payload_args["arguments"][0]
|
|
94
|
+
strings = []
|
|
95
|
+
strings << "pid: #{process_id}"
|
|
96
|
+
strings << "tid: #{thread_id}"
|
|
97
|
+
strings << "sjid: #{payload_args["job_id"]}"
|
|
98
|
+
if job_argument && job_argument["gi_job_transaction"] && job_argument["gi_job_transaction"]["_aj_globalid"]
|
|
99
|
+
strings << "job_id: #{job_argument["gi_job_transaction"]["_aj_globalid"]}"
|
|
100
|
+
end
|
|
101
|
+
strings << "class: #{payload_args["job_class"]}"
|
|
102
|
+
|
|
103
|
+
puts "[#{strings.join("][")}]"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
display_waiting_proc = Proc.new do |sidekiq_job|
|
|
107
|
+
Rails.logger.ap({
|
|
108
|
+
sidekiq_job: sidekiq_job
|
|
109
|
+
})
|
|
110
|
+
payload = sidekiq_job.item
|
|
111
|
+
payload_args = payload["args"][0]
|
|
112
|
+
job_argument = payload_args["arguments"][0]
|
|
113
|
+
strings = []
|
|
114
|
+
strings << "sjid: #{payload_args["job_id"]}"
|
|
115
|
+
if job_argument && job_argument["gi_job_transaction"] && job_argument["gi_job_transaction"]["_aj_globalid"]
|
|
116
|
+
strings << "job_id: #{job_argument["gi_job_transaction"]["_aj_globalid"]}"
|
|
117
|
+
end
|
|
118
|
+
strings << "class: #{payload_args["job_class"]}"
|
|
119
|
+
|
|
120
|
+
puts "[#{strings.join("][")}]"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
puts "キュー: #{Sidekiq::Queue.new.size} 件"
|
|
124
|
+
Sidekiq::Queue.new.each do |sidekiq_job|
|
|
125
|
+
display_waiting_proc.call(sidekiq_job)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
puts "再試行: #{Sidekiq::RetrySet.new.size} 件"
|
|
129
|
+
Sidekiq::RetrySet.new.each do |sidekiq_job|
|
|
130
|
+
display_waiting_proc.call(sidekiq_job)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
task :change_maintenance, ['mode'] => :environment do |task, args|
|
|
137
|
+
mode = args[:mode]
|
|
138
|
+
if mode.blank?
|
|
139
|
+
# modeが指定されなかった場合は現在のモードを表示して終了する
|
|
140
|
+
maintenance = Maintenance.find_record
|
|
141
|
+
puts "current mode: #{maintenance.mode}"
|
|
142
|
+
|
|
143
|
+
else
|
|
144
|
+
# mode変更
|
|
145
|
+
Maintenance.change_mode!(mode)
|
|
146
|
+
|
|
147
|
+
if mode == "none"
|
|
148
|
+
# suspendedされていたジョブを再起動する
|
|
149
|
+
jobs = Job.suspended
|
|
150
|
+
jobs.each do |job|
|
|
151
|
+
job_class_string = job.job_type.classify
|
|
152
|
+
Rails.logger.ap("class => #{job_class_string}")
|
|
153
|
+
|
|
154
|
+
job_class = job_class_string.constantize # -> ModelName
|
|
155
|
+
Rails.logger.ap({job_class: job_class})
|
|
156
|
+
|
|
157
|
+
job_class.start_job(job)
|
|
158
|
+
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
task :materialize_job_files, ['job_id'] => :environment do |task, args|
|
|
165
|
+
# dbに格納されたjob_fileを/tmpに作成する
|
|
166
|
+
job_id = args[:job_id]
|
|
167
|
+
job = Job.eager_load(:job_files).find_by(id: job_id)
|
|
168
|
+
job.job_files.each_with_index do |job_file, index|
|
|
169
|
+
file_name_suffix = "#{index == 0 ? "" : "_#{index.to_s}"}_#{job_file.file_name}"
|
|
170
|
+
file_path = Jobable.create_file_path(job, file_name_suffix)
|
|
171
|
+
Jobable.file_create(job_file.data_source, file_path)
|
|
172
|
+
puts "create_file: #{file_path}"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
end
|