uc 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 59c522f2247a747ec300e7cafbd827b7700f18be
4
- data.tar.gz: 7303d81d3893d08bed3de0856835014df3882efe
3
+ metadata.gz: a1136a67ca433cebf902cb4bb1eacc673e61abed
4
+ data.tar.gz: 77019d47d98b56c17929eff36c90fd7c8aa8a487
5
5
  SHA512:
6
- metadata.gz: 7bda91add1413b1fa20739eaf23b975d45920e8dd8739fce7d2d7de97db8ba1b18d9762337ced2c796203882d2a188e29dececa291e93d1ef2df7e9a31489f03
7
- data.tar.gz: e9764c28553b46752e4d1c0689ca93a5aed0e601c0c7d3e38a531d434ee3159e66fa12c690ebb3b8bcf41cb18960d35e8b37caaededa8898c99c525b2f1f6bc1
6
+ metadata.gz: 2f331fac3d78f17fca9267e1213d225c9b9ed0ba83ee1ea452199605a376fd02174336b4bae6cf45ace8013081f6b5b826b06c3e4ef760bc7fe7a5d9b7116cf6
7
+ data.tar.gz: 047df981a85aa29710c2ba2cd26e27dcc25b5c0ab716eb1d94a505b29c13801a3d16a50742921b7051a8760f4c863d6fc93b4bf2da76d9aebb02ac1442a4060c
data/bin/uc CHANGED
@@ -42,8 +42,8 @@ opts_parser = OptionParser.new do |opts|
42
42
  end
43
43
 
44
44
  opts.on("--debug", "Show debug messages") do
45
+ options[:debug] = true
45
46
  logger.level = ::Logger::DEBUG
46
- ENV["UC_DEBUG"] = "true"
47
47
  end
48
48
 
49
49
  opts.on_tail("-h", "--help", "Show this message") do
@@ -55,13 +55,11 @@ end
55
55
  begin
56
56
  opts_parser.parse!(ARGV)
57
57
  app_dir = options[:app_dir] || Dir.pwd
58
- lock = ::Uc::Lock.new(app_dir)
59
- lock.acquire
60
- server = ::Uc::Server.new(app_dir, rails_env: options[:rails_env])
58
+ server = ::Uc::Server.new(app_dir, rails_env: options[:rails_env], debug: options[:debug])
61
59
  command = ARGV.shift
62
60
 
63
61
  case command
64
- when "start", "stop", "restart", "status"
62
+ when "start", "stop", "restart", "status", "print_config"
65
63
  server.send command.to_sym
66
64
  when "rr", "rolling-restart"
67
65
  server.rolling_restart
@@ -69,9 +67,16 @@ begin
69
67
  logger.error "No command specified"
70
68
  puts opts_parser
71
69
  abort
70
+ else
71
+ logger.error "No such command #{command}"
72
+ abort
72
73
  end
73
74
 
74
75
  rescue OptionParser::InvalidOption, OptionParser::MissingArgument, ::Uc::Error => e
75
- logger.error "#{e.message}"
76
- abort
76
+ if options[:debug]
77
+ raise e
78
+ else
79
+ logger.error "#{e.message}"
80
+ abort
81
+ end
77
82
  end
@@ -0,0 +1,44 @@
1
+ require 'uc/unicorn/api'
2
+ require 'uc/unicorn/config'
3
+ app_dir = "/path/to/app/dir"
4
+
5
+ uc = ::Uc::Unicorn::Api.new
6
+ uconfig = ::Uc::Unicorn::Config.new(app_dir)
7
+
8
+ worker_processes 5
9
+ working_directory app_dir
10
+ timeout 30
11
+ listen uconfig.socket_file, :backlog => 128
12
+ pid uconfig.pid_file
13
+ stdout_path uconfig.stdout_log
14
+ stderr_path uconfig.stderr_log
15
+
16
+ preload_app true
17
+
18
+ GC.respond_to?(:copy_on_write_friendly=) and
19
+ GC.copy_on_write_friendly = true
20
+
21
+ check_client_connection false
22
+
23
+ before_fork do |server, worker|
24
+ # the following is highly recomended for Rails + "preload_app true"
25
+ # as there's no need for the master process to hold a connection
26
+ defined?(ActiveRecord::Base) and
27
+ ActiveRecord::Base.connection.disconnect!
28
+
29
+ if defined?(Resque)
30
+ Resque.redis.quit
31
+ Rails.logger.info('Disconnected from Redis')
32
+ end
33
+ uc.rolling_restart(server, worker, prestart_wait: 5)
34
+ end
35
+
36
+ after_fork do |server, worker|
37
+ defined?(ActiveRecord::Base) and
38
+ ActiveRecord::Base.establish_connection
39
+ uc.prestart server, worker, url: "/in"
40
+ end
41
+
42
+ before_exec do |server|
43
+ uc.clean_env
44
+ end
data/lib/uc/config.rb ADDED
@@ -0,0 +1,95 @@
1
+ require 'uc/logger'
2
+
3
+ module Uc
4
+ class Config
5
+
6
+ include ::Uc::Logger
7
+
8
+ def initialize(app_dir, config_file = nil)
9
+ @config_file = config_file
10
+ @app_dir = app_dir
11
+ end
12
+
13
+ def config_file
14
+ @config_file ||= "#{app_dir}/config/uc.rb"
15
+ end
16
+
17
+ def config
18
+ return @config if @config
19
+ @config = {
20
+ instances: 2,
21
+ queue_size: 1024,
22
+ timeout: 30,
23
+ prestart_url: "/",
24
+ working_dir: @app_dir,
25
+ event_queue: "unicorn_#{Process.uid}",
26
+ ready_wait: 5
27
+ }
28
+ read_from_file
29
+ return @config
30
+ end
31
+
32
+ def to_h
33
+ config
34
+ end
35
+
36
+ def ready_wait(wait_timeout)
37
+ config[:ready_wait] = wait_timeout.to_i
38
+ end
39
+
40
+ def event_queue_name
41
+ config[:event_queue]
42
+ end
43
+
44
+ def instances(num_instances)
45
+ config[:instances] = num_instances
46
+ end
47
+
48
+ def backlog(queue_size)
49
+ config[:queue_size] = queue_size
50
+ end
51
+
52
+ def prestart_url(url)
53
+ config[:prestart_url] = url
54
+ end
55
+
56
+ def timeout(secs)
57
+ config[:timeout] = secs
58
+ end
59
+
60
+ def working_dir
61
+ config[:working_dir] = working_dir
62
+ end
63
+
64
+ def event_queue(event_queue)
65
+ config[:event_queue] = event_queue
66
+ end
67
+
68
+ def app_dir
69
+ config[:working_dir]
70
+ end
71
+
72
+ def env_hash
73
+ @env_hash ||= {}
74
+ end
75
+
76
+ def env(key, value)
77
+ env_hash[key] = value
78
+ end
79
+
80
+ def load_env
81
+ config
82
+ env_hash.each do |k,v|
83
+ ENV[k] = v
84
+ end
85
+ end
86
+
87
+ def read_from_file
88
+ return if not File.readable? config_file
89
+ instance_eval(File.read(config_file))
90
+ rescue NoMethodError => e
91
+ logger.warn "invalid option used in config: #{e.name}"
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,24 @@
1
+ require 'logger'
2
+ module Uc
3
+ class CustomLogger < ::Logger
4
+
5
+ def initialize(file)
6
+ super(file)
7
+ @level = ::Logger::INFO
8
+ end
9
+
10
+ def format_message(severity, timestamp, progname, msg)
11
+ case severity
12
+ when "INFO"
13
+ "#{msg}\n"
14
+ when "ERROR"
15
+ "#{severity.bold.red} #{msg}\n"
16
+ when "WARN"
17
+ "#{severity.downcase.bold.yellow} #{msg}\n"
18
+ else
19
+ "#{severity.downcase.bold.blue} #{msg}\n"
20
+ end
21
+ end
22
+
23
+ end
24
+ end
data/lib/uc/event.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Uc
2
+ class Event < ::Struct.new(:type, :msg)
3
+ end
4
+ end
@@ -0,0 +1,162 @@
1
+ require 'uc/ext/string'
2
+ require 'uc/mqueue'
3
+ require 'uc/event'
4
+
5
+ module Uc
6
+ class EventStream
7
+
8
+ attr_reader :queue_name
9
+ attr_accessor :debug_output
10
+
11
+ def initialize(queue_name)
12
+ @queue_name = queue_name
13
+ end
14
+
15
+ def info(msg)
16
+ pub :info, msg
17
+ end
18
+
19
+ def debug(msg)
20
+ pub :debug, msg
21
+ end
22
+
23
+ def warn(msg)
24
+ pub :warn, msg
25
+ end
26
+
27
+ def fatal(msg)
28
+ pub :fatal, msg
29
+ end
30
+
31
+ def pub(type, msg)
32
+ tmsg = truncate "#{type}|#{msg}"
33
+ writer.send tmsg
34
+ rescue Errno::ENOENT, Errno::EAGAIN, Errno::EACCES, Errno::EMSGSIZE => e
35
+ puts "#{e.class} #{e.message}"
36
+ end
37
+
38
+ def truncate(msg)
39
+ if msg.size <= mq.msg_size
40
+ return msg
41
+ else
42
+ msg = "#{msg[0, mq.msg_size - 3] }..."
43
+ end
44
+ end
45
+
46
+ def watch(event_type, timeout: 30, recreate: true, &block)
47
+ mq.recreate if recreate
48
+ mq.clear
49
+ yield
50
+ wait(event_type, timeout, output: true)
51
+ rescue => e
52
+ raise uc_error(e)
53
+ end
54
+
55
+ def watch_in_background(event_type, timeout: 30, recreate: true, &block)
56
+ begin
57
+ mq.recreate if recreate
58
+ mq.clear
59
+ t = wait_in_background(event_type, timeout, output: true, first_timeout: 50)
60
+ yield
61
+ t.join
62
+ raise t[:error] if t[:error]
63
+ rescue => e
64
+ raise uc_error(e)
65
+ ensure
66
+ t.kill if t
67
+ end
68
+ end
69
+
70
+ def wait(event_type, timeout, output: false, first_timeout: nil)
71
+ event_type = event_type.to_s
72
+ message = ""
73
+ event = ""
74
+ t = first_timeout || timeout
75
+ mq.reader do |r|
76
+ loop do
77
+ r.receive(message, t)
78
+ t = timeout
79
+ event = parse message
80
+ print event if output
81
+ break if event.type == event_type
82
+ end
83
+ end
84
+ puts "#{"success".green.bold} #{event.msg}"
85
+ true
86
+ end
87
+
88
+ def wait_in_background(event_type, timeout, **kwargs)
89
+ Thread.new do
90
+ begin
91
+ wait(event_type, timeout, **kwargs)
92
+ rescue => e
93
+ Thread.current[:error] = e
94
+ false
95
+ end
96
+ end
97
+ end
98
+
99
+ def print(event)
100
+ case event.type
101
+ when "info"
102
+ puts event.msg
103
+ when "warn"
104
+ puts "#{"warn".yellow.bold} #{event.msg}"
105
+ when "debug"
106
+ puts "#{"debug".blue.bold} #{event.msg}" if debug_output
107
+ when "fatal"
108
+ raise ::Uc::Error, event.msg
109
+ end
110
+ end
111
+
112
+ def close_connections
113
+ writer.close if writer
114
+ @writer = nil
115
+ end
116
+
117
+
118
+ private
119
+
120
+ def read(timeout)
121
+ event = ""
122
+ reader do |r|
123
+ r.receive(event, timeout)
124
+ parse event
125
+ end
126
+ end
127
+
128
+ def parse(event_str)
129
+ arr = event_str.split("|",2)
130
+ if arr.length == 2
131
+ type, msg = arr[0], arr[1]
132
+ else
133
+ type, msg = "unknown", event
134
+ end
135
+ event = ::Uc::Event.new(type, msg)
136
+ end
137
+
138
+ def mq
139
+ @mq ||= ::Uc::Mqueue.new(@queue_name)
140
+ end
141
+
142
+ def writer
143
+ @writer ||= mq.nb_writer
144
+ end
145
+
146
+ def uc_error(e)
147
+ case e
148
+ when Errno::EACCES
149
+ msg = "unable to setup message queue"
150
+ when Errno::ENOENT
151
+ msg = "message queue deleted"
152
+ when Errno::ETIMEDOUT
153
+ msg = "timeout reached while waiting for server ready msg"
154
+ else
155
+ return e
156
+ end
157
+
158
+ return ::Uc::Error.new(msg)
159
+ end
160
+
161
+ end
162
+ end
@@ -0,0 +1,29 @@
1
+ class String
2
+ def colorize(color_code)
3
+ "\e[#{color_code}m#{self}\e[0m"
4
+ end
5
+
6
+ def bold
7
+ "\e[1m#{self}\e[0m"
8
+ end
9
+
10
+ def white
11
+ colorize(37)
12
+ end
13
+
14
+ def green
15
+ colorize(32)
16
+ end
17
+
18
+ def yellow
19
+ colorize(33)
20
+ end
21
+
22
+ def red
23
+ colorize(31)
24
+ end
25
+
26
+ def blue
27
+ colorize(34)
28
+ end
29
+ end
data/lib/uc/logger.rb CHANGED
@@ -1,32 +1,45 @@
1
1
  require 'logger'
2
- require 'uc/mq_logger'
2
+ require 'uc/custom_logger'
3
+ require 'uc/event_stream'
3
4
  module Uc
4
5
  module Logger
5
-
6
+
7
+ class << self
8
+ attr_reader :event_queue
9
+ end
10
+
11
+ def self.event_queue=(queue_name)
12
+ @event_stream = nil
13
+ @event_queue = queue_name
14
+ end
15
+
6
16
  def self.logger
7
- @logger ||= begin
8
- logger = ::Logger.new(STDOUT)
9
- logger.formatter = proc do |severity, datetime, progname, msg|
10
- if severity == "INFO"
11
- "#{msg}\n"
12
- else
13
- "#{severity} #{msg}\n"
14
- end
15
- end
16
- logger.level = ::Logger::INFO
17
- logger
18
- end
17
+ @logger ||= ::Uc::CustomLogger.new(STDOUT)
18
+ end
19
+
20
+ def self.stderr
21
+ @stderr ||= ::Logger.new(STDERR)
22
+ end
23
+
24
+
25
+ def self.event_stream
26
+ @event_stream ||= ::Uc::EventStream.new(event_queue)
27
+ end
28
+
29
+ def event_stream
30
+ ::Uc::Logger.event_stream
19
31
  end
20
32
 
21
33
  def logger
22
34
  ::Uc::Logger.logger
23
35
  end
24
36
 
25
- def mq_log(msg)
26
- return if not respond_to? :queue_name
27
- @mq_logger ||= ::Uc::MqLogger.new(queue_name)
28
- @mq_logger.log msg
29
- end
37
+ def stderr
38
+ ::Uc::Logger.stderr
39
+ end
30
40
 
41
+ def event_queue
42
+ ::Uc::Logger.event_queue
43
+ end
31
44
  end
32
45
  end
data/lib/uc/mqueue.rb CHANGED
@@ -4,7 +4,7 @@ module Uc
4
4
 
5
5
  attr_reader :name, :max_msg, :msg_size
6
6
 
7
- def initialize(name, max_msg: 10, msg_size: 100)
7
+ def initialize(name, max_msg: 15, msg_size: 70)
8
8
  @name = name
9
9
  @max_msg = max_msg
10
10
  @msg_size = msg_size
data/lib/uc/paths.rb ADDED
@@ -0,0 +1,109 @@
1
+ require 'pathname'
2
+ require 'uc/logger'
3
+
4
+ module Uc
5
+ class Paths
6
+
7
+ include ::Uc::Logger
8
+
9
+ attr_reader :app_dir
10
+
11
+ def initialize(app_dir)
12
+ @app_dir = Pathname.new(app_dir )
13
+ end
14
+
15
+ def rack
16
+ absolute_path "config.ru"
17
+ end
18
+
19
+ def log_dir
20
+ absolute_path "log"
21
+ end
22
+
23
+ def tmp_dir
24
+ absolute_path "tmp"
25
+ end
26
+
27
+ def socket_dir
28
+ absolute_path "tmp/sockets"
29
+ end
30
+
31
+ def pid_dir
32
+ absolute_path "tmp/pids"
33
+ end
34
+
35
+ def errors
36
+ @errors ||= []
37
+ end
38
+
39
+ def validate_required
40
+ validate_required_dirs
41
+ verify_readable rack
42
+ log_and_raise_errors
43
+ end
44
+
45
+ private
46
+
47
+ def log_and_raise_errors
48
+ if not errors.empty?
49
+ errors.each { |e| logger.error e }
50
+ raise ::Uc::Error, "exiting due to missing dirs/files"
51
+ end
52
+ end
53
+
54
+ def required_dirs
55
+ [ app_dir, tmp_dir, log_dir, socket_dir, pid_dir ]
56
+ end
57
+
58
+ def validate_required_dirs
59
+ required_dirs.each do |d|
60
+ validate_dir(d)
61
+ end
62
+ end
63
+
64
+ def throw_error(type, path)
65
+ rel_path = rpath(path)
66
+ case type
67
+ when :not_exist
68
+ msg = "path doesn't exist => #{rel_path}"
69
+ when :not_writable
70
+ msg = "path not writable => #{rel_path}"
71
+ when :not_dir
72
+ msg = "path not a directory => #{rel_path}"
73
+ end
74
+ throw :error, msg
75
+ end
76
+
77
+ def validate_dir(dir)
78
+ relative_path = rpath(dir)
79
+ error = catch(:error) do
80
+ throw_error :not_exist, dir if not File.exist? dir
81
+ throw_error :not_writable, dir if not File.writable? dir
82
+ throw_error :not_dir, dir if not File.directory? dir
83
+ end
84
+ errors << error if error
85
+ end
86
+
87
+ def verify_readable(path)
88
+ relative_path = rpath(path)
89
+ if not File.readable? path
90
+ errors << "path not readable => #{relative_path}"
91
+ return false
92
+ else
93
+ return true
94
+ end
95
+ end
96
+
97
+ def absolute_path(path)
98
+ path = Pathname.new(path)
99
+ raise "absolute path specified: #{path}" if path.absolute?
100
+ "#{app_dir}/#{path}"
101
+ end
102
+
103
+ def rpath(abs_path)
104
+ path = Pathname.new abs_path
105
+ rel_path = path.relative_path_from(app_dir)
106
+ end
107
+
108
+ end
109
+ end