reifier 0.3.0 → 0.4.0

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: c728b806deb19da5dcfa300f0a686b0981d369d8
4
- data.tar.gz: 8f9b2057ca56169779e32e71037f12df61bacd4c
3
+ metadata.gz: aa60f4a229669e2c71cccd301f93309a67fa48d6
4
+ data.tar.gz: 731f667e0829f067924abbf80ed8d4f5e88f559c
5
5
  SHA512:
6
- metadata.gz: b63257d7a6c23bfaadddfa3e0f11e9905d8ce5c0059ef7444db6259f62591076f8a1f240fe49fa0c326411eb9db99c84f3bc68454c186b0505b798c56e50a231
7
- data.tar.gz: 0717702206a003c2749e7dd018928a3ad68a71635e78e1300ba18396762a38c7f1dc9128c83dd9efe5a036ee0e7aba556e9ef0e99a96277974b5e9f3b73dc321
6
+ metadata.gz: 167c3dff17ad61c8fa5a5be610939603df0516d61eedf96e1d3545ae3bf13701c60ba8a554f4eaf34a9685d37550707e76c649eb859e6d7ec9e6eed4495143d2
7
+ data.tar.gz: b04ce039f7d7a1a86589f3fecc8514d28a09a4ebbab06ddab4a3b3956ea9c292a21bbb17d2e387e29c1bd740e03b57cbdb266ad1927b5db452976980bd55e8c5
data/README.md CHANGED
@@ -6,9 +6,11 @@ reify
6
6
 
7
7
  (transitive) to consider or make (an abstract idea or concept) real or concrete
8
8
 
9
+ Reifier is a threaded and pre forked rack app server written in pure ruby.
10
+
9
11
  ## Is it any good?
10
12
 
11
- [Yes](http://news.ycombinator.com/item?id=3067434), no really just a fun project use it in production when u want :P
13
+ [Yes](http://news.ycombinator.com/item?id=3067434), no really just a fun project use it in production if you want :P
12
14
 
13
15
  ## Y u no benchmark?!
14
16
 
@@ -39,7 +41,7 @@ Use it through rackup:
39
41
 
40
42
  ## Available Options
41
43
 
42
- You can adapt the ThreadPool sized with following option:
44
+ You can adapt the ThreadPool size with following option:
43
45
 
44
46
  $ rackup -s reifier -O Threads=8
45
47
 
@@ -47,6 +49,16 @@ Also the amount of workers is adaptable:
47
49
 
48
50
  $ rackup -s reifier -O Workers=5
49
51
 
52
+ ## Config File
53
+
54
+ You can also use a config file for these and more settings.
55
+
56
+ When you are using `rails s` reifier tries to load the file from `Rails.root/config/reifier.rb`
57
+
58
+ When you are using any other rack app it tries to load the file from `Dir.pwd/config/reifier.rb`
59
+
60
+ See the [example config](examples/reifier.rb)
61
+
50
62
  ## Development
51
63
 
52
64
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,2 @@
1
+ threads 8 # Using a thread pool size of 8
2
+ workers 9 # Using 9 worker processes
@@ -5,20 +5,22 @@ module Rack
5
5
  module Handler
6
6
  module Reifier
7
7
  DEFAULT_OPTIONS = {
8
- Workers: 3,
8
+ Workers: 1,
9
9
  Threads: 16
10
10
  }.freeze
11
11
 
12
12
  def self.run(app, options = {})
13
13
  options = DEFAULT_OPTIONS.merge(options)
14
- puts "Reifier #{::Reifier::VERSION} starting.."
14
+ puts "======= Reifier #{::Reifier::VERSION} starting ======="
15
15
  server = ::Reifier::Server.new(app, options)
16
+ server.load_configuration
16
17
  server.start
17
18
  end
18
19
 
19
20
  def self.valid_options
20
21
  {
21
- 'Threads=THREADS' => 'Number of threads (default: 5)'
22
+ 'Threads=THREADS' => 'Number of threads (default: 16)',
23
+ 'Workers=WORKERS' => 'Number of workers (default: 1)'
22
24
  }
23
25
  end
24
26
  end
@@ -2,16 +2,17 @@ module Reifier
2
2
  class Request
3
3
  attr_reader :request_method, :request_path, :protocol, :request_uri
4
4
 
5
- def initialize(options)
5
+ def initialize(socket, options)
6
+ @socket = socket
6
7
  @body = StringIO.new('')
7
8
  @options = options
8
9
  end
9
10
 
10
- def handle(socket)
11
- handle_request_line(socket)
12
- handle_headers(socket)
11
+ def handle
12
+ handle_request_line
13
+ handle_headers
13
14
 
14
- handle_body(socket) if request_with_body?
15
+ handle_body if request_with_body?
15
16
  end
16
17
 
17
18
  def rack_env
@@ -34,7 +35,9 @@ module Reifier
34
35
  'SERVER_PROTOCOL' => @protocol,
35
36
  'SERVER_SOFTWARE' => "Reifier #{Reifier::VERSION}",
36
37
  'SERVER_NAME' => @options[:Host],
37
- 'SERVER_PORT' => @options[:Port].to_s
38
+ 'SERVER_PORT' => @options[:Port].to_s,
39
+ 'HTTP_VERSION' => @protocol,
40
+ 'REMOTE_ADDR' => @socket.addr.last
38
41
  }
39
42
 
40
43
  @headers.each do |k, v|
@@ -52,12 +55,12 @@ module Reifier
52
55
 
53
56
  private
54
57
 
55
- def handle_request_line(socket)
58
+ def handle_request_line
56
59
  # It is possible that gets returns nil
57
60
  # "Returns nil if called at end of file" see http://ruby-doc.org/core-2.3.0/IO.html#method-i-gets
58
- request_line = socket.gets
61
+ request_line = @socket.gets
59
62
  raise EOFError unless request_line
60
- raise HTTPParseError unless request_line.include?('HTTP')
63
+ raise HTTPParseError, "Received #{request_line.inspect}" unless request_line.include?('HTTP')
61
64
 
62
65
  request_line_array = request_line.split
63
66
 
@@ -69,10 +72,10 @@ module Reifier
69
72
  @request_uri = request_line_array[1]
70
73
  end
71
74
 
72
- def handle_headers(socket)
75
+ def handle_headers
73
76
  @headers = {}
74
77
 
75
- while (line = socket.gets)
78
+ while (line = @socket.gets)
76
79
  break if line == CRLF
77
80
  if line.include?('Host')
78
81
  @headers['HOST'] = line.gsub('Host: ', '').strip.chomp
@@ -84,8 +87,8 @@ module Reifier
84
87
  end
85
88
  end
86
89
 
87
- def handle_body(socket)
88
- @body = StringIO.new(socket.readpartial(@headers['CONTENT_LENGTH'].to_i))
90
+ def handle_body
91
+ @body = StringIO.new(@socket.readpartial(@headers['CONTENT_LENGTH'].to_i))
89
92
  end
90
93
 
91
94
  def request_with_body?
@@ -2,17 +2,18 @@ module Reifier
2
2
  class Response
3
3
  attr_accessor :status, :headers, :body, :protocol
4
4
 
5
- def initialize
5
+ def initialize(socket)
6
+ @socket = socket
6
7
  @response = ''
7
8
  end
8
9
 
9
- def handle(socket)
10
+ def handle
10
11
  handle_request_line
11
12
  handle_headers
12
13
  handle_body
13
14
 
14
- socket.write @response
15
- socket.close
15
+ @socket.write @response
16
+ @socket.close
16
17
  end
17
18
 
18
19
  def <<(rack_return)
@@ -14,7 +14,7 @@ module Reifier
14
14
  end
15
15
 
16
16
  Signal.trap 'SIGINT' do
17
- puts "Cleaning up #{child_pids.length} Workers"
17
+ puts "\n======= Cleaning up #{child_pids.length} Workers =======\n"
18
18
  child_pids.each do |cpid|
19
19
  begin
20
20
  Process.kill(:INT, cpid)
@@ -40,12 +40,31 @@ module Reifier
40
40
  end
41
41
  end
42
42
 
43
+ def load_configuration
44
+ if defined?(Rails)
45
+ path = Rails.root.join('config/reifier.rb')
46
+ else
47
+ path = Dir.pwd + '/reifier.rb'
48
+ end
49
+
50
+ return unless File.exist?(path)
51
+
52
+ lines = File.read(path).split("\n")
53
+
54
+ lines.each do |line|
55
+ option = line.split.first.capitalize
56
+ value = line.split.last
57
+
58
+ @options[option.to_sym] = value
59
+ end
60
+
61
+ puts "======= Loaded settings from #{path} =======\n"
62
+ end
63
+
43
64
  private
44
65
 
45
66
  def spawn_worker(server)
46
67
  fork do
47
- Thread.abort_on_exception = true
48
-
49
68
  pool = Concurrent::FixedThreadPool.new(@options[:Threads])
50
69
 
51
70
  loop do
@@ -54,36 +73,26 @@ module Reifier
54
73
 
55
74
  pool.post do
56
75
  begin
57
- request = Request.new(@options)
58
- response = Response.new
76
+ request = Request.new(socket, @options)
77
+ response = Response.new(socket)
59
78
 
60
- request.handle(socket)
79
+ request.handle
61
80
 
62
81
  response.protocol = request.protocol
63
82
  response << @app.call(request.rack_env)
64
83
 
65
- response.handle(socket)
66
-
67
- log_request request, response if development?
84
+ response.handle
68
85
  rescue Exception => e
69
- log "\nError: #{e.class}\nMessage: #{e.message}\n\nBacktrace:\n\t#{e.backtrace.join("\n\t")}" if development?
70
86
  socket.close
87
+
88
+ STDERR.puts ERROR_HEADER
89
+ STDERR.puts "#{e.class}: #{e}"
90
+ STDERR.puts e.backtrace
91
+ STDERR.puts ERROR_FOOTER
71
92
  end
72
93
  end
73
94
  end
74
95
  end
75
96
  end
76
-
77
- def development?
78
- @options[:environment] == 'development'
79
- end
80
-
81
- def log(message)
82
- puts "[#{Time.now}] #{message}"
83
- end
84
-
85
- def log_request(request, response)
86
- puts "[#{Time.now}] \"#{request.request_method} #{request.request_path} #{request.protocol}\" #{response.status}"
87
- end
88
97
  end
89
98
  end
@@ -1,3 +1,3 @@
1
1
  module Reifier
2
- VERSION = "0.3.0".freeze
2
+ VERSION = "0.4.0".freeze
3
3
  end
data/lib/reifier.rb CHANGED
@@ -80,4 +80,6 @@ module Reifier
80
80
  PUT = 'PUT'.freeze
81
81
 
82
82
  HTTPParseError = Class.new(StandardError)
83
+ ERROR_HEADER = '=============================== FATAL SERVER ERROR =============================='.freeze
84
+ ERROR_FOOTER = "=================================================================================\n\n\n".freeze
83
85
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benny Klotz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-02-16 00:00:00.000000000 Z
11
+ date: 2016-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -137,6 +137,7 @@ files:
137
137
  - Rakefile
138
138
  - bin/console
139
139
  - bin/setup
140
+ - examples/reifier.rb
140
141
  - lib/rack/handler/reifier.rb
141
142
  - lib/reifier.rb
142
143
  - lib/reifier/request.rb