eye 0.8.1 → 0.9.pre
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +21 -2
- data/.travis.yml +2 -1
- data/Gemfile +3 -0
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/bin/loader_eye +1 -1
- data/examples/delayed_job.eye +2 -2
- data/examples/processes/sample.rb +1 -1
- data/examples/puma.eye +1 -1
- data/examples/rbenv.eye +1 -1
- data/examples/sidekiq.eye +1 -1
- data/examples/test.eye +1 -1
- data/examples/thin-farm.eye +1 -1
- data/examples/unicorn.eye +1 -1
- data/eye.gemspec +2 -2
- data/lib/eye.rb +2 -3
- data/lib/eye/application.rb +3 -6
- data/lib/eye/checker.rb +4 -3
- data/lib/eye/checker/children_count.rb +3 -3
- data/lib/eye/checker/socket.rb +7 -12
- data/lib/eye/child_process.rb +5 -7
- data/lib/eye/cli.rb +6 -4
- data/lib/eye/cli/commands.rb +1 -1
- data/lib/eye/cli/render.rb +6 -5
- data/lib/eye/client.rb +9 -4
- data/lib/eye/controller.rb +2 -2
- data/lib/eye/controller/{send_command.rb → apply.rb} +25 -32
- data/lib/eye/controller/commands.rb +13 -10
- data/lib/eye/controller/load.rb +49 -38
- data/lib/eye/controller/status.rb +2 -2
- data/lib/eye/dsl.rb +1 -1
- data/lib/eye/dsl/application_opts.rb +2 -2
- data/lib/eye/dsl/child_process_opts.rb +1 -1
- data/lib/eye/dsl/config_opts.rb +1 -1
- data/lib/eye/dsl/group_opts.rb +3 -3
- data/lib/eye/dsl/main.rb +3 -3
- data/lib/eye/dsl/opts.rb +17 -21
- data/lib/eye/dsl/process_opts.rb +3 -3
- data/lib/eye/dsl/validation.rb +2 -2
- data/lib/eye/group.rb +8 -114
- data/lib/eye/group/call.rb +73 -0
- data/lib/eye/group/chain.rb +19 -17
- data/lib/eye/group/data.rb +40 -0
- data/lib/eye/loader.rb +1 -1
- data/lib/eye/logger.rb +4 -4
- data/lib/eye/process.rb +2 -0
- data/lib/eye/process/commands.rb +11 -19
- data/lib/eye/process/config.rb +2 -1
- data/lib/eye/process/controller.rb +5 -12
- data/lib/eye/process/data.rb +11 -3
- data/lib/eye/process/monitor.rb +5 -5
- data/lib/eye/process/notify.rb +1 -1
- data/lib/eye/process/scheduler.rb +118 -63
- data/lib/eye/process/states.rb +10 -9
- data/lib/eye/process/states_history.rb +1 -1
- data/lib/eye/process/system.rb +1 -1
- data/lib/eye/process/trigger.rb +5 -4
- data/lib/eye/process/validate.rb +1 -1
- data/lib/eye/server.rb +22 -9
- data/lib/eye/trigger.rb +4 -7
- data/lib/eye/trigger/check_dependency.rb +1 -1
- data/lib/eye/trigger/flapping.rb +8 -10
- data/lib/eye/trigger/starting_guard.rb +7 -4
- data/lib/eye/trigger/stop_children.rb +1 -1
- data/lib/eye/trigger/wait_dependency.rb +2 -2
- data/lib/eye/utils.rb +19 -9
- metadata +10 -10
- data/lib/eye/reason.rb +0 -26
- data/lib/eye/utils/celluloid_chain.rb +0 -73
data/lib/eye/server.rb
CHANGED
@@ -25,13 +25,30 @@ class Eye::Server
|
|
25
25
|
text = socket.read
|
26
26
|
|
27
27
|
begin
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
# TODO, remove in 1.0
|
29
|
+
|
30
|
+
payload = Marshal.load(text)
|
31
|
+
raise "unknown payload #{payload.inspect}" unless payload.is_a?(Array)
|
32
|
+
cmd, *args = payload
|
33
|
+
|
34
|
+
rescue
|
35
|
+
# new format
|
36
|
+
begin
|
37
|
+
pos = text.index("\n")
|
38
|
+
msg_size = text[0..pos].to_i
|
39
|
+
content = text[pos + 1..-1]
|
40
|
+
content << socket.read(msg_size - content.length) while content.length < msg_size
|
41
|
+
payload = Marshal.load(content)
|
42
|
+
cmd = payload[:command]
|
43
|
+
args = payload[:args]
|
44
|
+
|
45
|
+
rescue => ex
|
46
|
+
error "Failed to read from socket: #{ex.message}"
|
47
|
+
return
|
48
|
+
end
|
32
49
|
end
|
33
50
|
|
34
|
-
response = command(cmd, *args)
|
51
|
+
response = Eye::Control.command(cmd, *args, {})
|
35
52
|
socket.write(Marshal.dump(response))
|
36
53
|
|
37
54
|
rescue Errno::EPIPE
|
@@ -42,10 +59,6 @@ class Eye::Server
|
|
42
59
|
socket.close
|
43
60
|
end
|
44
61
|
|
45
|
-
def command(cmd, *args)
|
46
|
-
Eye::Control.command(cmd, *args)
|
47
|
-
end
|
48
|
-
|
49
62
|
def unlink_socket_file
|
50
63
|
File.delete(@socket_path) if @socket_path
|
51
64
|
rescue
|
data/lib/eye/trigger.rb
CHANGED
@@ -65,19 +65,16 @@ class Eye::Trigger
|
|
65
65
|
"trigger(#{@options[:type]})"
|
66
66
|
end
|
67
67
|
|
68
|
-
def notify(transition,
|
68
|
+
def notify(transition, state_call)
|
69
69
|
debug { "check (:#{transition.event}) :#{transition.from} => :#{transition.to}" }
|
70
|
-
@
|
70
|
+
@state_call = state_call
|
71
71
|
@transition = transition
|
72
72
|
|
73
73
|
check(transition) if filter_transition(transition)
|
74
74
|
|
75
75
|
rescue Object => ex
|
76
|
-
if ex.class == Eye::Process::StateError
|
77
|
-
|
78
|
-
else
|
79
|
-
log_ex(ex)
|
80
|
-
end
|
76
|
+
raise ex if ex.class == Eye::Process::StateError || ex.class == Celluloid::TaskTerminated
|
77
|
+
log_ex(ex)
|
81
78
|
end
|
82
79
|
|
83
80
|
param :to, [Symbol, Array]
|
data/lib/eye/trigger/flapping.rb
CHANGED
@@ -44,20 +44,18 @@ private
|
|
44
44
|
debug { 'flapping recognized!!!' }
|
45
45
|
|
46
46
|
process.notify :error, 'flapping!'
|
47
|
-
process.schedule :unmonitor,
|
47
|
+
process.schedule command: :unmonitor, by: :flapping
|
48
48
|
|
49
49
|
return unless retry_in
|
50
50
|
if !retry_times || (retry_times && @retry_times < retry_times)
|
51
51
|
@retry_times += 1
|
52
|
-
process.
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
52
|
+
process.schedule(in: retry_in.to_f, command: :conditional_start,
|
53
|
+
by: :flapping, reason: 'retry start after flapping')
|
54
|
+
elsif reretry_in && !reretry_times || (reretry_times && @reretry_times < reretry_times)
|
55
|
+
@retry_times = 0
|
56
|
+
@reretry_times += 1
|
57
|
+
process.schedule(in: reretry_in.to_f, command: :conditional_start,
|
58
|
+
by: :flapping, reason: 'reretry start after flapping')
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
@@ -41,23 +41,26 @@ class Eye::Trigger::StartingGuard < Eye::Trigger
|
|
41
41
|
if times
|
42
42
|
if @retry_count < times
|
43
43
|
new_time = Time.now + every
|
44
|
-
process.
|
44
|
+
process.schedule(in: every, command: :conditional_start,
|
45
|
+
by: :starting_guard, reason: 'starting_guard, retry start')
|
45
46
|
else
|
46
47
|
@retry_count = 0
|
47
48
|
@reretry_count += 1
|
48
49
|
if retry_in && (!retry_times || (@reretry_count < retry_times))
|
49
50
|
new_time = Time.now + retry_in
|
50
|
-
process.
|
51
|
+
process.schedule(in: retry_in, command: :conditional_start,
|
52
|
+
by: :starting_guard, reason: 'restarting_guard, retry start')
|
51
53
|
end
|
52
54
|
end
|
53
55
|
else
|
54
56
|
new_time = Time.now + every
|
55
|
-
process.
|
57
|
+
process.schedule(in: every, command: :conditional_start,
|
58
|
+
by: :starting_guard, reason: 'starting_guard, retry start')
|
56
59
|
end
|
57
60
|
end
|
58
61
|
|
59
62
|
retry_msg = new_time ? ", retry at '#{Eye::Utils.human_time2(new_time.to_i)}'" : ''
|
60
|
-
process.switch :unmonitoring,
|
63
|
+
process.switch :unmonitoring, by: :starting_guard, reason: "failed condition#{retry_msg}"
|
61
64
|
|
62
65
|
raise Eye::Process::StateError, 'starting_guard, refused to start'
|
63
66
|
end
|
@@ -20,7 +20,7 @@ private
|
|
20
20
|
|
21
21
|
processes.each do |p|
|
22
22
|
if p.state_name != :up && (should_start != false)
|
23
|
-
p.schedule :start,
|
23
|
+
p.schedule command: :start, reason: 'start_dependency'
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -40,7 +40,7 @@ private
|
|
40
40
|
process.switch :unmonitoring
|
41
41
|
|
42
42
|
if retry_after
|
43
|
-
process.
|
43
|
+
process.schedule in: retry_after, command: :start, reason: 'wait_dependency'
|
44
44
|
end
|
45
45
|
|
46
46
|
raise Eye::Process::StateError, 'stop transition because dependency is not up'
|
data/lib/eye/utils.rb
CHANGED
@@ -4,13 +4,14 @@ module Eye::Utils
|
|
4
4
|
|
5
5
|
autoload :Tail, 'eye/utils/tail'
|
6
6
|
autoload :AliveArray, 'eye/utils/alive_array'
|
7
|
-
autoload :CelluloidChain, 'eye/utils/celluloid_chain'
|
8
7
|
|
9
8
|
def self.deep_clone(value)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
if value.is_a?(Array)
|
10
|
+
value.map { |v| deep_clone(v) }
|
11
|
+
elsif value.is_a?(Hash)
|
12
|
+
value.each_with_object({}) { |(k, v), r| r[deep_clone(k)] = deep_clone(v) }
|
13
|
+
else
|
14
|
+
value
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
@@ -27,17 +28,17 @@ module Eye::Utils
|
|
27
28
|
a
|
28
29
|
end
|
29
30
|
|
30
|
-
D1 = '%H:%M'
|
31
|
-
D2 = '%b%d'
|
31
|
+
D1 = '%H:%M'.freeze
|
32
|
+
D2 = '%b%d'.freeze
|
32
33
|
|
33
34
|
def self.human_time(unix_time)
|
34
35
|
time = Time.at(unix_time.to_i)
|
35
36
|
d1 = time.to_date
|
36
37
|
d2 = Time.now.to_date
|
37
|
-
time.strftime(
|
38
|
+
time.strftime(d1 == d2 ? D1 : D2)
|
38
39
|
end
|
39
40
|
|
40
|
-
DF = '%d %b %H:%M'
|
41
|
+
DF = '%d %b %H:%M'.freeze
|
41
42
|
|
42
43
|
def self.human_time2(unix_time)
|
43
44
|
Time.at(unix_time.to_i).strftime(DF)
|
@@ -56,4 +57,13 @@ module Eye::Utils
|
|
56
57
|
h
|
57
58
|
end
|
58
59
|
|
60
|
+
def self.wait_signal(timeout = nil, &block)
|
61
|
+
signal = Celluloid::Condition.new
|
62
|
+
block.call(signal)
|
63
|
+
signal.wait((timeout || 600).to_f)
|
64
|
+
:ok
|
65
|
+
rescue Celluloid::ConditionError
|
66
|
+
:timeouted
|
67
|
+
end
|
68
|
+
|
59
69
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eye
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Makarchev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05
|
11
|
+
date: 2016-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.17.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: state_machines
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -112,16 +112,16 @@ dependencies:
|
|
112
112
|
name: rr
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - '='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 1.1.2
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - '='
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: 1.1.2
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: ruby-graphviz
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -389,11 +389,11 @@ files:
|
|
389
389
|
- lib/eye/config.rb
|
390
390
|
- lib/eye/control.rb
|
391
391
|
- lib/eye/controller.rb
|
392
|
+
- lib/eye/controller/apply.rb
|
392
393
|
- lib/eye/controller/commands.rb
|
393
394
|
- lib/eye/controller/helpers.rb
|
394
395
|
- lib/eye/controller/load.rb
|
395
396
|
- lib/eye/controller/options.rb
|
396
|
-
- lib/eye/controller/send_command.rb
|
397
397
|
- lib/eye/controller/status.rb
|
398
398
|
- lib/eye/dsl.rb
|
399
399
|
- lib/eye/dsl/application_opts.rb
|
@@ -408,7 +408,9 @@ files:
|
|
408
408
|
- lib/eye/dsl/pure_opts.rb
|
409
409
|
- lib/eye/dsl/validation.rb
|
410
410
|
- lib/eye/group.rb
|
411
|
+
- lib/eye/group/call.rb
|
411
412
|
- lib/eye/group/chain.rb
|
413
|
+
- lib/eye/group/data.rb
|
412
414
|
- lib/eye/loader.rb
|
413
415
|
- lib/eye/local.rb
|
414
416
|
- lib/eye/logger.rb
|
@@ -431,7 +433,6 @@ files:
|
|
431
433
|
- lib/eye/process/trigger.rb
|
432
434
|
- lib/eye/process/validate.rb
|
433
435
|
- lib/eye/process/watchers.rb
|
434
|
-
- lib/eye/reason.rb
|
435
436
|
- lib/eye/server.rb
|
436
437
|
- lib/eye/sigar.rb
|
437
438
|
- lib/eye/system.rb
|
@@ -445,7 +446,6 @@ files:
|
|
445
446
|
- lib/eye/trigger/wait_dependency.rb
|
446
447
|
- lib/eye/utils.rb
|
447
448
|
- lib/eye/utils/alive_array.rb
|
448
|
-
- lib/eye/utils/celluloid_chain.rb
|
449
449
|
- lib/eye/utils/mini_active_support.rb
|
450
450
|
- lib/eye/utils/pmap.rb
|
451
451
|
- lib/eye/utils/tail.rb
|
data/lib/eye/reason.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
class Eye::Reason
|
2
|
-
|
3
|
-
def initialize(mes = nil)
|
4
|
-
@message = mes
|
5
|
-
end
|
6
|
-
|
7
|
-
def to_s
|
8
|
-
@message.to_s
|
9
|
-
end
|
10
|
-
|
11
|
-
def user?
|
12
|
-
self.class == User
|
13
|
-
end
|
14
|
-
|
15
|
-
class User < Eye::Reason
|
16
|
-
|
17
|
-
def to_s
|
18
|
-
"#{super} by user"
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
class Flapping < Eye::Reason; end
|
24
|
-
class StartingGuard < Eye::Reason; end
|
25
|
-
|
26
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
require 'celluloid'
|
2
|
-
|
3
|
-
class Eye::Utils::CelluloidChain
|
4
|
-
|
5
|
-
include Celluloid
|
6
|
-
|
7
|
-
def initialize(target)
|
8
|
-
@target = target
|
9
|
-
@calls = []
|
10
|
-
@running = false
|
11
|
-
@target_class = @target.class
|
12
|
-
end
|
13
|
-
|
14
|
-
def add(method_name, *args)
|
15
|
-
@calls << { method_name: method_name, args: args }
|
16
|
-
ensure_process
|
17
|
-
end
|
18
|
-
|
19
|
-
def add_wo_dups(method_name, *args)
|
20
|
-
h = { method_name: method_name, args: args }
|
21
|
-
if @calls[-1] != h
|
22
|
-
@calls << h
|
23
|
-
ensure_process
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def add_wo_dups_current(method_name, *args)
|
28
|
-
h = { method_name: method_name, args: args }
|
29
|
-
if !@calls.include?(h) && @call != h
|
30
|
-
@calls << h
|
31
|
-
ensure_process
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def list
|
36
|
-
@calls
|
37
|
-
end
|
38
|
-
|
39
|
-
def names_list
|
40
|
-
list.map { |el| el[:method_name].to_sym }
|
41
|
-
end
|
42
|
-
|
43
|
-
def clear
|
44
|
-
@calls = []
|
45
|
-
end
|
46
|
-
|
47
|
-
alias_method :clear_pending_list, :clear
|
48
|
-
|
49
|
-
# need, because of https://github.com/celluloid/celluloid/issues/22
|
50
|
-
def inspect
|
51
|
-
"Celluloid::Chain(#{@target_class}: #{@calls.size})"
|
52
|
-
end
|
53
|
-
|
54
|
-
attr_reader :running
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def ensure_process
|
59
|
-
unless @running
|
60
|
-
@running = true
|
61
|
-
async.process
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def process
|
66
|
-
while @call = @calls.shift
|
67
|
-
@running = true
|
68
|
-
@target.send(@call[:method_name], *@call[:args]) if @target.alive?
|
69
|
-
end
|
70
|
-
@running = false
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|