uc 0.0.7 → 0.0.8

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 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