task-orchestrator 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/examples/flock ADDED
@@ -0,0 +1,12 @@
1
+ orchestrator:
2
+ statedir: states
3
+ flock:
4
+ description: flocking statefile test
5
+ save: true
6
+ steps:
7
+ - type: sequential
8
+ scripts:
9
+ - command: sleep 10
10
+ - command: sleep 10
11
+ - command: sleep 10
12
+ - command: sleep 10
data/examples/timeouts CHANGED
@@ -8,10 +8,10 @@ orchestrator:
8
8
  # on_failure: die
9
9
  on_failure: ignore
10
10
  scripts:
11
- - command: sleep 5
12
- timeout: 2
13
- - command: sleep 1
14
- timeout: 2
11
+ - command: sleep 50
12
+ timeout: 10
13
+ - command: sleep 10
14
+ timeout: 5
15
15
  timeouts2:
16
16
  description: timeouts test 2
17
17
  save: true
@@ -32,7 +32,10 @@ module Orchestrator
32
32
  end
33
33
 
34
34
  options.reset = false
35
- parser.on( '--reset', 'Do not use state file if it exists' ) { |reset| options.reset = true }
35
+ parser.on( '--reset', 'Do not use state file if it exists' ) { options.reset = true }
36
+
37
+ options.kill = false
38
+ parser.on( '--kill', 'Kill running task based on statefile pid then lock can not be acquired' ) { options.kill = true }
36
39
 
37
40
  parser.on( '--args ARGS,', Array, 'extra args for interpolation as arg1=val1,arg2=val2,...]' ) do |extra_args|
38
41
  extra_args.each do |extra_arg|
@@ -14,6 +14,8 @@ module Orchestrator
14
14
  Thread.abort_on_exception = true
15
15
  @log = ''
16
16
 
17
+ @children = {}
18
+
17
19
  @options = options
18
20
 
19
21
  @defaults = {}
@@ -32,7 +34,52 @@ module Orchestrator
32
34
  FileUtils.mkdir_p(@settings['orchestrator']['statedir'])
33
35
  end
34
36
  end
35
- @state = (@options.statefile && File.exist?(@options.statefile) && !@options.reset) ? YAML.load_file(@options.statefile) : @settings['orchestrator'][@options.name]
37
+
38
+ if @options.statefile
39
+ if File.exist?(@options.statefile)
40
+ File.open(@options.statefile, "r") do |file|
41
+ @got_lock = file.flock( File::LOCK_NB | File::LOCK_EX )
42
+ end
43
+ unless @got_lock
44
+ if @options.kill
45
+ @state = YAML.load_file(@options.statefile)
46
+ begin
47
+ Process.kill("TERM", @state['pid']) if @state.has_key?('pid')
48
+ rescue Errno::ESRCH
49
+ end
50
+ sleep 0.1
51
+ File.open(@options.statefile, "r") do |file|
52
+ @got_lock = file.flock( File::LOCK_NB | File::LOCK_EX )
53
+ end
54
+ end
55
+ invalid("The state file #{@options.statefile} is already locked by other process") unless @got_lock
56
+ end
57
+ end
58
+
59
+ @state = (File.exist?(@options.statefile) && !@options.reset) ? YAML.load_file(@options.statefile) : @settings['orchestrator'][@options.name]
60
+
61
+ @state['pid'] = Process.pid
62
+
63
+ @statefile_handle = File.open(@options.statefile, "w")
64
+ @statefile_handle.flock( File::LOCK_NB | File::LOCK_EX )
65
+ @statefile_handle.sync = true
66
+ ### @statefile_handle.close_on_exec = true
67
+ Signal.trap("TERM") do
68
+ @children.each do |pid, command|
69
+ begin
70
+ Process.kill("TERM", pid)
71
+ puts "KILLED #{pid}: #{command}\n" if @options.verbose
72
+ @log += "KILLED #{pid}: #{command}\n"
73
+ rescue Errno::ESRCH
74
+ end
75
+ end
76
+ puts "KILLED ORCHESTRATOR\n" if @options.verbose
77
+ @log += "KILLED ORCHESTRATOR\n"
78
+ fail
79
+ end
80
+ else
81
+ @state = @settings['orchestrator'][@options.name]
82
+ end
36
83
 
37
84
  @options.email = false unless @state.has_key?('email')
38
85
  @options.email_on_success = (@options.email and @state['email'].has_key?('on_success')) ? @state['email']['on_success'] : true
@@ -49,7 +96,14 @@ module Orchestrator
49
96
  def save_state
50
97
  if @options.statefile
51
98
  @mutex.synchronize do
52
- File.open(@options.statefile, "w") {|f| YAML.dump(@state, f)}
99
+ unless File.exist?(@options.statefile)
100
+ @statefile_handle.close
101
+ @statefile_handle = File.open(@options.statefile, "w")
102
+ @statefile_handle.flock( File::LOCK_NB | File::LOCK_EX )
103
+ @statefile_handle.sync = true
104
+ end
105
+ @statefile_handle.rewind
106
+ YAML.dump(@state, @statefile_handle)
53
107
  end
54
108
  end
55
109
  end
@@ -185,9 +239,12 @@ module Orchestrator
185
239
  # start = Time.now
186
240
 
187
241
  status = 'STARTED'
242
+ child = nil
188
243
  begin
189
244
  Timeout::timeout(timeout) do
190
245
  status = POpen4::popen4(command) do |stdout, stderr, stdin, pid|
246
+ @children[pid] = command
247
+ child = pid
191
248
  result = stdout.read.strip
192
249
  error = stderr.read.strip
193
250
  end
@@ -195,12 +252,21 @@ module Orchestrator
195
252
  end
196
253
  rescue Timeout::Error
197
254
  status = 'TIMEOUT'
255
+ if child
256
+ begin
257
+ Process.kill("TERM", child)
258
+ result += "\nKILLED #{child}: #{command}\n"
259
+ rescue Errno::ESRCH
260
+ end
261
+ end
198
262
  end
199
263
 
200
264
  # runtime = Time.now - start
201
265
  # runtime = runtime > 60 ? runtime/60 : runtime
202
266
 
203
267
  @mutex.synchronize do
268
+ @children.delete(child) if child
269
+
204
270
  output = <<-EOF
205
271
 
206
272
  Running: #{command} - #{status}
@@ -1,3 +1,3 @@
1
1
  module Orchestrator
2
- VERSION ||= '0.0.9'
2
+ VERSION ||= '0.0.10'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: task-orchestrator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-11 00:00:00.000000000 Z
12
+ date: 2013-09-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pony
@@ -85,16 +85,17 @@ extra_rdoc_files: []
85
85
  files:
86
86
  - bin/orchestrator
87
87
  - lib/orchestrator.rb
88
- - lib/orchestrator/task.rb
89
88
  - lib/orchestrator/version.rb
90
89
  - lib/orchestrator/cli.rb
90
+ - lib/orchestrator/task.rb
91
+ - examples/timeouts
92
+ - examples/interpolation
93
+ - examples/dependencies
91
94
  - examples/sequential
92
95
  - examples/failure_handler
93
- - examples/multistep
94
96
  - examples/parallel
95
- - examples/interpolation
96
- - examples/timeouts
97
- - examples/dependencies
97
+ - examples/flock
98
+ - examples/multistep
98
99
  - task-orchestrator.gemspec
99
100
  - LICENSE
100
101
  - README.md