eye 0.1.11

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 (190) hide show
  1. data/.gitignore +31 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +132 -0
  6. data/Rakefile +18 -0
  7. data/bin/eye +282 -0
  8. data/bin/loader_eye +56 -0
  9. data/examples/processes/em.rb +56 -0
  10. data/examples/processes/forking.rb +20 -0
  11. data/examples/processes/sample.rb +144 -0
  12. data/examples/rbenv.eye +11 -0
  13. data/examples/test.eye +65 -0
  14. data/examples/unicorn.eye +29 -0
  15. data/eye.gemspec +37 -0
  16. data/lib/eye.rb +25 -0
  17. data/lib/eye/application.rb +65 -0
  18. data/lib/eye/checker.rb +118 -0
  19. data/lib/eye/checker/cpu.rb +27 -0
  20. data/lib/eye/checker/file_ctime.rb +29 -0
  21. data/lib/eye/checker/file_size.rb +38 -0
  22. data/lib/eye/checker/http.rb +94 -0
  23. data/lib/eye/checker/memory.rb +27 -0
  24. data/lib/eye/checker/socket.rb +148 -0
  25. data/lib/eye/checker/validation.rb +49 -0
  26. data/lib/eye/child_process.rb +75 -0
  27. data/lib/eye/client.rb +32 -0
  28. data/lib/eye/control.rb +2 -0
  29. data/lib/eye/controller.rb +43 -0
  30. data/lib/eye/controller/commands.rb +64 -0
  31. data/lib/eye/controller/helpers.rb +61 -0
  32. data/lib/eye/controller/load.rb +224 -0
  33. data/lib/eye/controller/send_command.rb +88 -0
  34. data/lib/eye/controller/status.rb +136 -0
  35. data/lib/eye/dsl.rb +52 -0
  36. data/lib/eye/dsl/application_opts.rb +33 -0
  37. data/lib/eye/dsl/chain.rb +12 -0
  38. data/lib/eye/dsl/child_process_opts.rb +7 -0
  39. data/lib/eye/dsl/config_opts.rb +11 -0
  40. data/lib/eye/dsl/group_opts.rb +27 -0
  41. data/lib/eye/dsl/helpers.rb +12 -0
  42. data/lib/eye/dsl/main.rb +58 -0
  43. data/lib/eye/dsl/opts.rb +88 -0
  44. data/lib/eye/dsl/process_opts.rb +21 -0
  45. data/lib/eye/dsl/pure_opts.rb +132 -0
  46. data/lib/eye/dsl/validate.rb +41 -0
  47. data/lib/eye/group.rb +125 -0
  48. data/lib/eye/group/chain.rb +68 -0
  49. data/lib/eye/io/unix_server.rb +44 -0
  50. data/lib/eye/io/unix_socket.rb +39 -0
  51. data/lib/eye/loader.rb +13 -0
  52. data/lib/eye/logger.rb +80 -0
  53. data/lib/eye/process.rb +83 -0
  54. data/lib/eye/process/child.rb +61 -0
  55. data/lib/eye/process/commands.rb +256 -0
  56. data/lib/eye/process/config.rb +70 -0
  57. data/lib/eye/process/controller.rb +72 -0
  58. data/lib/eye/process/data.rb +46 -0
  59. data/lib/eye/process/monitor.rb +97 -0
  60. data/lib/eye/process/notify.rb +17 -0
  61. data/lib/eye/process/scheduler.rb +50 -0
  62. data/lib/eye/process/states.rb +92 -0
  63. data/lib/eye/process/states_history.rb +62 -0
  64. data/lib/eye/process/system.rb +60 -0
  65. data/lib/eye/process/trigger.rb +32 -0
  66. data/lib/eye/process/watchers.rb +67 -0
  67. data/lib/eye/server.rb +51 -0
  68. data/lib/eye/settings.rb +35 -0
  69. data/lib/eye/system.rb +145 -0
  70. data/lib/eye/system_resources.rb +83 -0
  71. data/lib/eye/trigger.rb +53 -0
  72. data/lib/eye/trigger/flapping.rb +24 -0
  73. data/lib/eye/utils.rb +5 -0
  74. data/lib/eye/utils/alive_array.rb +31 -0
  75. data/lib/eye/utils/celluloid_chain.rb +51 -0
  76. data/lib/eye/utils/leak_19.rb +7 -0
  77. data/lib/eye/utils/tail.rb +20 -0
  78. data/spec/checker/cpu_spec.rb +58 -0
  79. data/spec/checker/file_ctime_spec.rb +34 -0
  80. data/spec/checker/file_size_spec.rb +107 -0
  81. data/spec/checker/http_spec.rb +109 -0
  82. data/spec/checker/memory_spec.rb +64 -0
  83. data/spec/checker/socket_spec.rb +116 -0
  84. data/spec/checker_spec.rb +188 -0
  85. data/spec/child_process/child_process_spec.rb +46 -0
  86. data/spec/client_server_spec.rb +34 -0
  87. data/spec/controller/commands_spec.rb +92 -0
  88. data/spec/controller/controller_spec.rb +133 -0
  89. data/spec/controller/find_objects_spec.rb +150 -0
  90. data/spec/controller/group_spec.rb +110 -0
  91. data/spec/controller/intergration_spec.rb +327 -0
  92. data/spec/controller/load_spec.rb +326 -0
  93. data/spec/controller/races_spec.rb +70 -0
  94. data/spec/controller/stop_on_delete_spec.rb +157 -0
  95. data/spec/dsl/chain_spec.rb +140 -0
  96. data/spec/dsl/checks_spec.rb +202 -0
  97. data/spec/dsl/config_spec.rb +44 -0
  98. data/spec/dsl/dsl_spec.rb +73 -0
  99. data/spec/dsl/getter_spec.rb +223 -0
  100. data/spec/dsl/integration_spec.rb +311 -0
  101. data/spec/dsl/load_spec.rb +52 -0
  102. data/spec/dsl/process_spec.rb +330 -0
  103. data/spec/dsl/sub_procs_spec.rb +93 -0
  104. data/spec/dsl/with_server_spec.rb +104 -0
  105. data/spec/example/em.rb +57 -0
  106. data/spec/example/forking.rb +20 -0
  107. data/spec/example/sample.rb +154 -0
  108. data/spec/fixtures/dsl/0.rb +8 -0
  109. data/spec/fixtures/dsl/0a.rb +8 -0
  110. data/spec/fixtures/dsl/0c.rb +8 -0
  111. data/spec/fixtures/dsl/1.rb +5 -0
  112. data/spec/fixtures/dsl/bad.eye +6 -0
  113. data/spec/fixtures/dsl/configs/1.eye +3 -0
  114. data/spec/fixtures/dsl/configs/2.eye +1 -0
  115. data/spec/fixtures/dsl/configs/3.eye +1 -0
  116. data/spec/fixtures/dsl/configs/4.eye +3 -0
  117. data/spec/fixtures/dsl/empty.eye +20 -0
  118. data/spec/fixtures/dsl/include_test.eye +5 -0
  119. data/spec/fixtures/dsl/include_test/1.rb +6 -0
  120. data/spec/fixtures/dsl/include_test/ha.rb +4 -0
  121. data/spec/fixtures/dsl/include_test2.eye +5 -0
  122. data/spec/fixtures/dsl/integration.eye +30 -0
  123. data/spec/fixtures/dsl/integration2.eye +32 -0
  124. data/spec/fixtures/dsl/integration_locks.eye +30 -0
  125. data/spec/fixtures/dsl/integration_sor.eye +32 -0
  126. data/spec/fixtures/dsl/integration_sor2.eye +27 -0
  127. data/spec/fixtures/dsl/integration_sor3.eye +32 -0
  128. data/spec/fixtures/dsl/load.eye +25 -0
  129. data/spec/fixtures/dsl/load2.eye +7 -0
  130. data/spec/fixtures/dsl/load2_dup2.eye +13 -0
  131. data/spec/fixtures/dsl/load2_dup_pid.eye +7 -0
  132. data/spec/fixtures/dsl/load3.eye +10 -0
  133. data/spec/fixtures/dsl/load4.eye +7 -0
  134. data/spec/fixtures/dsl/load5.eye +8 -0
  135. data/spec/fixtures/dsl/load6.eye +17 -0
  136. data/spec/fixtures/dsl/load_dubls.eye +36 -0
  137. data/spec/fixtures/dsl/load_dup_ex_names.eye +15 -0
  138. data/spec/fixtures/dsl/load_error.eye +5 -0
  139. data/spec/fixtures/dsl/load_error_folder/load3.eye +10 -0
  140. data/spec/fixtures/dsl/load_error_folder/load4.eye +7 -0
  141. data/spec/fixtures/dsl/load_folder/load3.eye +10 -0
  142. data/spec/fixtures/dsl/load_folder/load4.eye +7 -0
  143. data/spec/fixtures/dsl/load_int.eye +8 -0
  144. data/spec/fixtures/dsl/load_int2.eye +13 -0
  145. data/spec/fixtures/dsl/load_logger.eye +26 -0
  146. data/spec/fixtures/dsl/load_logger2.eye +3 -0
  147. data/spec/fixtures/dsl/long_load.eye +5 -0
  148. data/spec/fixtures/dsl/subfolder1/proc1.rb +3 -0
  149. data/spec/fixtures/dsl/subfolder2.eye +9 -0
  150. data/spec/fixtures/dsl/subfolder2/common.rb +1 -0
  151. data/spec/fixtures/dsl/subfolder2/proc2.rb +3 -0
  152. data/spec/fixtures/dsl/subfolder2/sub/proc3.rb +6 -0
  153. data/spec/fixtures/dsl/subfolder3.eye +8 -0
  154. data/spec/fixtures/dsl/subfolder3/common.rb +1 -0
  155. data/spec/fixtures/dsl/subfolder3/proc4.rb +3 -0
  156. data/spec/fixtures/dsl/subfolder3/sub/proc5.rb +6 -0
  157. data/spec/fixtures/dsl/subfolder4.eye +6 -0
  158. data/spec/fixtures/dsl/subfolder4/a.rb +2 -0
  159. data/spec/fixtures/dsl/subfolder4/b.rb +1 -0
  160. data/spec/fixtures/dsl/subfolder4/c.rb +1 -0
  161. data/spec/mock_spec.rb +32 -0
  162. data/spec/process/checks/child_checks_spec.rb +79 -0
  163. data/spec/process/checks/cpu_spec.rb +114 -0
  164. data/spec/process/checks/ctime_spec.rb +43 -0
  165. data/spec/process/checks/fsize_spec.rb +22 -0
  166. data/spec/process/checks/http_spec.rb +52 -0
  167. data/spec/process/checks/intergration_spec.rb +32 -0
  168. data/spec/process/checks/memory_spec.rb +113 -0
  169. data/spec/process/child_process_spec.rb +125 -0
  170. data/spec/process/config_spec.rb +75 -0
  171. data/spec/process/controller_spec.rb +173 -0
  172. data/spec/process/monitoring_spec.rb +180 -0
  173. data/spec/process/restart_spec.rb +174 -0
  174. data/spec/process/scheduler_spec.rb +150 -0
  175. data/spec/process/start_spec.rb +261 -0
  176. data/spec/process/states_history_spec.rb +118 -0
  177. data/spec/process/stop_spec.rb +150 -0
  178. data/spec/process/system_spec.rb +100 -0
  179. data/spec/process/triggers/flapping_spec.rb +81 -0
  180. data/spec/process/update_config_spec.rb +63 -0
  181. data/spec/spec_helper.rb +120 -0
  182. data/spec/support/rr_celluloid.rb +36 -0
  183. data/spec/support/scheduler_hack.rb +16 -0
  184. data/spec/support/spec_support.rb +164 -0
  185. data/spec/system_resources_spec.rb +59 -0
  186. data/spec/system_spec.rb +170 -0
  187. data/spec/utils/alive_array_spec.rb +50 -0
  188. data/spec/utils/celluloid_chain_spec.rb +82 -0
  189. data/spec/utils/tail_spec.rb +21 -0
  190. metadata +558 -0
@@ -0,0 +1,88 @@
1
+ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
2
+
3
+ STR_OPTIONS = [ :pid_file, :working_dir, :stdout, :stderr, :stdall, :start_command,
4
+ :stop_command, :restart_command ]
5
+
6
+ create_options_methods(STR_OPTIONS, String)
7
+
8
+ BOOL_OPTIONS = [ :daemonize, :keep_alive, :control_pid, :auto_start, :stop_on_delete]
9
+
10
+ create_options_methods(BOOL_OPTIONS, [TrueClass, FalseClass])
11
+
12
+ INTERVAL_OPTIONS = [ :check_alive_period, :start_timeout, :restart_timeout, :stop_timeout, :start_grace,
13
+ :restart_grace, :stop_grace, :childs_update_period ]
14
+
15
+ create_options_methods(INTERVAL_OPTIONS, [Fixnum, Float])
16
+
17
+ OTHER_OPTIONS = [ :environment, :stop_signals ]
18
+
19
+ create_options_methods(OTHER_OPTIONS)
20
+
21
+
22
+
23
+ def initialize(name = nil, parent = nil)
24
+ super(name, parent)
25
+
26
+ # ensure delete subobjects which can appears from parent config
27
+ @config.delete :groups
28
+ @config.delete :processes
29
+
30
+ @config[:application] = parent.name if parent.is_a?(Eye::Dsl::ApplicationOpts)
31
+ @config[:group] = parent.name if parent.is_a?(Eye::Dsl::GroupOpts)
32
+
33
+ # hack for full name
34
+ @full_name = parent.full_name if @name == '__default__'
35
+ end
36
+
37
+ def checks(type, opts = {})
38
+ type = type.to_sym
39
+ raise Eye::Dsl::Error, "unknown checker type #{type}" unless Eye::Checker::TYPES[type]
40
+
41
+ opts.merge!(:type => type)
42
+ Eye::Checker.validate!(opts)
43
+
44
+ @config[:checks] ||= {}
45
+ @config[:checks][type] = opts
46
+ end
47
+
48
+ def triggers(type, opts = {})
49
+ type = type.to_sym
50
+ raise Eye::Dsl::Error, "unknown trigger type #{type}" unless Eye::Trigger::TYPES[type]
51
+
52
+ opts.merge!(:type => type)
53
+ Eye::Trigger.validate!(opts)
54
+
55
+ @config[:triggers] ||= {}
56
+ @config[:triggers][type] = opts
57
+ end
58
+
59
+ # clear checks from parent
60
+ def nochecks(type)
61
+ type = type.to_sym
62
+ raise Eye::Dsl::Error, "unknown checker type #{type}" unless Eye::Checker::TYPES[type]
63
+ @config[:checks].try :delete, type
64
+ end
65
+
66
+ # clear triggers from parent
67
+ def notriggers(type)
68
+ type = type.to_sym
69
+ raise Eye::Dsl::Error, "unknown trigger type #{type}" unless Eye::Trigger::TYPES[type]
70
+ @config[:triggers].try :delete, type
71
+ end
72
+
73
+ def set_environment(value)
74
+ raise Eye::Dsl::Error, "environment should be a hash, but not #{value.inspect}" unless value.is_a?(Hash)
75
+ @config[:environment] ||= {}
76
+ @config[:environment].merge!(value)
77
+ end
78
+
79
+ alias :env :environment
80
+
81
+ def set_stdall(value)
82
+ super
83
+
84
+ set_stdout value
85
+ set_stderr value
86
+ end
87
+
88
+ end
@@ -0,0 +1,21 @@
1
+ class Eye::Dsl::ProcessOpts < Eye::Dsl::Opts
2
+
3
+ def monitor_children(&block)
4
+ opts = Eye::Dsl::ChildProcessOpts.new
5
+ opts.instance_eval(&block)
6
+ @config[:monitor_children] ||= {}
7
+ @config[:monitor_children].merge!(opts.config)
8
+ end
9
+
10
+ def xmonitor_children(&block); end
11
+
12
+ def application
13
+ parent.try(:parent)
14
+ end
15
+ alias :app :application
16
+
17
+ def group
18
+ parent
19
+ end
20
+
21
+ end
@@ -0,0 +1,132 @@
1
+ class Eye::Dsl::PureOpts
2
+
3
+ def self.create_options_methods(arr, types = nil)
4
+ m = Module.new do
5
+ arr.each do |opt|
6
+ define_method("set_#{opt}") do |arg|
7
+ key = opt.to_sym
8
+
9
+ if (disallow_options && disallow_options.include?(key)) || (allow_options && !allow_options.include?(key))
10
+ raise Eye::Dsl::Error, "disallow option #{key} for #{self.class.inspect}"
11
+ end
12
+
13
+ if types
14
+ good_type = Array(types).any?{|type| arg.is_a?(type) } || arg.nil?
15
+ raise Eye::Dsl::Error, "bad :#{opt} value #{arg.inspect}, type should be #{types.inspect}" unless good_type
16
+ end
17
+
18
+ @config[key] = arg
19
+ end
20
+
21
+ define_method("get_#{opt}") do
22
+ @config[ opt.to_sym ]
23
+ end
24
+
25
+ define_method(opt) do |*args|
26
+ if args.blank?
27
+ # getter
28
+ send "get_#{opt}"
29
+ else
30
+ send "set_#{opt}", *args
31
+ end
32
+ end
33
+
34
+ define_method("#{opt}=") do |arg|
35
+ send opt, arg
36
+ end
37
+ end
38
+ end
39
+
40
+ self.send :include, m
41
+ end
42
+
43
+ attr_reader :name, :full_name
44
+ attr_reader :config, :parent
45
+
46
+ def initialize(name = nil, parent = nil)
47
+ @name = name.to_s
48
+ @full_name = @name
49
+
50
+ if parent
51
+ @parent = parent
52
+ @config = Marshal.load(Marshal.dump(parent.config)) # O_o ruby recommended deep clone
53
+ @full_name = "#{parent.full_name}:#{@full_name}"
54
+ else
55
+ @config = {}
56
+ end
57
+
58
+ @config[:name] = @name if @name.present?
59
+ end
60
+
61
+ def allow_options
62
+ nil
63
+ end
64
+
65
+ def disallow_options
66
+ []
67
+ end
68
+
69
+ # execute part of config on particular server
70
+ # array of strings
71
+ # regexp
72
+ # string
73
+ def with_server(glob = nil, &block)
74
+ on_server = true
75
+
76
+ if glob.present?
77
+ host = Eye::System.host
78
+
79
+ if glob.is_a?(Array)
80
+ on_server = !!glob.any?{|elem| elem == host}
81
+ elsif glob.is_a?(Regexp)
82
+ on_server = !!host.match(glob)
83
+ elsif glob.is_a?(String) || glob.is_a?(Symbol)
84
+ on_server = (host == glob.to_s)
85
+ end
86
+ end
87
+
88
+ with_condition(on_server, &block)
89
+
90
+ on_server
91
+ end
92
+
93
+ def with_condition(cond = true, &block)
94
+ self.instance_eval(&block) if cond && block
95
+ end
96
+
97
+ def self.with_parsed_file(file_name)
98
+ saved_parsed_filename = Eye.parsed_filename
99
+
100
+ require 'pathname'
101
+
102
+ real_filename = Eye.parsed_filename && File.symlink?(Eye.parsed_filename) ? File.readlink(Eye.parsed_filename) : Eye.parsed_filename
103
+ dirname = File.dirname(real_filename) rescue nil
104
+ path = Pathname.new(file_name).expand_path(dirname).to_s
105
+
106
+ Eye.parsed_filename = path
107
+ yield path
108
+ ensure
109
+ Eye.parsed_filename = saved_parsed_filename
110
+ end
111
+
112
+ def include(proc, *args)
113
+ if proc.is_a?(String)
114
+ self.class.with_parsed_file(proc) do |path|
115
+ if File.exists?(path)
116
+ Eye::Dsl.debug "=> load #{path}"
117
+ self.instance_eval(File.read(path))
118
+ Eye::Dsl.debug "<= load #{path}"
119
+ end
120
+ end
121
+ else
122
+ ie = if args.present?
123
+ lambda{|i| proc[i, *args] }
124
+ else
125
+ proc
126
+ end
127
+
128
+ self.instance_eval(&ie)
129
+ end
130
+ end
131
+
132
+ end
@@ -0,0 +1,41 @@
1
+ module Eye::Dsl::Validate
2
+
3
+ # validate global config rules
4
+ def validate(config)
5
+ cfg = config[:config]
6
+ config = config[:applications]
7
+
8
+ all_processes = config.values.map{|e| (e[:groups] || {}).values.map{|c| (c[:processes] || {}).values} }.flatten
9
+
10
+ # Check blank pid_files
11
+
12
+ no_pid_file = all_processes.select{|c| c[:pid_file].blank? }
13
+ if no_pid_file.present?
14
+ raise Eye::Dsl::Error, "blank pid_file for: #{no_pid_file.map{|c| c[:name]} * ', '}"
15
+ end
16
+
17
+ # Check dublicates of the full pid_file
18
+
19
+ dubl_pids = all_processes.each_with_object(Hash.new(0)) do |o, h|
20
+ ex_pid_file = Eye::System.normalized_file(o[:pid_file], o[:working_dir])
21
+ h[ex_pid_file] += 1
22
+ end
23
+ dubl_pids = dubl_pids.select{|k,v| v>1}
24
+
25
+ if dubl_pids.present?
26
+ raise Eye::Dsl::Error, "dublicate pid_files: #{dubl_pids.inspect}"
27
+ end
28
+
29
+ # Check dublicates of the full_name
30
+ dubl_names = all_processes.each_with_object(Hash.new(0)) do |o, h|
31
+ full_name = "#{o[:application]}:#{o[:group]}:#{o[:name]}"
32
+ h[full_name] += 1
33
+ end
34
+ dubl_names = dubl_names.select{|k,v| v>1}
35
+
36
+ if dubl_names.present?
37
+ raise Eye::Dsl::Error, "dublicate names: #{dubl_names.inspect}"
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,125 @@
1
+ require 'celluloid'
2
+
3
+ class Eye::Group
4
+ include Celluloid
5
+
6
+ autoload :Chain, 'eye/group/chain'
7
+
8
+ include Eye::Logger::Helpers
9
+ include Eye::Process::Scheduler
10
+ include Eye::Group::Chain
11
+
12
+ attr_reader :processes, :name, :hidden, :config
13
+
14
+ def initialize(name, config)
15
+ @name = name
16
+ @config = config
17
+ @logger = Eye::Logger.new(full_name)
18
+ @processes = Eye::Utils::AliveArray.new
19
+ @hidden = (name == '__default__')
20
+ debug 'created'
21
+ end
22
+
23
+ def full_name
24
+ @full_name ||= "#{@config[:application]}:#{@name}"
25
+ end
26
+
27
+ def update_config(cfg)
28
+ @config = cfg
29
+ @full_name = nil
30
+ end
31
+
32
+ def add_process(process)
33
+ @processes << process
34
+ end
35
+
36
+ # sort processes in name order
37
+ def resort_processes
38
+ @processes = @processes.sort_by(&:name)
39
+ end
40
+
41
+ def status_data(debug = false)
42
+ plist = @processes.map{|p| p.status_data(debug) }
43
+
44
+ h = { name: name, type: :group, subtree: plist }
45
+
46
+ h.merge!(debug: debug_data) if debug
47
+
48
+ # show current chain
49
+ if current_scheduled_command
50
+ h.update(current_command: current_scheduled_command)
51
+
52
+ if (chain_commands = scheduler_actions_list) && chain_commands.present?
53
+ h.update(chain_commands: chain_commands)
54
+ end
55
+
56
+ if @chain_processes_current && @chain_processes_count
57
+ h.update(chain_progress: [@chain_processes_current, @chain_processes_count])
58
+ end
59
+ end
60
+
61
+ h
62
+ end
63
+
64
+ def debug_data
65
+ {:queue => scheduler_actions_list, :chain => chain_status}
66
+ end
67
+
68
+ def send_command(command, *args)
69
+ info "send_command: #{command}"
70
+
71
+ if command == :delete
72
+ delete *args
73
+ else
74
+ schedule command, *args, "#{command} by user"
75
+ end
76
+ end
77
+
78
+ def start
79
+ chain_command :start
80
+ end
81
+
82
+ def stop
83
+ async_schedule :stop
84
+ end
85
+
86
+ def restart
87
+ chain_command :restart
88
+ end
89
+
90
+ def delete
91
+ async_schedule :delete
92
+ terminate
93
+ end
94
+
95
+ def monitor
96
+ chain_command :monitor
97
+ end
98
+
99
+ def unmonitor
100
+ async_schedule :unmonitor
101
+ end
102
+
103
+ def signal(sig)
104
+ async_schedule :signal, sig
105
+ end
106
+
107
+ def clear
108
+ @processes.clear
109
+ end
110
+
111
+ def sub_object?(obj)
112
+ @processes.include?(obj)
113
+ end
114
+
115
+ private
116
+
117
+ def async_schedule(command, *args)
118
+ info "send to all processes #{command} #{args.present? ? args*',' : nil}"
119
+
120
+ @processes.each do |process|
121
+ process.send_command(command, *args)
122
+ end
123
+ end
124
+
125
+ end
@@ -0,0 +1,68 @@
1
+ module Eye::Group::Chain
2
+
3
+ private
4
+
5
+ def chain_schedule(type, grace, command, *args)
6
+ info "start #{type} with #{grace}s chain #{command} #{args}"
7
+
8
+ @chain_processes_count = @processes.size
9
+ @chain_processes_current = 0
10
+
11
+ @processes.each do | process |
12
+ chain_schedule_process(process, type, command, *args)
13
+
14
+ @chain_processes_current = @chain_processes_current.to_i + 1
15
+
16
+ # to skip last sleep
17
+ break if @chain_processes_current.to_i == @chain_processes_count.to_i
18
+
19
+ # wait next process
20
+ sleep grace.to_f
21
+ end
22
+
23
+ @chain_processes_count = nil
24
+ @chain_processes_current = nil
25
+ end
26
+
27
+ def chain_schedule_process(process, type, command, *args)
28
+ if type == :sync
29
+ # sync command, with waiting
30
+ process.send(command, *args)
31
+ else
32
+ # async command
33
+ process.send_command(command, *args)
34
+ end
35
+ end
36
+
37
+ def chain_status
38
+ if @config[:chain]
39
+ [:start, :restart].map{|c| @config[:chain][c].try(:[], :grace) }
40
+ end
41
+ end
42
+
43
+ def chain_command(command, *args)
44
+ chain_opts = chain_options(command)
45
+ chain_schedule(chain_opts[:type], chain_opts[:grace], command, *args)
46
+ end
47
+
48
+ # with such delay will chained processes by default
49
+ DEFAULT_CHAIN = 0.2
50
+
51
+ def chain_options(command)
52
+ command = :start if command == :monitor # hack for monitor command, work as start
53
+
54
+ if @config[:chain] && @config[:chain][command]
55
+ type = @config[:chain][command].try :[], :type
56
+ type = [:async, :sync].include?(type) ? type : :async
57
+
58
+ grace = @config[:chain][command].try :[], :grace
59
+ grace = grace ? (grace.to_f rescue DEFAULT_CHAIN) : DEFAULT_CHAIN
60
+
61
+ {:type => type, :grace => grace}
62
+ else
63
+ # default chain case
64
+ {:type => :async, :grace => DEFAULT_CHAIN}
65
+ end
66
+ end
67
+
68
+ end