bizside 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/app/assets/images/jquery-treeTable/images/toggle-collapse-dark.png +0 -0
- data/app/assets/images/jquery-treeTable/images/toggle-collapse-light.png +0 -0
- data/app/assets/images/jquery-treeTable/images/toggle-expand-dark.png +0 -0
- data/app/assets/images/jquery-treeTable/images/toggle-expand-light.png +0 -0
- data/app/assets/javascripts/bizside.js +1 -0
- data/app/assets/javascripts/jquery-treeTable/jquery.treeTable.js +400 -0
- data/app/assets/stylesheets/bizside.css +3 -0
- data/app/assets/stylesheets/jquery-treeTable/jquery.treeTable.css.erb +55 -0
- data/lib/bizside/acl/access_control_utils.rb +36 -0
- data/lib/bizside/acl/available_helper.rb +65 -0
- data/lib/bizside/acl/controller_helper.rb +15 -0
- data/lib/bizside/acl.rb +6 -0
- data/lib/bizside/active_record_logger.rb +3 -0
- data/lib/bizside/audit/job_logger.rb +14 -0
- data/lib/bizside/audit/logger.rb +35 -0
- data/lib/bizside/audit_log.rb +158 -0
- data/lib/bizside/cache/entry.rb +112 -0
- data/lib/bizside/cache/file_store.rb +167 -0
- data/lib/bizside/cache/store.rb +237 -0
- data/lib/bizside/cache_util.rb +47 -0
- data/lib/bizside/cache_utils.rb +10 -0
- data/lib/bizside/carrierwave.rb +48 -0
- data/lib/bizside/config.rb +63 -0
- data/lib/bizside/configurations/mail.rb +37 -0
- data/lib/bizside/configurations/prefix.rb +25 -0
- data/lib/bizside/configurations/storage.rb +28 -0
- data/lib/bizside/coverage/launch.rb +25 -0
- data/lib/bizside/coverage/rcov_formatter.rb +13 -0
- data/lib/bizside/cron_validator.rb +62 -0
- data/lib/bizside/cucumber.rb +1 -0
- data/lib/bizside/engine.rb +4 -0
- data/lib/bizside/file_converter.rb +56 -0
- data/lib/bizside/file_uploader.rb +71 -0
- data/lib/bizside/gengou.rb +46 -0
- data/lib/bizside/gengou.yml +5 -0
- data/lib/bizside/hanaita_conf.rb +88 -0
- data/lib/bizside/implicit_ftps.rb +29 -0
- data/lib/bizside/itamae_conf.rb +186 -0
- data/lib/bizside/job_utils.rb +285 -0
- data/lib/bizside/log_analyzer.rb +122 -0
- data/lib/bizside/mailer.rb +56 -0
- data/lib/bizside/query_builder.rb +78 -0
- data/lib/bizside/railtie.rb +80 -0
- data/lib/bizside/record_has_warnings.rb +4 -0
- data/lib/bizside/resque.rb +141 -0
- data/lib/bizside/rsync.rb +40 -0
- data/lib/bizside/safe_pty.rb +17 -0
- data/lib/bizside/shib_utils.rb +18 -0
- data/lib/bizside/show_exceptions.rb +18 -0
- data/lib/bizside/sql_utils.rb +45 -0
- data/lib/bizside/string_io.rb +39 -0
- data/lib/bizside/string_utils.rb +157 -0
- data/lib/bizside/task_helper.rb +263 -0
- data/lib/bizside/tasks.rb +6 -0
- data/lib/bizside/test_help.rb +17 -0
- data/lib/bizside/uploader/content_type_validator.rb +39 -0
- data/lib/bizside/uploader/default_extensions.yml +15 -0
- data/lib/bizside/uploader/exif.rb +43 -0
- data/lib/bizside/uploader/extension_whitelist.rb +26 -0
- data/lib/bizside/uploader/filename_validator.rb +31 -0
- data/lib/bizside/user_agent/action_view/action_view_4.rb +56 -0
- data/lib/bizside/user_agent/action_view/use_variant.rb +4 -0
- data/lib/bizside/user_agent/action_view.rb +10 -0
- data/lib/bizside/user_agent/controller_helper.rb +51 -0
- data/lib/bizside/user_agent.rb +108 -0
- data/lib/bizside/validations.rb +8 -0
- data/lib/bizside/version.rb +3 -0
- data/lib/bizside/view_helper.rb +10 -0
- data/lib/bizside/warning.rb +24 -0
- data/lib/bizside/yes.rb +16 -0
- data/lib/bizside.rb +96 -0
- data/lib/cron_validator.rb +3 -0
- data/lib/gengou.rb +3 -0
- data/lib/job_utils.rb +3 -0
- data/lib/query_builder.rb +3 -0
- data/lib/record_has_warnings.rb +3 -0
- data/lib/sql_utils.rb +3 -0
- data/lib/string_utils.rb +3 -0
- data/lib/user_agent.rb +3 -0
- data/lib/yes.rb +3 -0
- data/rails/locales/ja.yml +12 -0
- data/validations/collection_presence_validator.rb +15 -0
- data/validations/email_validator.rb +1 -0
- data/validations/ip_address_validator.rb +22 -0
- data/validations/tel_validator.rb +28 -0
- data/validations/url_validator.rb +30 -0
- data/validations/zip_validator.rb +35 -0
- metadata +467 -0
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Bizside
|
5
|
+
# itamae_conf をテストするため、 singleton 以前のクラスを定義
|
6
|
+
#
|
7
|
+
# TODO: HanaitaConf と類似していますが HanaitaConf は obsolete 予定なので
|
8
|
+
# 敢えて refactoring はやっていません。
|
9
|
+
class ItamaeConfSub
|
10
|
+
class << self
|
11
|
+
# base..derived の順
|
12
|
+
def conf_files
|
13
|
+
if ENV['ITAMAE_CONFS']
|
14
|
+
ENV['ITAMAE_CONFS'].split
|
15
|
+
else
|
16
|
+
result = ['/etc/bizside/hanaita.yml']
|
17
|
+
add_yml(result, 'itamae.yml')
|
18
|
+
add_yml(result, 'database.yml')
|
19
|
+
result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# shared/*.yml を優先して指定。存在しない時にのみ config/*.yml を指定。
|
26
|
+
def add_yml(paths, basename)
|
27
|
+
candidates = []
|
28
|
+
candidates << File.join(ENV['DEPLOY_TO'], 'shared', basename).to_s unless ENV['DEPLOY_TO'].to_s.empty?
|
29
|
+
candidates << File.join('config', basename).to_s
|
30
|
+
|
31
|
+
candidates.each do |path|
|
32
|
+
if File.exist?(path)
|
33
|
+
paths << path
|
34
|
+
break
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize
|
41
|
+
for conf_file in self.class.conf_files do
|
42
|
+
if File.exist?(conf_file)
|
43
|
+
@_conf ||= {}
|
44
|
+
hash = YAML.load(ERB.new(File.read(conf_file)).result)
|
45
|
+
|
46
|
+
case conf_file
|
47
|
+
# itamae.yml スペシャルロジック。ROLE必須。
|
48
|
+
when /itamae.yml$/
|
49
|
+
role = ENV['ROLE']
|
50
|
+
next if role.nil? || role.empty?
|
51
|
+
hash = hash[role]
|
52
|
+
|
53
|
+
# database.yml スペシャルロジック。例:
|
54
|
+
#
|
55
|
+
# database.yml:: RAILS_ENV.adapter
|
56
|
+
# ↓:: ↓
|
57
|
+
# itamae_conf:: db.adapter
|
58
|
+
when /database.yml$/
|
59
|
+
partial = hash[Bizside.env]
|
60
|
+
hash = {'db' => partial.dup} if partial
|
61
|
+
end
|
62
|
+
deep_merge!(@_conf, hash) if hash
|
63
|
+
else
|
64
|
+
$stderr.printf("WARN: %s does NOT exist.\n", conf_file)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def conf
|
70
|
+
@_conf
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# (c)Rails
|
76
|
+
def deep_merge(h1, h2, &block)
|
77
|
+
deep_merge!(h1.dup, h2, &block)
|
78
|
+
end
|
79
|
+
|
80
|
+
# (c)Rails
|
81
|
+
def deep_merge!(h1, h2, &block)
|
82
|
+
h2.each_pair do |current_key, other_value|
|
83
|
+
this_value = h1[current_key]
|
84
|
+
h1[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
|
85
|
+
deep_merge(this_value, other_value, &block)
|
86
|
+
else
|
87
|
+
if block_given? && key?(current_key)
|
88
|
+
block.call(current_key, this_value, other_value)
|
89
|
+
else
|
90
|
+
other_value
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
h1
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# 各種 yml を1つの hash にマージした on-memory モデル:
|
99
|
+
#
|
100
|
+
# == SYNOPSIS
|
101
|
+
# require 'itamae_plugin_recipe_bizside'
|
102
|
+
# itamae_conf(:a, :b, ...) # Or
|
103
|
+
# itamae_conf('a.b...')
|
104
|
+
#
|
105
|
+
# == DESCRIPTION
|
106
|
+
# yaml設定ファイル(後述。FILES節参照) の hash に対するキー検索を行います。
|
107
|
+
#
|
108
|
+
# ファイルが存在しない場合は nil を返します。
|
109
|
+
#
|
110
|
+
# itamae_conf(:a, :b) は意味的に itamae.yml のハッシュに対する
|
111
|
+
# アクセスitamae_conf['a']['b'] と同等です。
|
112
|
+
#
|
113
|
+
# itamae_conf(:a) が ハッシュでない場合(未定義または文字列や数値など)、
|
114
|
+
# itamae_conf(:a, :b) は単に nil を返します('undefined method `[]'
|
115
|
+
# for nil:NilClass' とはなりません)。
|
116
|
+
#
|
117
|
+
# I18n#t と同様、'a.b' と言った文字列指定も可能です。
|
118
|
+
#
|
119
|
+
# == FILES
|
120
|
+
# config/database.yml:: 設定ファイル-1(*1)
|
121
|
+
# config/itamae.yml:: 設定ファイル-2(*2)
|
122
|
+
# /etc/bizside/hanaita.yml:: 設定ファイル-3
|
123
|
+
#
|
124
|
+
# (*1) RAISL_ENV に該当する部分のみ 'db' エントリの下に読み込みます。
|
125
|
+
# (*2) 指定された ROLE のみ読み込みます。
|
126
|
+
class ItamaeConf < ItamaeConfSub
|
127
|
+
class OverWriteError < StandardError; end
|
128
|
+
|
129
|
+
include Singleton
|
130
|
+
end
|
131
|
+
|
132
|
+
# 各フェーズで itamae_conf メソッド経由でアクセスできるようにするための
|
133
|
+
# ユーティリティ。node メソッドと同様。
|
134
|
+
module ItamaeConfAccessorMixin
|
135
|
+
# 必要に応じて上書き
|
136
|
+
def itamae_conf_factory
|
137
|
+
Bizside::ItamaeConf.instance
|
138
|
+
end
|
139
|
+
|
140
|
+
def itamae_conf(*args)
|
141
|
+
if args.nil? || (args.is_a?(Array) && args[0].is_a?(Symbol) || args[0].nil?)
|
142
|
+
itamae_conf_sub(itamae_conf_factory.conf, args)
|
143
|
+
elsif args.is_a?(Array) && args[0].is_a?(String)
|
144
|
+
itamae_conf_sub(itamae_conf_factory.conf, args[0].split('.').map{|s| s.to_sym})
|
145
|
+
else
|
146
|
+
raise 'unsupported argument type'
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# itamae_conf に値をセットします。
|
151
|
+
#
|
152
|
+
# 安易な上書きを避けるため、既存値が存在する場合は OverWriteError としています。
|
153
|
+
#
|
154
|
+
# 簡単化のため、シンボル指定(set_itamae_conf(:a, :b, ..., value))はサポートしていません
|
155
|
+
# (itamae_conf と違って)。
|
156
|
+
def set_itamae_conf(key, value)
|
157
|
+
raise 'まだ用途が定まっていないので、使用不可です。' unless Bizside.env == 'test'
|
158
|
+
set_itamae_conf_sub(itamae_conf_factory.conf, key.split('.'), key, value)
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
def itamae_conf_sub(data, args)
|
164
|
+
if args.size == 0
|
165
|
+
data
|
166
|
+
elsif data.is_a?(Hash)
|
167
|
+
itamae_conf_sub(data[args[0].to_s], args.drop(1))
|
168
|
+
else
|
169
|
+
nil
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# ここで key は単にエラーメッセージ用途
|
174
|
+
def set_itamae_conf_sub(hash, args, key, value)
|
175
|
+
arg0 = args[0]
|
176
|
+
if args.size == 1
|
177
|
+
raise ItamaeConf::OverWriteError.new("duplicate on #{key}") if hash[arg0]
|
178
|
+
|
179
|
+
hash[arg0] = value
|
180
|
+
else
|
181
|
+
hash[arg0] = {} if hash[arg0].nil?
|
182
|
+
set_itamae_conf_sub(hash[arg0], args.drop(1), key, value)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'bizside/cron_validator'
|
2
|
+
|
3
|
+
module Bizside
|
4
|
+
class JobUtils
|
5
|
+
|
6
|
+
def self.add_job(klass, *args, &block)
|
7
|
+
add_job_to(nil, klass, *args, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.add_job_to(queue, klass, *args)
|
11
|
+
if Bizside.rails_env&.test?
|
12
|
+
if klass.respond_to?(:before_enqueue)
|
13
|
+
return unless klass.before_enqueue(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
Bizside.logger.info "テスト時にはジョブの登録を行わず、即時実行します。"
|
17
|
+
klass.perform(*args)
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
if block_given?
|
22
|
+
yield
|
23
|
+
else
|
24
|
+
if queue
|
25
|
+
Bizside.logger.info "ジョブ #{klass} を #{queue} に登録します。"
|
26
|
+
else
|
27
|
+
Bizside.logger.info "ジョブ #{klass} を登録します。"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
if queue.present?
|
32
|
+
::Resque.enqueue_to(queue, klass, *args)
|
33
|
+
else
|
34
|
+
::Resque.enqueue(klass, *args)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.add_job_silently(klass, *args)
|
39
|
+
add_job(klass, *args) do
|
40
|
+
# 何も出力しない
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.add_job_silently_to(queue, klass, *args)
|
45
|
+
add_job_to(queue, klass, *args) do
|
46
|
+
# 何も出力しない
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.set_job_at(time, klass, *args)
|
51
|
+
if Bizside.rails_env&.test?
|
52
|
+
if klass.respond_to?(:before_enqueue)
|
53
|
+
return unless klass.before_enqueue(*args)
|
54
|
+
end
|
55
|
+
|
56
|
+
Bizside.logger.info "テスト時には遅延ジョブの登録を行わず、即時実行します。"
|
57
|
+
klass.perform(*args)
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
61
|
+
if block_given?
|
62
|
+
yield
|
63
|
+
else
|
64
|
+
Bizside.logger.info "遅延ジョブ #{klass} を登録します。"
|
65
|
+
end
|
66
|
+
|
67
|
+
::Resque.enqueue_at(time, klass, *args)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.set_job_silently_at(time, klass, *args)
|
71
|
+
set_job_at(time, klass, *args) do
|
72
|
+
# 何も出力しない
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.cancel_job_at(klass, *args)
|
77
|
+
if Bizside.rails_env&.test?
|
78
|
+
Bizside.logger.info "テスト時には遅延ジョブのキャンセルを行いません。"
|
79
|
+
return
|
80
|
+
end
|
81
|
+
|
82
|
+
::Resque.remove_delayed(klass, *args)
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.add_cron(name, job_type, cron, *args)
|
86
|
+
add_cron_to(nil, name, job_type, cron, *args)
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.add_cron_to(queue, name, job_type, cron, *args)
|
90
|
+
if Bizside.rails_env&.test?
|
91
|
+
Bizside.logger.info 'テスト時にはCronの設定を行いません。'
|
92
|
+
return
|
93
|
+
end
|
94
|
+
|
95
|
+
::Resque.remove_schedule(name)
|
96
|
+
|
97
|
+
cronline = Array(cron).first
|
98
|
+
|
99
|
+
if cronline.to_s.strip.empty?
|
100
|
+
return
|
101
|
+
elsif CronValidator.new(cronline).valid?
|
102
|
+
config = {
|
103
|
+
:class => job_type,
|
104
|
+
:cron => cron,
|
105
|
+
:args => args,
|
106
|
+
:persist => true
|
107
|
+
}
|
108
|
+
|
109
|
+
config[:queue] = queue if queue.present?
|
110
|
+
|
111
|
+
::Resque.set_schedule(name, config)
|
112
|
+
else
|
113
|
+
raise ArgumentError, "Cronの書式が正しくないのでスケジューリングしません。name=#{name}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.remove_cron(name)
|
118
|
+
remove_scheduler(name)
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.add_scheduler(name, job_type, interval_args, *args)
|
122
|
+
if Bizside.rails_env&.test?
|
123
|
+
Bizside.logger.info 'テスト時にはCronの設定を行いません。'
|
124
|
+
return
|
125
|
+
end
|
126
|
+
|
127
|
+
::Resque.remove_schedule(name)
|
128
|
+
|
129
|
+
if interval_args[:cron].present?
|
130
|
+
add_cron(name, job_type, interval_args[:cron], args)
|
131
|
+
elsif interval_args[:every].present?
|
132
|
+
config = {
|
133
|
+
:class => job_type,
|
134
|
+
:every => interval_args[:every],
|
135
|
+
:args => args,
|
136
|
+
:persist => true
|
137
|
+
}
|
138
|
+
::Resque.set_schedule(name, config)
|
139
|
+
else
|
140
|
+
raise ArgumentError, "cronもしくはeveryが指定されていないのでスケジューリングしません。name=#{name}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.remove_scheduler(name)
|
145
|
+
if Bizside.rails_env&.test?
|
146
|
+
Bizside.logger.info 'テスト時にはCronの設定を行いません。'
|
147
|
+
return
|
148
|
+
end
|
149
|
+
|
150
|
+
::Resque.remove_schedule(name)
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.peek(queue, start = 0, count = 1)
|
154
|
+
if Bizside.rails_env&.test?
|
155
|
+
Bizside.logger.info 'テスト時は、ジョブ 0 件とします。'
|
156
|
+
return []
|
157
|
+
end
|
158
|
+
|
159
|
+
::Resque.peek(queue, start, count)
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.enqueue_in(time_to_delay, klass, *args)
|
163
|
+
if Bizside.rails_env&.test?
|
164
|
+
Bizside.logger.info 'テスト時にジョブの遅延実行は行いません。'
|
165
|
+
return
|
166
|
+
end
|
167
|
+
|
168
|
+
::Resque.enqueue_in(time_to_delay, klass, *args)
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.enqueue_in_with_queue(queue, time_to_delay, klass, *args)
|
172
|
+
if Bizside.rails_env&.test?
|
173
|
+
Bizside.logger.info 'テスト時にジョブの遅延実行は行いません。'
|
174
|
+
return
|
175
|
+
end
|
176
|
+
|
177
|
+
::Resque.enqueue_in_with_queue(queue, time_to_delay, klass, *args)
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.dequeue(klass, *args)
|
181
|
+
if Bizside.rails_env&.test?
|
182
|
+
Bizside.logger.info 'テスト時にジョブの削除は行いません。'
|
183
|
+
return
|
184
|
+
end
|
185
|
+
|
186
|
+
::Resque.dequeue(klass, *args)
|
187
|
+
end
|
188
|
+
|
189
|
+
def self.any_jobs_for?(queue)
|
190
|
+
ret = ::Resque.size(queue)
|
191
|
+
ret += ::Resque.working.reduce(0){|sum, worker| sum += worker.queues.include?(queue) ? 1 : 0 }
|
192
|
+
ret > 0
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.remove_queue(queue)
|
196
|
+
if Bizside.rails_env&.test?
|
197
|
+
Bizside.logger.info 'テスト時にキューの削除は行いません。'
|
198
|
+
return
|
199
|
+
end
|
200
|
+
|
201
|
+
::Resque.remove_queue(queue)
|
202
|
+
end
|
203
|
+
|
204
|
+
def self.queue_from_class(klass)
|
205
|
+
::Resque.queue_from_class(klass)
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.queue_size(queue)
|
209
|
+
return 0 if Bizside.rails_env&.test?
|
210
|
+
|
211
|
+
::Resque.size(queue)
|
212
|
+
end
|
213
|
+
|
214
|
+
def self.unique_in_queue?(klass, args = {}, queue, count: 100, except: [])
|
215
|
+
if Bizside.rails_env&.test?
|
216
|
+
Bizside.logger.info "テスト時は常にキューに同一ジョブが存在しない前提とします。"
|
217
|
+
return true
|
218
|
+
end
|
219
|
+
|
220
|
+
jobs = self.peek(queue, 0, count) # 先頭からcount件のジョブ
|
221
|
+
|
222
|
+
if already_in_jobs?(klass, args, jobs, except: except)
|
223
|
+
false
|
224
|
+
else
|
225
|
+
count = rest_count(self.queue_size(queue), count)
|
226
|
+
if count == 0
|
227
|
+
true
|
228
|
+
else
|
229
|
+
count += 1 if count == 1 # Resque.peek()が1件だと戻り値の型が違うのを回避
|
230
|
+
jobs = self.peek(queue, count * -1, count) # 後ろからcount件のジョブ
|
231
|
+
! already_in_jobs?(klass, args, jobs, except: except)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.already_in_jobs?(klass, args = {}, jobs, except: [])
|
237
|
+
args_to_check = args.with_indifferent_access.except(*Array(except))
|
238
|
+
|
239
|
+
jobs.each do |hash|
|
240
|
+
hash = hash.with_indifferent_access
|
241
|
+
next unless hash['class'] == klass.to_s
|
242
|
+
|
243
|
+
args = Hash(hash['args'].present? ? hash['args'][0] : {}).with_indifferent_access.except(*Array(except))
|
244
|
+
next unless args.size == args_to_check.size
|
245
|
+
|
246
|
+
found = true
|
247
|
+
args_to_check.each do |key, value|
|
248
|
+
if args[key] != value
|
249
|
+
found = false
|
250
|
+
break
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
if found
|
255
|
+
Bizside.logger.info "キューに #{hash} がすでに登録されています。"
|
256
|
+
return true
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
false
|
261
|
+
end
|
262
|
+
private_class_method :already_in_jobs?
|
263
|
+
|
264
|
+
def self.rest_count(size, limit)
|
265
|
+
[[size - limit, 0].max, limit].min
|
266
|
+
end
|
267
|
+
private_class_method :rest_count
|
268
|
+
|
269
|
+
def self.failure_jobs(start = 0, count = 1, queue = nil)
|
270
|
+
if Bizside.rails_env&.test?
|
271
|
+
Bizside.logger.info 'テスト時は、ジョブ 0 件とします。'
|
272
|
+
return []
|
273
|
+
end
|
274
|
+
|
275
|
+
::Resque::Failure.all(start, count, queue)
|
276
|
+
end
|
277
|
+
|
278
|
+
def self.failure_count(queue = nil, class_name = nil)
|
279
|
+
return 0 if Bizside.rails_env&.test?
|
280
|
+
|
281
|
+
::Resque::Failure.count(queue, class_name)
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Bizside
|
2
|
+
class LogAnalyzer
|
3
|
+
attr_reader :add_on_name
|
4
|
+
attr_reader :error_contents
|
5
|
+
|
6
|
+
def initialize(add_on_name, files)
|
7
|
+
@add_on_name = add_on_name
|
8
|
+
@files = files
|
9
|
+
end
|
10
|
+
|
11
|
+
def analyze(output_file_name)
|
12
|
+
@success = system("request-log-analyzer --format rails3 --parse-strategy cautious --file #{output_file_name}.html --output HTML #{@files.join(' ')}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def success?
|
16
|
+
@success
|
17
|
+
end
|
18
|
+
|
19
|
+
def scrape_errors
|
20
|
+
@error_content = String.new
|
21
|
+
@error_contents = {}
|
22
|
+
|
23
|
+
# TODO Okozeを解析できるようにする
|
24
|
+
return if add_on_name == 'okoze'
|
25
|
+
|
26
|
+
# TODO ログ内で重複したエラーメッセージを除外する
|
27
|
+
return if ['amadai', 'webcam_api', 'seri', 'sushioke'].include?(add_on_name)
|
28
|
+
|
29
|
+
@files.each do |file|
|
30
|
+
content = File.read(file, encoding: 'utf-8')
|
31
|
+
content = content.encode('UTF-16BE', 'UTF-8', :invalid => :replace, :undef => :replace, :replace => '?').encode('UTF-8')
|
32
|
+
next unless content.include?('Completed 500') or content.include?('FATAL')
|
33
|
+
|
34
|
+
# ログをプロセス単位に分割
|
35
|
+
partition_contents = divide_into_pid(content)
|
36
|
+
# プロセス単位に分割したログからエラーを抽出
|
37
|
+
partition_content_errors = extract_error_log(partition_contents)
|
38
|
+
# 抽出したエラーを出力用にまとめる
|
39
|
+
partition_content_errors.each do |pid, pc|
|
40
|
+
@error_contents[pid] = "#{file}のエラー抽出結果\n\n\n" if @error_contents[pid].nil? or @error_contents[pid].empty?
|
41
|
+
@error_contents[pid] << pc
|
42
|
+
end
|
43
|
+
|
44
|
+
@error_contents
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def divide_into_pid(content)
|
49
|
+
pid = nil
|
50
|
+
ret = {}
|
51
|
+
content.each_line do |c|
|
52
|
+
s = c.scan(/#[0-9]+\]/)
|
53
|
+
pid = s.first.scan(/[0-9]+/).first unless s.empty?
|
54
|
+
ret[pid] = "" unless ret[pid]
|
55
|
+
ret[pid] << c
|
56
|
+
end
|
57
|
+
|
58
|
+
ret
|
59
|
+
end
|
60
|
+
|
61
|
+
def extract_error_log(partition_contents)
|
62
|
+
ret = {}
|
63
|
+
partition_contents.each do |pid, pc|
|
64
|
+
tmp = ""
|
65
|
+
pc.each_line do |line|
|
66
|
+
unless line.scan(/: Started /).empty?
|
67
|
+
if !tmp.scan(/Completed 500/).empty? or !tmp.scan(/\] FATAL/).empty? or !tmp.scan(/\[FATAL\]/).empty?
|
68
|
+
ret[pid] = "" if ret[pid].nil? or ret[pid].empty?
|
69
|
+
ret[pid] << tmp
|
70
|
+
end
|
71
|
+
tmp.clear
|
72
|
+
end
|
73
|
+
tmp << exclude_error_log_line(line)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Startedの前にログが終了した場合、その時点までにエラーが含まれていれば抽出に含める
|
77
|
+
if !tmp.empty? and !tmp.scan(/Completed 500/).empty? or !tmp.scan(/\] FATAL/).empty? or !tmp.scan(/\[FATAL\]/).empty?
|
78
|
+
ret[pid] = "" if ret[pid].nil? or ret[pid].empty?
|
79
|
+
ret[pid] << tmp
|
80
|
+
end
|
81
|
+
tmp.clear
|
82
|
+
end
|
83
|
+
|
84
|
+
ret
|
85
|
+
end
|
86
|
+
|
87
|
+
def exclude_error_log_line(line)
|
88
|
+
ret = nil
|
89
|
+
ret = line.match("INFO -- : ジョブ.*登録します。")
|
90
|
+
|
91
|
+
if ret.nil?
|
92
|
+
line
|
93
|
+
else
|
94
|
+
""
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# TODO 重複したエラーログを除外する
|
99
|
+
def get_duplicate_check_line(line)
|
100
|
+
ret = line.scan(/(INFO -- :.*|ERROR -- :.*|WARN -- :.*|FATAL -- :.*)/).first
|
101
|
+
ret = ret.gsub(/\" for .*/, "\"") unless ret.nil or ret.empty?
|
102
|
+
|
103
|
+
ret
|
104
|
+
end
|
105
|
+
|
106
|
+
# TODO 重複したエラーログを除外する
|
107
|
+
def duplicate_error_log?(extract_error_logs, duplicate_check_lines)
|
108
|
+
res = false
|
109
|
+
extract_error_logs.each do |eer|
|
110
|
+
tmp = false
|
111
|
+
duplicate_check_lines.each do |dcl|
|
112
|
+
tmp = eer.include?(dcl)
|
113
|
+
break unless tmp
|
114
|
+
end
|
115
|
+
res = tmp
|
116
|
+
break if res
|
117
|
+
end
|
118
|
+
|
119
|
+
res
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Bizside
|
2
|
+
module Mailer
|
3
|
+
|
4
|
+
def mail(headers={ })
|
5
|
+
headers = headers.merge(:delivery_method_options => Bizside.config.smtp_settings)
|
6
|
+
m = super
|
7
|
+
m.transport_encoding = '8bit'
|
8
|
+
m.from ||= Bizside.config.mail.from
|
9
|
+
m
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def set_priority_headers(priority)
|
15
|
+
get_priority_headers(priority).each do |key, value|
|
16
|
+
headers[key] = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def get_priority_headers(priority)
|
23
|
+
ret = {}
|
24
|
+
|
25
|
+
# Outlook、ThunderBird
|
26
|
+
ret['X-Priority'] = priority
|
27
|
+
|
28
|
+
# Notes
|
29
|
+
notes_priority = convert_priority_for_notes(priority)
|
30
|
+
if notes_priority
|
31
|
+
ret['Importance'] = notes_priority
|
32
|
+
end
|
33
|
+
|
34
|
+
ret
|
35
|
+
end
|
36
|
+
|
37
|
+
def convert_priority_for_notes(priority)
|
38
|
+
case priority.to_i
|
39
|
+
when 1
|
40
|
+
return 'High'
|
41
|
+
when 2
|
42
|
+
return 'High'
|
43
|
+
when 3
|
44
|
+
return 'Normal'
|
45
|
+
when 4
|
46
|
+
return 'Low'
|
47
|
+
when 5
|
48
|
+
return 'Low'
|
49
|
+
else
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|