bricolage 5.23.3 → 5.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bricolage/application.rb +160 -37
  3. data/lib/bricolage/commandlineapplication.rb +0 -0
  4. data/lib/bricolage/commandutils.rb +0 -20
  5. data/lib/bricolage/context.rb +19 -4
  6. data/lib/bricolage/job.rb +38 -38
  7. data/lib/bricolage/jobfile.rb +2 -1
  8. data/lib/bricolage/jobnet.rb +21 -3
  9. data/lib/bricolage/jobnetrunner.rb +102 -62
  10. data/lib/bricolage/logfilepath.rb +2 -2
  11. data/lib/bricolage/loglocator.rb +71 -0
  12. data/lib/bricolage/loglocatorbuilder.rb +29 -0
  13. data/lib/bricolage/psqldatasource.rb +1 -1
  14. data/lib/bricolage/s3writer.rb +22 -0
  15. data/lib/bricolage/version.rb +1 -1
  16. data/test/home/Gemfile.lock +41 -0
  17. data/test/home/config/bricolage.yml +3 -0
  18. data/test/home/config/development/database.yml +113 -0
  19. data/test/home/config/development/password.yml +6 -0
  20. data/test/home/config/development/variable.yml +7 -0
  21. data/test/home/config/streamingload.yml +8 -0
  22. data/test/home/log/20170117/subsys::job1/20170117_202014082/subsys-job1.log +3 -0
  23. data/test/home/log/20170117/subsys::job1/20170117_202334852/subsys-job1.log +3 -0
  24. data/test/home/log/20170117/subsys::job1/20170117_202405056/subsys-job1.log +3 -0
  25. data/test/home/log/20170117/subsys::migrate/20170117_202548409/subsys-migrate.log +80 -0
  26. data/test/home/log/20170117/subsys::migrate/20170117_202636115/subsys-migrate.log +79 -0
  27. data/test/home/log/20170117/subsys::net1/20170117_203022461/subsys-job1.log +3 -0
  28. data/test/home/log/20170117/subsys::net1/20170117_203022461/subsys-job2.log +3 -0
  29. data/test/home/log/20170117/subsys::net1/20170117_203022461/subsys-job3.log +3 -0
  30. data/test/home/log/20170117/subsys::net1/20170117_203022461/subsys-job4.log +3 -0
  31. data/test/home/log/20170117/subsys::net1/20170117_203102130/subsys-job1.log +3 -0
  32. data/test/home/log/20170117/subsys::net1/20170117_203102130/subsys-job2.log +3 -0
  33. data/test/home/log/20170117/subsys::net1/20170117_203102130/subsys-job3.log +3 -0
  34. data/test/home/log/20170117/subsys::net1/20170117_203102130/subsys-job4.log +3 -0
  35. data/test/home/log/20170117/subsys::net1/20170117_203232033/subsys-job1.log +3 -0
  36. data/test/home/log/20170117/subsys::net1/20170117_203232033/subsys-job2.log +3 -0
  37. data/test/home/log/20170117/subsys::net1/20170117_203232033/subsys-job3.log +3 -0
  38. data/test/home/log/20170117/subsys::net1/20170117_203232033/subsys-job4.log +3 -0
  39. data/test/home/log/20170629/subsys::job1/20170629_155543985/subsys-job1.log +3 -0
  40. data/test/home/log/20170629/subsys::net1/20170629_154308811/subsys-job1.log +3 -0
  41. data/test/home/log/20170629/subsys::net1/20170629_154308811/subsys-job2.log +3 -0
  42. data/test/home/log/20170629/subsys::net1/20170629_154308811/subsys-job3.log +3 -0
  43. data/test/home/log/20170629/subsys::net1/20170629_154308811/subsys-job4.log +3 -0
  44. data/test/home/log/20170629/subsys::net1/20170629_155330208/subsys-job1.log +3 -0
  45. data/test/home/log/20170629/subsys::net1/20170629_155330208/subsys-job2.log +3 -0
  46. data/test/home/log/20170629/subsys::net1/20170629_155330208/subsys-job3.log +3 -0
  47. data/test/home/log/20170629/subsys::net1/20170629_155330208/subsys-job4.log +3 -0
  48. data/test/home/log/20170630/subsys::net1/20170630_145523511/subsys-job1.log +3 -0
  49. data/test/home/log/20170630/subsys::net1/20170630_145523511/subsys-job2.log +3 -0
  50. data/test/home/log/20170630/subsys::net1/20170630_145523511/subsys-job3.log +3 -0
  51. data/test/home/log/20170630/subsys::net1/20170630_145523511/subsys-job4.log +3 -0
  52. data/test/home/log/20170630/subsys::net1/20170630_145545097/subsys-job1.log +3 -0
  53. data/test/home/log/20170630/subsys::net1/20170630_145545097/subsys-job2.log +3 -0
  54. data/test/home/log/20170630/subsys::net1/20170630_145545097/subsys-job3.log +3 -0
  55. data/test/home/log/20170630/subsys::net1/20170630_145545097/subsys-job4.log +3 -0
  56. data/test/home/log/20170630/subsys::net1/20170630_145615702/subsys-job1.log +3 -0
  57. data/test/home/log/20170630/subsys::net1/20170630_145615702/subsys-job2.log +3 -0
  58. data/test/home/log/20170630/subsys::net1/20170630_145615702/subsys-job3.log +3 -0
  59. data/test/home/log/20170630/subsys::net1/20170630_145615702/subsys-job4.log +3 -0
  60. data/test/home/log/20170630/subsys::net1/20170630_153437221/subsys-job1.log +3 -0
  61. data/test/home/log/20170630/subsys::net1/20170630_153507519/subsys-job1.log +3 -0
  62. data/test/home/log/20170630/subsys::net1/20170630_153507519/subsys-job2.log +3 -0
  63. data/test/home/log/20170630/subsys::net1/20170630_153507519/subsys-job3.log +3 -0
  64. data/test/home/log/20170630/subsys::net1/20170630_153507519/subsys-job4.log +3 -0
  65. data/test/home/log/20170704/subsys::insert.sql.job/20170704_163033119/subsys-insert.log +14 -0
  66. data/test/home/log/20170704/subsys::insert.sql.job/20170704_172410576/subsys-insert.log +14 -0
  67. data/test/home/log/20170704/subsys::insert.sql.job/20170704_173130175/subsys-insert.log +14 -0
  68. data/test/home/log/20170704/subsys::insert.sql.job/20170704_173201376/subsys-insert.log +14 -0
  69. data/test/home/log/20170704/subsys::insert.sql/20170704_164143661/subsys-insert.sql.log +14 -0
  70. data/test/home/log/20170704/subsys::insert/20170704_164335210/subsys-insert.log +14 -0
  71. data/test/home/log/20170704/subsys::insert/20170704_164344251/subsys-insert.log +14 -0
  72. data/test/home/log/20170704/subsys::insert/20170704_164723299/subsys-insert.log +14 -0
  73. data/test/home/log/20170704/subsys::net1/20170704_162457694/subsys-job1.log +3 -0
  74. data/test/home/log/20170704/subsys::net1/20170704_162544282/subsys-job1.log +3 -0
  75. data/test/home/log/20170704/subsys::net1/20170704_162544282/subsys-job2.log +3 -0
  76. data/test/home/log/20170704/subsys::net1/20170704_162544282/subsys-job3.log +3 -0
  77. data/test/home/log/20170704/subsys::net1/20170704_162544282/subsys-job4.log +3 -0
  78. data/test/home/log/20170706/subsys::net1/20170706_201157129/subsys-job1.log +3 -0
  79. data/test/home/log/20170706/subsys::net1/20170706_201157129/subsys-job2.log +3 -0
  80. data/test/home/log/20170706/subsys::net1/20170706_201157129/subsys-job3.log +3 -0
  81. data/test/home/log/20170706/subsys::net1/20170706_201157129/subsys-job4.log +3 -0
  82. data/test/home/log/20170707/subsys::insert/20170707_020050817/subsys-insert.log +51 -0
  83. data/test/home/log/20170707/subsys::insert/20170707_020050817/subsys-insert.log.status +1 -0
  84. data/test/home/log/20170707/subsys::job1/20170707_020542902/subsys-job1.log +3 -0
  85. data/test/home/log/20170707/subsys::net1/20170707_012252058/subsys-job1.log +3 -0
  86. data/test/home/log/20170707/subsys::net1/20170707_012252058/subsys-job2.log +3 -0
  87. data/test/home/log/20170707/subsys::net1/20170707_012252058/subsys-job3.log +3 -0
  88. data/test/home/log/20170707/subsys::net1/20170707_012252058/subsys-job4.log +3 -0
  89. data/test/home/log/20170707/subsys::net1/20170707_020039222/subsys-job1.log +3 -0
  90. data/test/home/log/20170707/subsys::net1/20170707_020039222/subsys-job2.log +3 -0
  91. data/test/home/log/20170707/subsys::net1/20170707_020039222/subsys-job3.log +3 -0
  92. data/test/home/log/20170707/subsys::net1/20170707_020039222/subsys-job4.log +3 -0
  93. data/test/home/revert.sh +7 -0
  94. data/test/home/s +1 -0
  95. metadata +125 -43
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 23ebf2fa74d99d152e388d57872332cd013fcd73
4
- data.tar.gz: 73a60961068be073e8833cd1d73769982e25b486
3
+ metadata.gz: f06abf75b09a7c9188d54ca938ccca52e8f122b5
4
+ data.tar.gz: 59c808715776490dc3374ef141528c3dc1d61960
5
5
  SHA512:
6
- metadata.gz: e7f1556d282e2ad26385bdb42c4133280208af22ab5098702384dda235a423ed15569dab1d596185654647e9e48db003191883229a092a1fd9c2f4bfc873631a
7
- data.tar.gz: 36b056529ae9ea99fd4318d30ef159a8b4dfd2b2936fb62e0987e81f620b9be5665a79c114f963a9fffb3bb460df894d52946ed4122e13cc13a4024434a992f5
6
+ metadata.gz: ee5d6895a71111e135885180841cc2c5518cf7fc822bdad0ea576c84a5f77fccade1a3f0f8d68ab3240c3e9cc4d21e01798c685f73e3e8fc114ed6997daf69e2
7
+ data.tar.gz: df04ca26661704bc676ee26afcbe1d9bc2940bfbd97bd8c70f42725ee4ccf5842046903620f1e87471ffd97bdbeec9059a8b61c42de0dda37142df9692d067cb
@@ -8,6 +8,7 @@ require 'bricolage/datasource'
8
8
  require 'bricolage/eventhandlers'
9
9
  require 'bricolage/postgresconnection'
10
10
  require 'bricolage/logfilepath'
11
+ require 'bricolage/loglocatorbuilder'
11
12
  require 'bricolage/logger'
12
13
  require 'bricolage/exception'
13
14
  require 'bricolage/version'
@@ -36,15 +37,26 @@ module Bricolage
36
37
  def main
37
38
  opts = GlobalOptions.new(self)
38
39
  @hooks.run_before_option_parsing_hooks(opts)
39
- opts.parse ARGV
40
+ opts.parse!(ARGV)
41
+
40
42
  @ctx = Context.for_application(opts.home, opts.job_file, environment: opts.environment, global_variables: opts.global_variables)
43
+ opts.merge_saved_options(@ctx.load_system_options)
44
+
45
+ if opts.dump_options?
46
+ opts.option_pairs.each do |name, value|
47
+ puts "#{name}=#{value.inspect}"
48
+ end
49
+ exit 0
50
+ end
41
51
  if opts.list_global_variables?
42
52
  list_variables @ctx.global_variables.resolve
43
53
  exit 0
44
54
  end
55
+
45
56
  job = load_job(@ctx, opts)
46
- process_job_options job, opts
57
+ process_job_options(job, opts)
47
58
  job.compile
59
+
48
60
  if opts.list_declarations?
49
61
  list_declarations job.declarations
50
62
  exit 0
@@ -62,11 +74,11 @@ module Bricolage
62
74
  exit 0
63
75
  end
64
76
 
77
+ @log_locator_builder = LogLocatorBuilder.for_options(@ctx, opts.log_path_format, opts.log_s3_ds, opts.log_s3_key_format)
78
+
65
79
  @hooks.run_before_all_jobs_hooks(BeforeAllJobsEvent.new(job.id, [job]))
66
80
  @hooks.run_before_job_hooks(BeforeJobEvent.new(job))
67
- result = redirect_log_to_file(opts.log_path, job) {
68
- job.execute
69
- }
81
+ result = job.execute(log_locator: build_log_locator(job))
70
82
  @hooks.run_after_job_hooks(AfterJobEvent.new(result))
71
83
  @hooks.run_after_all_jobs_hooks(AfterAllJobsEvent.new(result.success?, [job]))
72
84
  exit result.status
@@ -78,28 +90,13 @@ module Bricolage
78
90
  error_exit ex.message
79
91
  end
80
92
 
81
- def redirect_log_to_file(log_path, job)
82
- return yield unless log_path
83
-
84
- path = log_path.format(
93
+ def build_log_locator(job)
94
+ @log_locator_builder.build(
85
95
  job_ref: JobNet::JobRef.new(job.subsystem, job.id, '-'),
86
96
  jobnet_id: "#{job.subsystem}/#{job.id}",
87
97
  job_start_time: @start_time,
88
98
  jobnet_start_time: @start_time
89
99
  )
90
- FileUtils.mkdir_p File.dirname(path)
91
- stdout_save = $stdout.dup
92
- stderr_save = $stderr.dup
93
- begin
94
- File.open(path, 'w+') {|f|
95
- $stdout.reopen f
96
- $stderr.reopen f
97
- }
98
- return yield
99
- ensure
100
- $stdout.reopen stdout_save; stdout_save.close
101
- $stderr.reopen stderr_save; stderr_save.close
102
- end
103
100
  end
104
101
 
105
102
  def load_job(ctx, opts)
@@ -175,7 +172,124 @@ module Bricolage
175
172
  end
176
173
  end
177
174
 
178
- class GlobalOptions
175
+ class CommonApplicationOptions
176
+ OptionValue = Struct.new(:location, :value)
177
+ class OptionValue
178
+ def inspect
179
+ if location
180
+ "#{value.inspect} (#{location})"
181
+ else
182
+ value.inspect
183
+ end
184
+ end
185
+ end
186
+
187
+ def init_options
188
+ @opts = nil # valid only after #parse!
189
+ @opts_default = opts_default()
190
+ @opts_saved = {}
191
+ @opts_env = opts_env()
192
+ @opts_cmdline = {}
193
+ @parser = OptionParser.new
194
+ define_options @parser
195
+ end
196
+ private :init_options
197
+
198
+ attr_reader :parser
199
+
200
+ def opts_default
201
+ {
202
+ 'log-path' => OptionValue.new('default value', nil),
203
+ 'log-dir' => OptionValue.new('default value', nil),
204
+ 's3-log' => OptionValue.new('default value', nil)
205
+ }
206
+ end
207
+ private :opts_default
208
+
209
+ def opts_env
210
+ env = {}
211
+ if path = ENV['BRICOLAGE_LOG_PATH']
212
+ env['log-path'] = OptionValue.new('env BRICOLAGE_LOG_PATH', path)
213
+ end
214
+ if path = ENV['BRICOLAGE_LOG_DIR']
215
+ env['log-dir'] = OptionValue.new('env BRICOLAGE_LOG_DIR', path)
216
+ end
217
+ env
218
+ end
219
+ private :opts_env
220
+
221
+ # abstract :define_options
222
+
223
+ def define_common_options
224
+ @parser.on('-L', '--log-dir=PATH', 'Log file prefix.') {|path|
225
+ @opts_cmdline['log-dir'] = OptionValue.new('--log-dir option', path)
226
+ }
227
+ @parser.on('--log-path=PATH', 'Log file path template.') {|path|
228
+ @opts_cmdline['log-path'] = OptionValue.new('--log-path option', path)
229
+ }
230
+ @parser.on('--s3-log=DS_KEY', 'S3 log file. (format: "DS:KEY")') {|spec|
231
+ @opts_cmdline['s3-log'] = OptionValue.new('--s3-log option', spec)
232
+ }
233
+ end
234
+ private :define_common_options
235
+
236
+ def merge_saved_options(vars)
237
+ saved = {}
238
+ @opts_default.keys.each do |key|
239
+ if val = vars.get_force(key)
240
+ saved[key] = OptionValue.new("bricolage.yml:#{key}", val)
241
+ end
242
+ end
243
+ @opts_saved = saved
244
+ build_common_options!
245
+ end
246
+
247
+ def build_common_options!
248
+ @opts = [@opts_default, @opts_saved, @opts_env, @opts_cmdline].inject({}) {|h, opts| h.update(opts); h }
249
+ end
250
+ private :build_common_options!
251
+
252
+ #
253
+ # Accessors
254
+ #
255
+
256
+ def common_options
257
+ @opts
258
+ end
259
+
260
+ def log_path_format
261
+ if opt = @opts['log-dir']
262
+ LogFilePath.new("#{opt.value}/%{std}.log")
263
+ elsif opt = @opts['log-path']
264
+ LogFilePath.new(opt.value)
265
+ else
266
+ nil
267
+ end
268
+ end
269
+
270
+ def log_s3_ds
271
+ s3_log_spec.first
272
+ end
273
+
274
+ def log_s3_key_format
275
+ s3_log_spec.last
276
+ end
277
+
278
+ def s3_log_spec
279
+ @s3_log_spec ||=
280
+ if opt = @opts['s3-log']
281
+ spec = opt.value
282
+ ds, k = spec.split(':', 2)
283
+ k = k.to_s.strip
284
+ key = k.empty? ? nil : k
285
+ [ds, LogFilePath.new(key || '%{std}.log')]
286
+ else
287
+ [nil, nil]
288
+ end
289
+ end
290
+ end
291
+
292
+ class GlobalOptions < CommonApplicationOptions
179
293
  def initialize(app)
180
294
  @app = app
181
295
  @job_file = nil
@@ -184,16 +298,13 @@ module Bricolage
184
298
  @global_variables = Variables.new
185
299
  @dry_run = false
186
300
  @explain = false
187
- @log_path = LogFilePath.default
188
301
  @list_global_variables = false
189
302
  @list_variables = false
190
303
  @list_declarations = false
191
- @parser = OptionParser.new
192
- define_options @parser
304
+ @dump_options = false
305
+ init_options
193
306
  end
194
307
 
195
- attr_reader :parser
196
-
197
308
  def help
198
309
  @parser.help
199
310
  end
@@ -220,12 +331,9 @@ Global Options:
220
331
  parser.on('-E', '--explain', 'Applies EXPLAIN to the SQL.') {
221
332
  @explain = true
222
333
  }
223
- parser.on('-L', '--log-dir=PATH', 'Log file prefix.') {|path|
224
- @log_path = LogFilePath.new("#{path}/%{std}.log")
225
- }
226
- parser.on('--log-path=PATH', 'Log file path template.') {|path|
227
- @log_path = LogFilePath.new(path)
228
- }
334
+
335
+ define_common_options
336
+
229
337
  parser.on('--list-job-class', 'Lists job class name and (internal) class path.') {
230
338
  JobClass.list.each do |name|
231
339
  puts name
@@ -248,6 +356,9 @@ Global Options:
248
356
  name, value = name_value.split('=', 2)
249
357
  @global_variables[name] = value
250
358
  }
359
+ parser.on('--dump-options', 'Shows option parsing result and quit.') {
360
+ @dump_options = true
361
+ }
251
362
  parser.on('--help', 'Shows this message and quit.') {
252
363
  puts parser.help
253
364
  exit 0
@@ -262,19 +373,18 @@ Global Options:
262
373
  @parser.on(*args, &block)
263
374
  end
264
375
 
265
- def parse(argv)
376
+ def parse!(argv)
266
377
  @parser.order! argv
267
378
  @rest_args = argv.dup
379
+ build_common_options!
268
380
  rescue OptionParser::ParseError => ex
269
381
  raise OptionError, ex.message
270
382
  end
271
383
 
272
384
  attr_reader :environment
273
385
  attr_reader :home
274
- attr_reader :global_variables
275
386
 
276
387
  attr_reader :job_file
277
- attr_reader :log_path
278
388
 
279
389
  def file_mode?
280
390
  !!@job_file
@@ -288,6 +398,12 @@ Global Options:
288
398
  @explain
289
399
  end
290
400
 
401
+ def dump_options?
402
+ @dump_options
403
+ end
404
+
405
+ attr_reader :global_variables
406
+
291
407
  def list_global_variables?
292
408
  @list_global_variables
293
409
  end
@@ -299,6 +415,13 @@ Global Options:
299
415
  def list_declarations?
300
416
  @list_declarations
301
417
  end
418
+
419
+ def option_pairs
420
+ common_options.merge({
421
+ 'environment' => OptionValue.new(nil, @environment),
422
+ 'home' => OptionValue.new(nil, @home)
423
+ })
424
+ end
302
425
  end
303
426
 
304
427
  end
File without changes
@@ -27,26 +27,6 @@ module Bricolage
27
27
  def new_tmpfile_path(tmpdir = Dir.tmpdir)
28
28
  "#{tmpdir}/#{Time.now.to_i}_#{$$}_#{'%x' % Thread.current.object_id}_#{rand(2**16)}"
29
29
  end
30
-
31
- # CLUDGE: FIXME: bricolage-jobnet command writes stderr to the file, we can find error messages from there.
32
- # Using a temporary file or Ruby SQL driver is **MUCH** better.
33
- def retrieve_last_match_from_stderr(re, nth = 0)
34
- return unless $stderr.stat.file?
35
- $stderr.flush
36
- f = $stderr.dup
37
- matched = nil
38
- begin
39
- f.seek(0)
40
- f.each do |line|
41
- m = line.slice(re, nth)
42
- matched = m if m
43
- end
44
- ensure
45
- f.close
46
- end
47
- matched = matched.to_s.strip
48
- matched.empty? ? nil : matched
49
- end
50
30
  end
51
31
 
52
32
  end
@@ -84,6 +84,16 @@ module Bricolage
84
84
  :parameter_file,
85
85
  :parameter_file_loader
86
86
 
87
+ #
88
+ # System Parameters
89
+ #
90
+
91
+ SYSTEM_OPTION_FILE = 'bricolage.yml'
92
+
93
+ def load_system_options
94
+ load_variables_for_all_scopes(SYSTEM_OPTION_FILE)
95
+ end
96
+
87
97
  #
88
98
  # Variables
89
99
  #
@@ -103,15 +113,20 @@ module Bricolage
103
113
  }
104
114
  end
105
115
 
116
+ GLOBAL_VARIABLE_FILE = 'variable.yml'
117
+
106
118
  def load_global_variables
107
- subsys_path = scoped? ? [@filesystem.relative(GLOBAL_VARIABLE_FILE)] : []
108
- vars_list = (config_pathes(GLOBAL_VARIABLE_FILE) + subsys_path).map {|path|
119
+ load_variables_for_all_scopes(GLOBAL_VARIABLE_FILE)
120
+ end
121
+
122
+ def load_variables_for_all_scopes(basename)
123
+ subsys_path = scoped? ? [@filesystem.relative(basename)] : []
124
+ vars_list = (config_pathes(basename) + subsys_path).map {|path|
109
125
  path.exist? ? load_variables(path) : nil
110
126
  }
111
127
  Variables.union(*vars_list.compact)
112
128
  end
113
-
114
- GLOBAL_VARIABLE_FILE = 'variable.yml'
129
+ private :load_variables_for_all_scopes
115
130
 
116
131
  def load_variables(path)
117
132
  Variables.define {|vars|
data/lib/bricolage/job.rb CHANGED
@@ -55,7 +55,8 @@ module Bricolage
55
55
  end
56
56
 
57
57
  def init_global_variables
58
- # Context#global_variables loads file on each call, fix global variables here.
58
+ # Context#global_variables loads file on each call,
59
+ # updating @global_variables is multi-thread safe.
59
60
  @global_variables = @context.global_variables
60
61
  @global_variables['bricolage_cwd'] = Dir.pwd
61
62
  @global_variables['bricolage_job_dir'] = @context.job_dir.to_s
@@ -135,7 +136,26 @@ module Bricolage
135
136
  @script.run_explain
136
137
  end
137
138
 
138
- def execute
139
+ def execute(log_locator: LogLocator.empty)
140
+ log_locator.redirect_stdouts {
141
+ do_execute
142
+ }
143
+ end
144
+
145
+ def execute_in_process(log_locator:)
146
+ # ??? FIXME: status_path should be independent from log_path.
147
+ # Also, status_path should be defined regardless of log_path.
148
+ status_path = log_locator.path ? "#{log_locator.path}.status" : nil
149
+ isolate_process(status_path) {
150
+ log_locator.redirect_stdouts {
151
+ do_execute
152
+ }
153
+ }
154
+ end
155
+
156
+ private
157
+
158
+ def do_execute
139
159
  ENV['BRICOLAGE_PID'] = Process.pid.to_s
140
160
  logger = @context.logger
141
161
  logger.info "#{@context.environment} environment"
@@ -154,60 +174,40 @@ module Bricolage
154
174
  return JobResult.error(ex)
155
175
  end
156
176
 
157
- def execute_in_process(log_path)
158
- isolate(log_path) {
159
- execute
160
- }
161
- end
162
-
163
- private
164
-
165
- def isolate(log_path)
177
+ def isolate_process(status_path)
166
178
  cpid = Process.fork {
167
179
  Process.setproctitle "bricolage [#{@id}]"
168
- redirect_stdouts_to log_path if log_path
169
180
  result = yield
170
- save_result result, log_path
181
+ save_result result, status_path
171
182
  exit result.status
172
183
  }
173
184
  _, st = Process.waitpid2(cpid)
174
- restore_result(st, log_path)
175
- end
176
-
177
- def redirect_stdouts_to(path)
178
- FileUtils.mkdir_p File.dirname(path)
179
- # make readable for retrieve_last_match_from_stderr
180
- File.open(path, 'w+') {|f|
181
- $stdout.reopen f
182
- $stderr.reopen f
183
- }
185
+ restore_result(st, status_path)
184
186
  end
185
187
 
186
- def save_result(result, log_path)
188
+ def save_result(result, status_path)
187
189
  return if result.success?
188
- return unless log_path
190
+ return unless status_path
189
191
  begin
190
- File.open(error_log_path(log_path), 'w') {|f|
192
+ File.open(status_path, 'w') {|f|
191
193
  f.puts result.message
192
194
  }
193
195
  rescue
194
196
  end
195
197
  end
196
198
 
197
- def restore_result(st, log_path)
198
- JobResult.for_process_status(st, restore_message(log_path))
199
- end
200
-
201
- def restore_message(log_path)
202
- return nil unless log_path
203
- msg = read_if_exist(error_log_path(log_path))
204
- msg ? msg.strip : nil
205
- ensure
206
- FileUtils.rm_f error_log_path(log_path) if log_path
199
+ def restore_result(st, status_path)
200
+ JobResult.for_process_status(st, restore_message(status_path))
207
201
  end
208
202
 
209
- def error_log_path(log_path)
210
- "#{log_path}.error"
203
+ def restore_message(status_path)
204
+ return nil unless status_path
205
+ begin
206
+ msg = read_if_exist(status_path)
207
+ msg ? msg.strip : nil
208
+ ensure
209
+ FileUtils.rm_f status_path
210
+ end
211
211
  end
212
212
 
213
213
  def read_if_exist(path)