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/dsl/process_opts.rb
CHANGED
@@ -7,13 +7,13 @@ class Eye::Dsl::ProcessOpts < Eye::Dsl::Opts
|
|
7
7
|
Eye::Utils.deep_merge!(@config[:monitor_children], opts.config)
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
alias xmonitor_children nop
|
11
11
|
|
12
12
|
def application
|
13
13
|
parent.try(:parent)
|
14
14
|
end
|
15
|
-
|
16
|
-
|
15
|
+
alias app application
|
16
|
+
alias group parent
|
17
17
|
|
18
18
|
def depend_on(names, opts = {})
|
19
19
|
names = Array(names).map(&:to_s)
|
data/lib/eye/dsl/validation.rb
CHANGED
@@ -4,7 +4,7 @@ module Eye::Dsl::Validation
|
|
4
4
|
base.extend(ClassMethods)
|
5
5
|
end
|
6
6
|
|
7
|
-
class Error <
|
7
|
+
class Error < RuntimeError; end
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
|
@@ -43,7 +43,7 @@ module Eye::Dsl::Validation
|
|
43
43
|
|
44
44
|
return if param == :do
|
45
45
|
|
46
|
-
define_method
|
46
|
+
define_method param do
|
47
47
|
value = @options[param]
|
48
48
|
value.nil? ? self.class.defaults[param] : value
|
49
49
|
end
|
data/lib/eye/group.rb
CHANGED
@@ -4,10 +4,14 @@ class Eye::Group
|
|
4
4
|
|
5
5
|
include Celluloid
|
6
6
|
|
7
|
-
autoload :
|
7
|
+
autoload :Call, 'eye/group/call'
|
8
|
+
autoload :Chain, 'eye/group/chain'
|
9
|
+
autoload :Data, 'eye/group/data'
|
8
10
|
|
9
11
|
include Eye::Process::Scheduler
|
12
|
+
include Eye::Group::Call
|
10
13
|
include Eye::Group::Chain
|
14
|
+
include Eye::Group::Data
|
11
15
|
|
12
16
|
attr_reader :processes, :name, :hidden, :config
|
13
17
|
|
@@ -31,11 +35,6 @@ class Eye::Group
|
|
31
35
|
@full_name ||= "#{app_name}:#{@name}"
|
32
36
|
end
|
33
37
|
|
34
|
-
def update_config(cfg)
|
35
|
-
@config = cfg
|
36
|
-
@full_name = nil
|
37
|
-
end
|
38
|
-
|
39
38
|
def add_process(process)
|
40
39
|
@processes << process
|
41
40
|
end
|
@@ -45,99 +44,6 @@ class Eye::Group
|
|
45
44
|
@processes = @processes.sort_by(&:name)
|
46
45
|
end
|
47
46
|
|
48
|
-
def status_data(opts = {})
|
49
|
-
plist = @processes.map { |p| p.status_data(opts) }
|
50
|
-
|
51
|
-
h = { name: name, type: :group, subtree: plist }
|
52
|
-
|
53
|
-
h[:debug] = debug_data if opts[:debug]
|
54
|
-
|
55
|
-
# show current chain
|
56
|
-
if current_scheduled_command
|
57
|
-
h.update(current_command: current_scheduled_command)
|
58
|
-
|
59
|
-
if (chain_commands = scheduler_actions_list) && chain_commands.present?
|
60
|
-
h.update(chain_commands: chain_commands)
|
61
|
-
end
|
62
|
-
|
63
|
-
if @chain_processes_current && @chain_processes_count
|
64
|
-
h.update(chain_progress: [@chain_processes_current, @chain_processes_count])
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
h
|
69
|
-
end
|
70
|
-
|
71
|
-
def status_data_short
|
72
|
-
h = {}
|
73
|
-
@processes.each do |p|
|
74
|
-
state = p.state
|
75
|
-
h[state] ||= 0
|
76
|
-
h[state] += 1
|
77
|
-
end
|
78
|
-
{ name: (@name == '__default__' ? 'default' : @name), type: :group, states: h }
|
79
|
-
end
|
80
|
-
|
81
|
-
def debug_data
|
82
|
-
{ queue: scheduler_actions_list, chain: chain_status }
|
83
|
-
end
|
84
|
-
|
85
|
-
def send_command(command, *args)
|
86
|
-
info "send_command: #{command}"
|
87
|
-
|
88
|
-
case command
|
89
|
-
when :delete
|
90
|
-
delete(*args)
|
91
|
-
when :break_chain
|
92
|
-
break_chain(*args)
|
93
|
-
else
|
94
|
-
schedule command, *args, Eye::Reason::User.new(command)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def start
|
99
|
-
chain_command :start
|
100
|
-
end
|
101
|
-
|
102
|
-
def stop
|
103
|
-
async_schedule :stop
|
104
|
-
end
|
105
|
-
|
106
|
-
def restart
|
107
|
-
chain_command :restart
|
108
|
-
end
|
109
|
-
|
110
|
-
def delete
|
111
|
-
async_schedule :delete
|
112
|
-
terminate
|
113
|
-
end
|
114
|
-
|
115
|
-
def monitor
|
116
|
-
chain_command :monitor
|
117
|
-
end
|
118
|
-
|
119
|
-
def unmonitor
|
120
|
-
async_schedule :unmonitor
|
121
|
-
end
|
122
|
-
|
123
|
-
def signal(sig)
|
124
|
-
async_schedule :signal, sig
|
125
|
-
end
|
126
|
-
|
127
|
-
def user_command(cmd)
|
128
|
-
async_schedule :user_command, cmd
|
129
|
-
end
|
130
|
-
|
131
|
-
def break_chain
|
132
|
-
info 'break chain'
|
133
|
-
scheduler_clear_pending_list
|
134
|
-
@chain_breaker = true
|
135
|
-
end
|
136
|
-
|
137
|
-
def freeze
|
138
|
-
async_schedule :freeze
|
139
|
-
end
|
140
|
-
|
141
47
|
def clear
|
142
48
|
@processes = Eye::Utils::AliveArray.new
|
143
49
|
end
|
@@ -150,22 +56,10 @@ class Eye::Group
|
|
150
56
|
def <=>(other)
|
151
57
|
if hidden
|
152
58
|
1
|
59
|
+
elsif other.hidden
|
60
|
+
-1
|
153
61
|
else
|
154
|
-
|
155
|
-
-1
|
156
|
-
else
|
157
|
-
name <=> other.name
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
private
|
163
|
-
|
164
|
-
def async_schedule(command, *args)
|
165
|
-
info "send to all processes #{command} #{args.present? ? args * ',' : nil}"
|
166
|
-
|
167
|
-
@processes.each do |process|
|
168
|
-
process.send_command(command, *args) unless process.skip_group_action?(command)
|
62
|
+
name <=> other.name
|
169
63
|
end
|
170
64
|
end
|
171
65
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Eye::Group::Call
|
2
|
+
|
3
|
+
# :update_config, :start, :stop, :restart, :unmonitor, :monitor, :break_chain, :delete, :signal, :user_command
|
4
|
+
def send_call(call)
|
5
|
+
info "call: #{call[:method]}"
|
6
|
+
|
7
|
+
case call[:command]
|
8
|
+
when :delete
|
9
|
+
delete
|
10
|
+
when :break_chain
|
11
|
+
break_chain
|
12
|
+
else
|
13
|
+
user_schedule(call)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def update_config(cfg)
|
18
|
+
@config = cfg
|
19
|
+
@full_name = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def start
|
23
|
+
chained_call command: :start
|
24
|
+
end
|
25
|
+
|
26
|
+
def stop
|
27
|
+
fast_call command: :stop
|
28
|
+
end
|
29
|
+
|
30
|
+
def restart
|
31
|
+
chained_call command: :restart
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete
|
35
|
+
fast_call command: :delete
|
36
|
+
terminate
|
37
|
+
end
|
38
|
+
|
39
|
+
def monitor
|
40
|
+
chained_call command: :monitor
|
41
|
+
end
|
42
|
+
|
43
|
+
def unmonitor
|
44
|
+
fast_call command: :unmonitor
|
45
|
+
end
|
46
|
+
|
47
|
+
def signal(sig)
|
48
|
+
fast_call command: :signal, args: [sig]
|
49
|
+
end
|
50
|
+
|
51
|
+
def user_command(cmd)
|
52
|
+
fast_call command: :user_command, args: [cmd]
|
53
|
+
end
|
54
|
+
|
55
|
+
def break_chain
|
56
|
+
info 'break chain'
|
57
|
+
scheduler_clear_pending_list
|
58
|
+
@chain_breaker = true
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def fast_call(call)
|
64
|
+
command = call[:command]
|
65
|
+
args = call[:args]
|
66
|
+
info "send to all processes #{command} #{args.present? ? args * ',' : nil}"
|
67
|
+
|
68
|
+
@processes.each do |process|
|
69
|
+
process.send_call(call) unless process.skip_group_action?(command)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
data/lib/eye/group/chain.rb
CHANGED
@@ -2,7 +2,14 @@ module Eye::Group::Chain
|
|
2
2
|
|
3
3
|
private
|
4
4
|
|
5
|
-
def
|
5
|
+
def chained_call(call)
|
6
|
+
type, grace = chain_options(call[:command])
|
7
|
+
chain_schedule(type, grace, call)
|
8
|
+
end
|
9
|
+
|
10
|
+
def chain_schedule(type, grace, call)
|
11
|
+
command = call[:command]
|
12
|
+
args = call[:args]
|
6
13
|
info "starting #{type} with #{grace}s chain #{command} #{args}"
|
7
14
|
|
8
15
|
@chain_processes_count = @processes.size
|
@@ -17,7 +24,7 @@ private
|
|
17
24
|
next
|
18
25
|
end
|
19
26
|
|
20
|
-
chain_schedule_process(process, type,
|
27
|
+
chain_schedule_process(process, type, call)
|
21
28
|
|
22
29
|
@chain_processes_current = @chain_processes_current.to_i + 1
|
23
30
|
|
@@ -37,18 +44,18 @@ private
|
|
37
44
|
@chain_processes_current = nil
|
38
45
|
end
|
39
46
|
|
40
|
-
def chain_schedule_process(process, type,
|
41
|
-
debug { "chain_schedule_process #{process.name} #{type} #{command}" }
|
47
|
+
def chain_schedule_process(process, type, call)
|
48
|
+
debug { "chain_schedule_process #{process.name} #{type} #{call[:command]}" }
|
42
49
|
|
43
50
|
if type == :sync
|
44
51
|
# sync command, with waiting
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
52
|
+
Eye::Utils.wait_signal(call[:signal_timeout]) do |signal|
|
53
|
+
process.send_call(call.merge(signal: signal))
|
54
|
+
end
|
55
|
+
|
49
56
|
else
|
50
57
|
# async command
|
51
|
-
process.
|
58
|
+
process.send_call(call)
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
@@ -58,11 +65,6 @@ private
|
|
58
65
|
end
|
59
66
|
end
|
60
67
|
|
61
|
-
def chain_command(command, *args)
|
62
|
-
chain_opts = chain_options(command)
|
63
|
-
chain_schedule(chain_opts[:type], chain_opts[:grace], command, *args)
|
64
|
-
end
|
65
|
-
|
66
68
|
# with such delay will chained processes by default
|
67
69
|
DEFAULT_CHAIN = 0.2
|
68
70
|
|
@@ -74,12 +76,12 @@ private
|
|
74
76
|
type = [:async, :sync].include?(type) ? type : :async
|
75
77
|
|
76
78
|
grace = @config[:chain][command].try :[], :grace
|
77
|
-
grace = grace
|
79
|
+
grace = (grace || DEFAULT_CHAIN).to_f rescue DEFAULT_CHAIN
|
78
80
|
|
79
|
-
|
81
|
+
[type, grace]
|
80
82
|
else
|
81
83
|
# default chain case
|
82
|
-
|
84
|
+
[:async, DEFAULT_CHAIN]
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Eye::Group::Data
|
2
|
+
|
3
|
+
def status_data(opts = {})
|
4
|
+
plist = @processes.map { |p| p.status_data(opts) }
|
5
|
+
|
6
|
+
h = { name: name, type: :group, subtree: plist }
|
7
|
+
|
8
|
+
h[:debug] = debug_data if opts[:debug]
|
9
|
+
|
10
|
+
# show current chain
|
11
|
+
if scheduled_call = @scheduled_call
|
12
|
+
h[:current_command] = scheduled_call[:command]
|
13
|
+
|
14
|
+
if (chain_commands = scheduler_commands_list) && chain_commands.present?
|
15
|
+
h[:chain_commands] = chain_commands
|
16
|
+
end
|
17
|
+
|
18
|
+
if @chain_processes_current && @chain_processes_count
|
19
|
+
h[:chain_progress] = [@chain_processes_current, @chain_processes_count]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
h
|
24
|
+
end
|
25
|
+
|
26
|
+
def status_data_short
|
27
|
+
h = {}
|
28
|
+
@processes.each do |p|
|
29
|
+
state = p.state
|
30
|
+
h[state] ||= 0
|
31
|
+
h[state] += 1
|
32
|
+
end
|
33
|
+
{ name: (@name == '__default__' ? 'default' : @name), type: :group, states: h }
|
34
|
+
end
|
35
|
+
|
36
|
+
def debug_data
|
37
|
+
{ queue: scheduler_commands_list, chain: chain_status }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/eye/loader.rb
CHANGED
data/lib/eye/logger.rb
CHANGED
@@ -6,7 +6,7 @@ class Eye::Logger
|
|
6
6
|
|
7
7
|
class InnerLogger < Logger
|
8
8
|
|
9
|
-
FORMAT = '%d.%m.%Y %H:%M:%S'
|
9
|
+
FORMAT = '%d.%m.%Y %H:%M:%S'.freeze
|
10
10
|
|
11
11
|
def initialize(*args)
|
12
12
|
super
|
@@ -39,7 +39,7 @@ class Eye::Logger
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def log_ex(ex)
|
42
|
-
error "#{ex.message} #{ex.backtrace}"
|
42
|
+
error "Exception: #{ex.message} #{ex.backtrace}"
|
43
43
|
# notify here?
|
44
44
|
end
|
45
45
|
|
@@ -73,8 +73,8 @@ class Eye::Logger
|
|
73
73
|
if dev.nil?
|
74
74
|
@inner_logger = InnerLogger.new(nil)
|
75
75
|
elsif dev.is_a?(String)
|
76
|
-
@dev_fd = STDOUT if @dev.to_s.
|
77
|
-
@dev_fd = STDERR if @dev.to_s.
|
76
|
+
@dev_fd = STDOUT if @dev.to_s.casecmp('stdout') == 0
|
77
|
+
@dev_fd = STDERR if @dev.to_s.casecmp('stderr') == 0
|
78
78
|
@inner_logger = InnerLogger.new(@dev_fd, *args)
|
79
79
|
else
|
80
80
|
@inner_logger = dev
|
data/lib/eye/process.rb
CHANGED
data/lib/eye/process/commands.rb
CHANGED
@@ -7,7 +7,7 @@ module Eye::Process::Commands
|
|
7
7
|
|
8
8
|
unless self[:start_command]
|
9
9
|
warn 'no :start_command found, unmonitoring'
|
10
|
-
switch :unmonitoring,
|
10
|
+
switch :unmonitoring, reason: 'no_start_command'
|
11
11
|
return :no_start_command
|
12
12
|
end
|
13
13
|
|
@@ -30,7 +30,7 @@ module Eye::Process::Commands
|
|
30
30
|
|
31
31
|
result
|
32
32
|
|
33
|
-
rescue
|
33
|
+
rescue StateMachines::InvalidTransition, Eye::Process::StateError => e
|
34
34
|
warn "wrong switch '#{e.message}'"
|
35
35
|
|
36
36
|
:state_error
|
@@ -48,7 +48,7 @@ module Eye::Process::Commands
|
|
48
48
|
if process_really_running?
|
49
49
|
warn "process <#{self.pid}> was not stopped; try checking your command/signals or tuning the stop_timeout/stop_grace values"
|
50
50
|
|
51
|
-
switch :unmonitoring,
|
51
|
+
switch :unmonitoring, reason: 'not stopped (soft command)'
|
52
52
|
nil
|
53
53
|
|
54
54
|
else
|
@@ -59,7 +59,7 @@ module Eye::Process::Commands
|
|
59
59
|
true
|
60
60
|
end
|
61
61
|
|
62
|
-
rescue
|
62
|
+
rescue StateMachines::InvalidTransition, Eye::Process::StateError => e
|
63
63
|
warn "wrong switch '#{e.message}'"
|
64
64
|
nil
|
65
65
|
end
|
@@ -83,7 +83,7 @@ module Eye::Process::Commands
|
|
83
83
|
|
84
84
|
true
|
85
85
|
|
86
|
-
rescue
|
86
|
+
rescue StateMachines::InvalidTransition, Eye::Process::StateError => e
|
87
87
|
warn "wrong switch '#{e.message}'"
|
88
88
|
nil
|
89
89
|
end
|
@@ -121,7 +121,7 @@ private
|
|
121
121
|
delay = stop_signals.shift
|
122
122
|
signal = stop_signals.shift
|
123
123
|
|
124
|
-
if wait_for_condition(delay.to_f, 0.
|
124
|
+
if wait_for_condition(delay.to_f, 0.1) { !process_really_running? }
|
125
125
|
info 'has terminated'
|
126
126
|
break
|
127
127
|
end
|
@@ -129,19 +129,11 @@ private
|
|
129
129
|
send_signal(signal) if signal
|
130
130
|
end
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
else
|
135
|
-
|
136
|
-
|
137
|
-
sleep_grace(:stop_grace)
|
138
|
-
|
139
|
-
# if process not die here, by default we force kill it
|
140
|
-
if process_really_running?
|
141
|
-
warn "process <#{self.pid}> did not die after TERM, sending KILL"
|
142
|
-
send_signal(:KILL)
|
143
|
-
sleep 0.1 # little grace
|
144
|
-
end
|
132
|
+
# little grace
|
133
|
+
sleep 0.1
|
134
|
+
else
|
135
|
+
# TODO, notify here?
|
136
|
+
error 'stop_command or stop_signals should be'
|
145
137
|
end
|
146
138
|
end
|
147
139
|
|