batchbase 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ *.lock
4
+ .bundle
5
+ .config
6
+ coverage
7
+ InstalledFiles
8
+ lib/bundler/man
9
+ pkg
10
+ rdoc
11
+ spec/reports
12
+ test/tmp
13
+ test/version_tmp
14
+ tmp
15
+
16
+ # YARD artifacts
17
+ .yardoc
18
+ _yardoc
19
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in batchbase.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/batchbase.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "batchbase/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "batchbase"
7
+ s.version = Batchbase::VERSION
8
+ s.authors = ["pacojp"]
9
+ s.email = ["paco.jp@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{oreore batch base class}
12
+ s.description = %q{oreore batch base class}
13
+ s.rubyforge_project = "batchbase"
14
+
15
+ s.add_dependency "sys-proctable","0.9.1"
16
+ s.add_dependency "kanamei_log_formatter","0.0.1"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ # specify any dependencies here; for example:
24
+ # s.add_development_dependency "rspec"
25
+ # s.add_runtime_dependency "rest-client"
26
+ end
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'batchbase'
3
+
4
+ # usage type 1
5
+
6
+ include Batchbase::Core
7
+ create_logger('/tmp/batchbase_test_sample1.log')
8
+
9
+ execute do
10
+ logger.info 'test'
11
+ logger.info env[:pid_file]
12
+ end
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'batchbase'
3
+
4
+ # usage type 2
5
+
6
+ class Batch
7
+ include Batchbase::Core
8
+
9
+ def proceed
10
+ opts = self.option_parser
11
+ opts.on("-f", "--favorite_number=value",
12
+ Integer,"favo"
13
+ ) do |v|
14
+ env[:favorite_number] = v
15
+ end
16
+
17
+ execute do
18
+ logger.info env.inspect
19
+ if env[:favorite_number]
20
+ logger.info env[:favorite_number].to_s
21
+ else
22
+ logger.info 'fovorite_number not set'
23
+ end
24
+ logger.info 'info message'
25
+ end
26
+ end
27
+ end
28
+
29
+ b = Batch.new
30
+ b.proceed
@@ -0,0 +1,27 @@
1
+
2
+ require 'rubygems'
3
+ require 'batchbase'
4
+
5
+ # usage type 3
6
+
7
+ include Batchbase::Core
8
+ create_logger('/tmp/batchbase_test_sample3.log')
9
+
10
+ def receive_signal(signal)
11
+ logger.info("receive signal #{signal}")
12
+ @stop = true
13
+ end
14
+
15
+ @stop = false
16
+
17
+ set_signal_observer(:receive_signal)
18
+
19
+ execute(:daemonize=>true) do
20
+ logger.info 'test'
21
+ logger.info env[:pid_file]
22
+ 3600.times do
23
+ logger.info Time.now.strftime("%Y/%m/%d %H:%M:%S")
24
+ sleep 1
25
+ break if @stop
26
+ end
27
+ end
@@ -0,0 +1,273 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'digest/md5'
3
+ require "optparse"
4
+ require 'sys/proctable'
5
+ require 'logger'
6
+ require 'kanamei_log_formatter'
7
+
8
+ module Batchbase
9
+ module Core
10
+
11
+ SIGNALS = [ :QUIT, :INT, :TERM, :USR1, :USR2, :HUP ]
12
+ #SIGNALS = [ :QUIT, :INT, :TERM ]
13
+
14
+ DOUBLE_PROCESS_CHECK__OK = 1
15
+ DOUBLE_PROCESS_CHECK__AUTO_RECOVERD = 2
16
+ DOUBLE_PROCESS_CHECK__NG = 0
17
+ DOUBLE_PROCESS_CHECK__STILL_RUNNING = -1
18
+
19
+ def option_parser
20
+ @__option_parser ||= OptionParser.new
21
+ end
22
+
23
+ def set_option_parser(v)
24
+ @__option_parser = v
25
+ end
26
+
27
+ def env
28
+ @__env ||= {}
29
+ end
30
+
31
+ def executed
32
+ @__executed
33
+ end
34
+
35
+ def pg_path;env[:pg_path];end
36
+
37
+ def pid_file;env[:pid_file];end
38
+
39
+ #
40
+ # loggerの出力をOFFにしたい場合は
41
+ # 引数を"/dev/null"で渡してください
42
+ #
43
+ def logger
44
+ @__logger ||= create_logger
45
+ end
46
+
47
+ #
48
+ # 内部保持をするロガーを新規作成
49
+ #
50
+ def create_logger(io=STDERR,log_level=Logger::INFO)
51
+ @__logger = Logger.new(io)
52
+ @__logger.formatter = Kanamei::LogFormatter.formatter
53
+ @__logger.level = log_level
54
+ @__logger
55
+ end
56
+
57
+ #
58
+ # 内部保持するロガーを引数にて設定
59
+ #
60
+ def set_logger(_logger)
61
+ @__logger = _logger
62
+ end
63
+
64
+ #
65
+ # ログを出力しないように設定(内部的にはログを出力するが、その向き先が/dev/nullって実装になってます)
66
+ #
67
+ def skip_logging
68
+ create_logger("/dev/null")
69
+ end
70
+
71
+ #
72
+ # 内部的には
73
+ # init
74
+ # parse_options
75
+ # execute_inner
76
+ # release
77
+ # の順にコールしてます
78
+ #
79
+ # [options]
80
+ # プログラムより指定するバッチ動作オプション(ハッシュ値)
81
+ # :double_process_check 初期値 true
82
+ # :auto_recover 初期値 false
83
+ #
84
+ def execute(options={},&process)
85
+ begin
86
+ init
87
+ logger.info "start script(#{pg_path})"
88
+ logger.debug "caller=#{caller}"
89
+ parse_options(options,ARGV)
90
+ result = double_process_check_and_create_pid_file
91
+ case result
92
+ when DOUBLE_PROCESS_CHECK__OK,DOUBLE_PROCESS_CHECK__AUTO_RECOVERD
93
+ if result == DOUBLE_PROCESS_CHECK__AUTO_RECOVERD
94
+ logger.warn "lock file still exists[pid=#{env[:old_pid_from_pid_file]}:file=#{pid_file}],but process does not found.Auto_recover enabled.so process continues"
95
+ end
96
+ execute_inner(&process)
97
+ when DOUBLE_PROCESS_CHECK__NG
98
+ logger.error "lock file still exists[pid=#{env[:old_pid_from_pid_file]}:file=#{pid_file}],but process does not found.Auto_recover disabled.so process can not continue"
99
+ when DOUBLE_PROCESS_CHECK__STILL_RUNNING
100
+ logger.warn "pid:#{env[:old_pid_from_pid_file]} still running"
101
+ else
102
+ raise 'must not happen'
103
+ end
104
+ rescue => e
105
+ logger.error e
106
+ ensure
107
+ release
108
+ logger.info "finish script (%1.3fsec)" % (Time.now - @__script_started_at)
109
+ end
110
+ end
111
+
112
+ module ClassMethods
113
+ def is_there_process(pid)
114
+ pid = pid.to_i
115
+ raise 'pid must be number' if pid == 0
116
+ process = Sys::ProcTable.ps(pid)
117
+ process != nil && process.state == 'run'
118
+ end
119
+ end
120
+
121
+ def self.included(mod)
122
+ # ModuleのインスタンスmodがAをincludeした際に呼び出され、
123
+ # A::ClassMethodsのインスタンスメソッドをmodに特異メソッドとして追加する。
124
+ mod.extend ClassMethods
125
+ end
126
+
127
+ def signal_observers
128
+ @__signal_observers ||= []
129
+ end
130
+
131
+ def set_signal_observer(method_name)
132
+ @__signal_observers ||= []
133
+ case method_name
134
+ when String
135
+ method_name = method_name.to_sym
136
+ when Symbol
137
+ else
138
+ raise ArgumentError.new('method_name must be String or Symbol')
139
+ end
140
+ @__signal_observers << method_name
141
+ end
142
+
143
+ private
144
+
145
+ def init
146
+ SIGNALS.each { |sig| trap(sig){r_signal(sig)} }
147
+ @__script_started_at = Time.now
148
+ raise 'already inited' if @__init
149
+ @__init = true
150
+ env[:pid] = $$
151
+ if File.expand_path(caller[0]) =~ /(.*):\d*:in `.*?'\z/
152
+ env[:pg_path] = $1
153
+ else
154
+ raise "must not happen!! can not get caller value"
155
+ end
156
+ end
157
+
158
+ def parse_options(options,argv)
159
+ env[:double_process_check] = options[:double_process_check]
160
+ env[:double_process_check] = true if env[:double_process_check] == nil
161
+ env[:auto_recover] = options[:auto_recover]
162
+ env[:auto_recover] = false if env[:auto_recover] == nil
163
+ env[:environment] = options[:environment] ||= 'development'
164
+ env[:pg_name] = File.basename(pg_path)
165
+ env[:pid_file] = options[:pid_file]
166
+ env[:daemonize] = options[:daemonize]
167
+ env[:daemonize] = false if env[:daemonize] == nil
168
+ env[:pid_file] ||= "/tmp/.#{env[:pg_name]}.#{Digest::MD5.hexdigest(pg_path)}.pid"
169
+
170
+ opts = option_parser
171
+
172
+ opts.on("-e", "--environment=name",
173
+ String,"specifies the environment",
174
+ "default: development") do |v|
175
+ env[:environment] = v
176
+ end
177
+
178
+ opts.on("-d", "--daemonize") do
179
+ env[:daemonize] = true
180
+ end
181
+
182
+ opts.on("-h","--help","show this help message.") { $stderr.puts opts; exit }
183
+
184
+ opts.on("--lockfile LOCK_FILE_PATH","set lock file path") do |v|
185
+ double_process_check = true
186
+ env[:pid_file] = v
187
+ end
188
+ opts.on("--double_process_check_off","disable double process check") do |v|
189
+ env[:double_process_check] = false
190
+ end
191
+ opts.on("--auto_recover","enable auto recover mode") do |v|
192
+ env[:auto_recover] = true
193
+ end
194
+
195
+ opts.parse!(argv)
196
+
197
+ if env[:auto_recover] == true
198
+ env[:double_process_check] = true
199
+ end
200
+ end
201
+
202
+ def double_process_check_and_create_pid_file
203
+ ret = DOUBLE_PROCESS_CHECK__OK
204
+ if env[:double_process_check]
205
+ double_process_check_worked = false
206
+ #pg_path = File.expand_path($0)
207
+ logger.debug pid_file
208
+ if File.exists?(pid_file)
209
+ pid = File.open(pid_file).read.chomp
210
+ env[:old_pid_from_pid_file] = pid
211
+ if (pid != nil && pid != "" ) && self.class.is_there_process(pid)
212
+ env[:double_process_check_problem] = true
213
+ return DOUBLE_PROCESS_CHECK__STILL_RUNNING
214
+ else
215
+ if env[:auto_recover]
216
+ ret = DOUBLE_PROCESS_CHECK__AUTO_RECOVERD
217
+ else
218
+ env[:double_process_check_problem] = true
219
+ return DOUBLE_PROCESS_CHECK__NG
220
+ end
221
+ end
222
+ end
223
+ File.open(pid_file, "w"){|f|f.write $$}
224
+ env[:double_process_check_worked] = double_process_check_worked
225
+ end
226
+ ret
227
+ end
228
+
229
+ def release
230
+ # 2重起動チェックで問題があった場合はpid_fileを消してはいけないので
231
+ unless env[:double_process_check_problem]
232
+ File.delete(pid_file) if pid_file && File.exist?(pid_file)
233
+ end
234
+ end
235
+
236
+ #
237
+ # receive_signal
238
+ # 一応名前がバッティングしないように、、
239
+ #
240
+ def r_signal(signal)
241
+ sent_signal = false
242
+ signal_observers.each do |method_name|
243
+ begin
244
+ self.send method_name,signal
245
+ sent_signal = true
246
+ rescue => e
247
+ message = "signal #{signal} received. but can not call '#{method_name}'"
248
+ env[:signal_error] = message
249
+ logger.error(message)
250
+ end
251
+ end
252
+
253
+ unless sent_signal
254
+ trap(signal,"DEFAULT")
255
+ Process.kill signal,$$
256
+ end
257
+ end
258
+
259
+ def execute_inner(&process)
260
+ @__executed = true
261
+ if env[:daemonize]
262
+ # HACKME logging
263
+ logger.info "daemonized"
264
+ env[:pid_old] = env[:pid]
265
+ Process.daemon
266
+ env[:pid] = Process.pid
267
+ File.open(pid_file, "w"){|f|f.write env[:pid]}
268
+ sleep 1
269
+ end
270
+ return yield(process)
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,3 @@
1
+ module Batchbase
2
+ VERSION = "0.0.2"
3
+ end
data/lib/batchbase.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "batchbase/version"
2
+
3
+ require "batchbase/core"
4
+
5
+ include Batchbase::Core
6
+
7
+ module Batchbase
8
+ end
data/readme.md ADDED
@@ -0,0 +1,11 @@
1
+
2
+ # batchbase
3
+
4
+ kanamei/keystoneからのポーティングです。
5
+
6
+ ## 基本的機能は
7
+
8
+ * 2重起動チェック、、、、ぐらいです
9
+
10
+ ### インストールはrake -Tで確認してください
11
+
data/test/batch.rb ADDED
@@ -0,0 +1,30 @@
1
+ class Batch
2
+ include Batchbase::Core
3
+ skip_logging
4
+
5
+ TEST_FILE = '/tmp/.batchbase_batch.txt'
6
+
7
+ def proceed(opt={})
8
+ @shutdown = false
9
+ set_signal_observer(:receive_signal)
10
+
11
+ execute(opt) do
12
+ sleep 2
13
+ File.write(TEST_FILE,$$)
14
+ if opt[:daemonize]
15
+ loop do
16
+ sleep 1
17
+ if @shutdown
18
+ #puts "shutdown by #{@shutdown}"
19
+ break
20
+ end
21
+ end
22
+ end
23
+ 11
24
+ end
25
+ end
26
+
27
+ def receive_signal(sig)
28
+ @shutdown = sig
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ class BatchTooLong
2
+ include Batchbase::Core
3
+
4
+ def proceed(opt={})
5
+ unless opt[:not_set_observer]
6
+ if opt[:signal_cancel]
7
+ set_signal_observer(:ignore_signal)
8
+ else
9
+ set_signal_observer(:receive_signal)
10
+ end
11
+ end
12
+ @shutdown = false
13
+ execute(opt) do
14
+ 100.times do
15
+ sleep 1
16
+ break if @shutdown
17
+ end
18
+ end
19
+ end
20
+
21
+ def receive_signal(sig)
22
+ @shutdown = true
23
+ end
24
+
25
+ def ignore_signal(sig)
26
+ end
27
+ end
data/test/by_hand.rb ADDED
@@ -0,0 +1,14 @@
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ $: << File.dirname(__FILE__)
5
+ require 'test_helper'
6
+
7
+ require 'batch'
8
+
9
+ b = Batch.new
10
+ b.set_signal_observer(:receive_signal)
11
+ b.proceed
12
+
13
+
14
+
@@ -0,0 +1,31 @@
1
+
2
+
3
+ # -*- coding: utf-8 -*-
4
+
5
+ $: << File.dirname(__FILE__)
6
+ require 'test_helper'
7
+
8
+ require 'batch'
9
+ require 'logger'
10
+
11
+ class CheckLogger
12
+ def self.check
13
+ logger = Logger.new(STDERR)
14
+ logger.formatter = Batchbase::LogFormatter.formatter
15
+ logger.info 'test'
16
+ logger.info 1
17
+ begin
18
+ raise 'some error'
19
+ rescue => e
20
+ logger.error e
21
+ end
22
+
23
+ logger = Logger.new("/dev/null")
24
+ logger.formatter = Batchbase::LogFormatter.formatter
25
+ logger.info 'should not show'
26
+ end
27
+ end
28
+
29
+ CheckLogger.check
30
+
31
+
data/test/test.rb ADDED
@@ -0,0 +1,321 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ $: << File.dirname(__FILE__)
4
+ require 'test_helper'
5
+ require 'test/unit'
6
+ require 'Fileutils'
7
+
8
+ #require 'bundler'
9
+ #Bundler.require
10
+
11
+ #require 'sys/proctable'
12
+
13
+ require 'batch'
14
+ require 'batch_too_long'
15
+
16
+ class TestBatchbase < Test::Unit::TestCase
17
+
18
+ PID_FILE_FORCE = '/tmp/.batchbase_test.pid'
19
+ PID_FILE_DAEMONIZE_TEST = '/tmp/.batchbase_daemonize_test.pid'
20
+
21
+ def setup
22
+ delete_file(pid_file)
23
+ delete_file(PID_FILE_FORCE)
24
+ delete_file(PID_FILE_DAEMONIZE_TEST)
25
+ delete_file(Batch::TEST_FILE)
26
+ end
27
+
28
+ def new_batch_instance
29
+ b = Batch.new
30
+ b.skip_logging
31
+ b
32
+ end
33
+
34
+ def delete_file(file)
35
+ File.delete(file) if File.exist?(file)
36
+ end
37
+
38
+ def pid_file
39
+ b = new_batch_instance
40
+ b.send(:init)
41
+ b.send(:parse_options,{},[])
42
+ b.env[:pid_file]
43
+ end
44
+
45
+ def test_pid_file
46
+ b = new_batch_instance
47
+ b.send(:init)
48
+ b.send(:parse_options,{},[])
49
+ b.send(:double_process_check_and_create_pid_file)
50
+ assert_equal true,File.exists?(b.env[:pid_file])
51
+ b.send(:release)
52
+ assert_equal false,File.exists?(b.env[:pid_file])
53
+ end
54
+
55
+ def test_there_was_lock_file
56
+ FileUtils.touch(pid_file) # すでにpid_fileがあるとして
57
+ b = new_batch_instance
58
+ b.send(:init)
59
+ b.send(:parse_options,{},[])
60
+ result = b.send(:double_process_check_and_create_pid_file)
61
+ assert_equal Batchbase::Core::DOUBLE_PROCESS_CHECK__NG,result
62
+ File.delete(pid_file)
63
+ end
64
+
65
+ def test_there_was_lock_file_but_not_double_cheking
66
+ FileUtils.touch(pid_file) # すでにpid_fileがあるとして
67
+ b = new_batch_instance
68
+ b.send(:init)
69
+ b.send(:parse_options,{:double_process_check=>false},[])
70
+ result = b.send(:double_process_check_and_create_pid_file)
71
+ assert_equal Batchbase::Core::DOUBLE_PROCESS_CHECK__OK,result
72
+ File.delete(pid_file)
73
+ end
74
+
75
+ def test_auto_recover
76
+ FileUtils.touch(pid_file) # すでにpid_fileがあるとして
77
+ b = new_batch_instance
78
+ b.send(:init)
79
+ b.send(:parse_options,{:auto_recover=>true},[])
80
+ result = b.send(:double_process_check_and_create_pid_file)
81
+ assert_equal Batchbase::Core::DOUBLE_PROCESS_CHECK__AUTO_RECOVER,result
82
+ assert_equal true,File.exists?(b.env[:pid_file]) # pid_fileは存在していないとだめ
83
+ File.delete(pid_file)
84
+ end
85
+
86
+ def test_auto_recover
87
+ b = new_batch_instance
88
+ b.send(:init)
89
+ b.send(:parse_options,{},[:auto_recover=>true])
90
+ b.send(:double_process_check_and_create_pid_file)
91
+ assert_equal true,File.exists?(b.env[:pid_file])
92
+ b.send(:release)
93
+ assert_equal false,File.exists?(b.env[:pid_file])
94
+ end
95
+
96
+ def test_option_parser
97
+ # ぎゃくにかいてもーた、、、、
98
+ b = new_batch_instance
99
+ b.send(:init)
100
+ argv = []
101
+ b.send(:parse_options,{},argv)
102
+ assert_equal b.env[:environment],'development'
103
+ assert_equal b.env[:double_process_check],true
104
+ assert_equal b.env[:auto_recover],false
105
+ assert_equal b.env[:pg_name],'test.rb'
106
+
107
+ b = new_batch_instance
108
+ b.send(:init)
109
+ argv = ['-e','test','--auto_recover']
110
+ b.send(:parse_options,{},argv)
111
+ assert_equal b.env[:environment],'test'
112
+ assert_equal b.env[:double_process_check],true
113
+ assert_equal b.env[:auto_recover],true
114
+
115
+ b = new_batch_instance
116
+ b.send(:init)
117
+ argv = ['--double_process_check_off']
118
+ b.send(:parse_options,{},argv)
119
+ assert_equal b.env[:double_process_check],false
120
+
121
+ # オートリカバリー入れたらダブルプロセスチェックは強制ON
122
+ b = new_batch_instance
123
+ b.send(:init)
124
+ argv = ['-e','test','--auto_recover','double_process_check_off']
125
+ b.send(:parse_options,{},argv)
126
+ assert_equal b.env[:environment],'test'
127
+ assert_equal b.env[:double_process_check],true
128
+ assert_equal b.env[:auto_recover],true
129
+
130
+ b = new_batch_instance
131
+ b.send(:init)
132
+ argv = ['--lockfile','/tmp/.lockfile_test']
133
+ b.send(:parse_options,{},argv)
134
+ assert_equal b.env[:pid_file],'/tmp/.lockfile_test'
135
+ end
136
+
137
+ def test_options
138
+ # ぎゃくにかいてもーた、、、、
139
+ b = new_batch_instance
140
+ b.send(:init)
141
+ argv = []
142
+ options = {:double_process_check=>false,:environment=>'test'}
143
+ b.send(:parse_options,options,argv)
144
+ assert_equal b.env[:environment],'test'
145
+ assert_equal b.env[:double_process_check],false
146
+ assert_equal b.env[:auto_recover],false
147
+ assert_equal b.env[:pg_name],'test.rb'
148
+
149
+ # オートリカバリー入れたらダブルプロセスチェックは強制ON
150
+ b = new_batch_instance
151
+ b.send(:init)
152
+ argv = []
153
+ options = {:double_process_check=>false,:auto_recover=>true}
154
+ b.send(:parse_options,options,argv)
155
+ assert_equal b.env[:double_process_check],true
156
+ assert_equal b.env[:auto_recover],true
157
+
158
+ b = new_batch_instance
159
+ b.send(:init)
160
+ argv = []
161
+ options = {:pid_file=>'/tmp/.lock_test'}
162
+ b.send(:parse_options,options,argv)
163
+ assert_equal b.env[:pid_file],'/tmp/.lock_test'
164
+
165
+ # ミックスならARGVの指定の方を優先
166
+ b = new_batch_instance
167
+ b.send(:init)
168
+ argv = ['--lockfile','/tmp/.lllock','--auto_recover']
169
+ options = {:pid_file=>'/tmp/.lock_test',:auto_recover=>false,:double_process_check=>false}
170
+ b.send(:parse_options,options,argv)
171
+ assert_equal b.env[:double_process_check],true
172
+ assert_equal b.env[:auto_recover],true
173
+ assert_equal b.env[:pid_file],'/tmp/.lllock'
174
+ end
175
+
176
+ def test_options_plus
177
+ b = new_batch_instance
178
+ opts = b.option_parser
179
+ opts.on("-f", "--favorite_number=value",
180
+ Integer,"your favorite number"
181
+ ) do |v|
182
+ b.env[:favorite_number] = v
183
+ end
184
+
185
+ b.send(:init)
186
+ argv = ['--favorite_number','11']
187
+ b.send(:parse_options,{},argv)
188
+ assert_equal 'development',b.env[:environment]
189
+ assert_equal true,b.env[:double_process_check]
190
+ assert_equal false,b.env[:auto_recover]
191
+ assert_equal 'test.rb',b.env[:pg_name]
192
+ assert_equal 11,b.env[:favorite_number]
193
+ end
194
+
195
+ def test_daemonize
196
+ pid = fork do
197
+ b = new_batch_instance
198
+ b.proceed(:daemonize=>true,:pid_file=>PID_FILE_DAEMONIZE_TEST)
199
+ end
200
+
201
+ sleep 1
202
+ #
203
+ # デーモン化すると
204
+ # ・pidが変わる
205
+ # ・ppidが1になるk
206
+ #
207
+ pid_new = File.read(PID_FILE_DAEMONIZE_TEST).chomp.to_i
208
+ assert_not_equal pid,pid_new
209
+ daemon_process = Sys::ProcTable.ps(pid_new)
210
+ assert_equal 1,daemon_process.ppid
211
+ sleep 3
212
+ assert_equal true,Batch.is_there_process(pid_new)
213
+ # デーモン化したスクリプトから書き込んだ自身のpidがこちらで認識しているpidと同一化の確認
214
+ assert_equal pid_new,File.read(Batch::TEST_FILE).chomp.to_i
215
+ # シグナルを送る
216
+ # pid_fileを消して終了するか?
217
+ `kill #{pid_new}`
218
+ sleep 3
219
+ assert_equal false,Batch.is_there_process(pid_new)
220
+ assert_equal false,File.exists?(PID_FILE_DAEMONIZE_TEST)
221
+ end
222
+
223
+ def test_is_there_process
224
+ assert_equal true,Batch.is_there_process($$)
225
+ assert_equal false,Batch.is_there_process(1111111111)
226
+ end
227
+
228
+ def test_signal
229
+ assert_equal false,File.exists?(PID_FILE_FORCE)
230
+ pid = fork do
231
+ b = BatchTooLong.new
232
+ b.skip_logging
233
+ b.proceed(:pid_file=>PID_FILE_FORCE)
234
+ end
235
+ sleep 3
236
+ pid_by_file = File.read(PID_FILE_FORCE).chomp.to_i
237
+ assert_equal true,Batch.is_there_process(pid)
238
+ assert_equal pid,pid_by_file
239
+ # シグナルを送る
240
+ # pid_fileを消して終了するか?
241
+ `kill #{pid}`
242
+ sleep 3
243
+ assert_equal false,Batch.is_there_process(pid)
244
+ assert_equal false,File.exists?(PID_FILE_FORCE)
245
+ end
246
+
247
+ #
248
+ # オブザーバーを設定していない場合は
249
+ # デフォルトの挙動をするように変更して
250
+ # もう一度同様のシグナルを受ける
251
+ #
252
+ def test_signal_observer_not_set
253
+ assert_equal false,File.exists?(PID_FILE_FORCE)
254
+ pid = fork do
255
+ b = BatchTooLong.new
256
+ b.skip_logging
257
+ b.proceed(:pid_file=>PID_FILE_FORCE,:not_set_observer=>true)
258
+ end
259
+ sleep 3
260
+ pid_by_file = File.read(PID_FILE_FORCE).chomp.to_i
261
+ assert_equal true,Batch.is_there_process(pid)
262
+ assert_equal pid,pid_by_file
263
+ `kill #{pid}`
264
+ sleep 3
265
+ # 普通に終了すべき
266
+ assert_equal false,Batch.is_there_process(pid)
267
+ assert_equal false,File.exists?(PID_FILE_FORCE)
268
+ end
269
+
270
+ # 特に何もしないシグナルハンドラーを設定すると
271
+ def test_signal_ignore
272
+ assert_equal false,File.exists?(PID_FILE_FORCE)
273
+ pid = fork do
274
+ b = BatchTooLong.new
275
+ b.skip_logging
276
+ b.proceed(:pid_file=>PID_FILE_FORCE,:signal_cancel=>true)
277
+ end
278
+ sleep 3
279
+ pid_by_file = File.read(PID_FILE_FORCE).chomp.to_i
280
+ assert_equal true,Batch.is_there_process(pid)
281
+ assert_equal pid,pid_by_file
282
+ `kill #{pid}`
283
+ sleep 3
284
+ # 終了しない
285
+ assert_equal true,Batch.is_there_process(pid)
286
+ assert_equal true,File.exists?(PID_FILE_FORCE)
287
+ `kill -9 #{pid}`
288
+ sleep 3
289
+ # 終了するがpidファイルは残る
290
+ assert_equal false,Batch.is_there_process(pid)
291
+ assert_equal true,File.exists?(PID_FILE_FORCE)
292
+ end
293
+
294
+ # すでにバッチ起動&プロセスがまだ存在する場合のテスト
295
+ def test_prosess_still_exists
296
+ pid = fork do
297
+ b = new_batch_instance
298
+ b.proceed(:pid_file=>PID_FILE_FORCE)
299
+ end
300
+
301
+ sleep 1
302
+
303
+ b2 = new_batch_instance
304
+ b2.send(:init)
305
+ b2.send(:parse_options,{:pid_file=>PID_FILE_FORCE},[])
306
+ result = b2.send(:double_process_check_and_create_pid_file)
307
+ assert_equal Batch::DOUBLE_PROCESS_CHECK__STILL_RUNNING,result
308
+ #b2.send(:execute_inner)
309
+ b2.send(:release)
310
+ # pid_fileまだは存在していないとだめ
311
+ assert_equal true,File.exists?(b2.env[:pid_file])
312
+ sleep 2
313
+ end
314
+
315
+ #
316
+ # HACKME
317
+ # executeを読んだ際のメッセージ文言等でエラーが出る場合のフック、、、
318
+ # 実際はexecuteをシュミレートしたテストしかしていない&log出力も
319
+ # 切ってるので、、、、、、
320
+ #
321
+ end
@@ -0,0 +1,5 @@
1
+ $: << File.dirname(__FILE__) + '/../lib'
2
+ #require File.dirname(__FILE__) + '/../lib/image_convert_lite'
3
+
4
+ require 'batchbase'
5
+ require 'batchbase/version'
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: batchbase
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - pacojp
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sys-proctable
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - '='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - '='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.9.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: kanamei_log_formatter
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - '='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.0.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.0.1
46
+ description: oreore batch base class
47
+ email:
48
+ - paco.jp@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - Rakefile
56
+ - batchbase.gemspec
57
+ - example/sample1.rb
58
+ - example/sample2.rb
59
+ - example/sample3.rb
60
+ - lib/batchbase.rb
61
+ - lib/batchbase/core.rb
62
+ - lib/batchbase/version.rb
63
+ - readme.md
64
+ - test/batch.rb
65
+ - test/batch_too_long.rb
66
+ - test/by_hand.rb
67
+ - test/check_logger.rb
68
+ - test/test.rb
69
+ - test/test_helper.rb
70
+ homepage: ''
71
+ licenses: []
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project: batchbase
90
+ rubygems_version: 1.8.23
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: oreore batch base class
94
+ test_files:
95
+ - test/batch.rb
96
+ - test/batch_too_long.rb
97
+ - test/by_hand.rb
98
+ - test/check_logger.rb
99
+ - test/test.rb
100
+ - test/test_helper.rb
101
+ has_rdoc: