batchbase 0.0.2

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.
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: