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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +21 -2
  4. data/.travis.yml +2 -1
  5. data/Gemfile +3 -0
  6. data/LICENSE +1 -1
  7. data/README.md +1 -1
  8. data/bin/loader_eye +1 -1
  9. data/examples/delayed_job.eye +2 -2
  10. data/examples/processes/sample.rb +1 -1
  11. data/examples/puma.eye +1 -1
  12. data/examples/rbenv.eye +1 -1
  13. data/examples/sidekiq.eye +1 -1
  14. data/examples/test.eye +1 -1
  15. data/examples/thin-farm.eye +1 -1
  16. data/examples/unicorn.eye +1 -1
  17. data/eye.gemspec +2 -2
  18. data/lib/eye.rb +2 -3
  19. data/lib/eye/application.rb +3 -6
  20. data/lib/eye/checker.rb +4 -3
  21. data/lib/eye/checker/children_count.rb +3 -3
  22. data/lib/eye/checker/socket.rb +7 -12
  23. data/lib/eye/child_process.rb +5 -7
  24. data/lib/eye/cli.rb +6 -4
  25. data/lib/eye/cli/commands.rb +1 -1
  26. data/lib/eye/cli/render.rb +6 -5
  27. data/lib/eye/client.rb +9 -4
  28. data/lib/eye/controller.rb +2 -2
  29. data/lib/eye/controller/{send_command.rb → apply.rb} +25 -32
  30. data/lib/eye/controller/commands.rb +13 -10
  31. data/lib/eye/controller/load.rb +49 -38
  32. data/lib/eye/controller/status.rb +2 -2
  33. data/lib/eye/dsl.rb +1 -1
  34. data/lib/eye/dsl/application_opts.rb +2 -2
  35. data/lib/eye/dsl/child_process_opts.rb +1 -1
  36. data/lib/eye/dsl/config_opts.rb +1 -1
  37. data/lib/eye/dsl/group_opts.rb +3 -3
  38. data/lib/eye/dsl/main.rb +3 -3
  39. data/lib/eye/dsl/opts.rb +17 -21
  40. data/lib/eye/dsl/process_opts.rb +3 -3
  41. data/lib/eye/dsl/validation.rb +2 -2
  42. data/lib/eye/group.rb +8 -114
  43. data/lib/eye/group/call.rb +73 -0
  44. data/lib/eye/group/chain.rb +19 -17
  45. data/lib/eye/group/data.rb +40 -0
  46. data/lib/eye/loader.rb +1 -1
  47. data/lib/eye/logger.rb +4 -4
  48. data/lib/eye/process.rb +2 -0
  49. data/lib/eye/process/commands.rb +11 -19
  50. data/lib/eye/process/config.rb +2 -1
  51. data/lib/eye/process/controller.rb +5 -12
  52. data/lib/eye/process/data.rb +11 -3
  53. data/lib/eye/process/monitor.rb +5 -5
  54. data/lib/eye/process/notify.rb +1 -1
  55. data/lib/eye/process/scheduler.rb +118 -63
  56. data/lib/eye/process/states.rb +10 -9
  57. data/lib/eye/process/states_history.rb +1 -1
  58. data/lib/eye/process/system.rb +1 -1
  59. data/lib/eye/process/trigger.rb +5 -4
  60. data/lib/eye/process/validate.rb +1 -1
  61. data/lib/eye/server.rb +22 -9
  62. data/lib/eye/trigger.rb +4 -7
  63. data/lib/eye/trigger/check_dependency.rb +1 -1
  64. data/lib/eye/trigger/flapping.rb +8 -10
  65. data/lib/eye/trigger/starting_guard.rb +7 -4
  66. data/lib/eye/trigger/stop_children.rb +1 -1
  67. data/lib/eye/trigger/wait_dependency.rb +2 -2
  68. data/lib/eye/utils.rb +19 -9
  69. metadata +10 -10
  70. data/lib/eye/reason.rb +0 -26
  71. data/lib/eye/utils/celluloid_chain.rb +0 -73
@@ -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
- alias_method :xmonitor_children, :nop
10
+ alias xmonitor_children nop
11
11
 
12
12
  def application
13
13
  parent.try(:parent)
14
14
  end
15
- alias_method :app, :application
16
- alias_method :group, :parent
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)
@@ -4,7 +4,7 @@ module Eye::Dsl::Validation
4
4
  base.extend(ClassMethods)
5
5
  end
6
6
 
7
- class Error < Exception; end
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 "#{param}" do
46
+ define_method param do
47
47
  value = @options[param]
48
48
  value.nil? ? self.class.defaults[param] : value
49
49
  end
@@ -4,10 +4,14 @@ class Eye::Group
4
4
 
5
5
  include Celluloid
6
6
 
7
- autoload :Chain, 'eye/group/chain'
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
- if other.hidden
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
@@ -2,7 +2,14 @@ module Eye::Group::Chain
2
2
 
3
3
  private
4
4
 
5
- def chain_schedule(type, grace, command, *args)
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, command, *args)
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, command, *args)
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
- # this is very hackety, because call method of the process without its scheduler
46
- # need to provide some scheduler future
47
- process.last_scheduled_reason = last_scheduled_reason
48
- process.send(command, *args)
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.send_command(command, *args)
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 ? (grace.to_f rescue DEFAULT_CHAIN) : DEFAULT_CHAIN
79
+ grace = (grace || DEFAULT_CHAIN).to_f rescue DEFAULT_CHAIN
78
80
 
79
- { type: type, grace: grace }
81
+ [type, grace]
80
82
  else
81
83
  # default chain case
82
- { type: :async, grace: DEFAULT_CHAIN }
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
@@ -6,5 +6,5 @@ gem 'celluloid-io', '~> 0.17.0'
6
6
  gem 'nio4r'
7
7
  gem 'timers'
8
8
 
9
- gem 'state_machine'
9
+ gem 'state_machines'
10
10
  gem 'sigar', '~> 0.7.3'
@@ -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.downcase == 'stdout'
77
- @dev_fd = STDERR if @dev.to_s.downcase == 'stderr'
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
@@ -35,6 +35,8 @@ class Eye::Process
35
35
  @states_history = Eye::Process::StatesHistory.new(100)
36
36
  @states_history << :unmonitored
37
37
 
38
+ @state_call = {}
39
+
38
40
  debug { "creating with config: #{@config.inspect}" }
39
41
 
40
42
  add_triggers
@@ -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, Eye::Reason.new(:no_start_command)
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 StateMachine::InvalidTransition, Eye::Process::StateError => e
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, Eye::Reason.new(:'not stopped (soft command)')
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 StateMachine::InvalidTransition, Eye::Process::StateError => e
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 StateMachine::InvalidTransition, Eye::Process::StateError => e
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.3) { !process_really_running? }
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
- sleep_grace(:stop_grace)
133
-
134
- else # default command
135
- debug { "executing: `kill -TERM #{self.pid}` with stop_grace: #{self[:stop_grace].to_f}s" }
136
- send_signal(:TERM)
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