task-orchestrator 0.0.9 → 0.0.10

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/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