mongrel2 0.52.1 → 0.52.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,13 @@
1
+ == v0.52.2 [2019-04-24] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Bugfixes:
4
+
5
+ - Don't set linger on the Connection sockets until they're closing
6
+ - Defer creation of the reactor in the handler until it's #run
7
+ - Add #extended_reply? predicate to Mongrel2::Request for cases where
8
+ it's used as a response too
9
+
10
+
1
11
  == v0.52.1 [2018-07-23] Michael Granger <ged@FaerieMUD.org>
2
12
 
3
13
  Bugfixes:
@@ -22,10 +22,10 @@ module Mongrel2
22
22
  abort "\n\n>>> Mongrel2 requires Ruby 2.2 or later. <<<\n\n" if RUBY_VERSION < '2.2.0'
23
23
 
24
24
  # Library version constant
25
- VERSION = '0.52.1'
25
+ VERSION = '0.52.2'
26
26
 
27
27
  # Version-control revision constant
28
- REVISION = %q$Revision: 476c62e8a8f0 $
28
+ REVISION = %q$Revision$
29
29
 
30
30
 
31
31
  require 'mongrel2/constants'
@@ -68,12 +68,10 @@ class Mongrel2::Connection
68
68
  def connect
69
69
  self.log.info "Connecting PULL request socket (%s)" % [ self.sub_addr ]
70
70
  @request_sock = CZTop::Socket::PULL.new
71
- @request_sock.options.linger = 0
72
71
  @request_sock.connect( self.sub_addr )
73
72
 
74
73
  self.log.info "Connecting PUB response socket (%s)" % [ self.pub_addr ]
75
74
  @response_sock = CZTop::Socket::PUB.new
76
- @response_sock.options.linger = 0
77
75
  @response_sock.connect( self.pub_addr )
78
76
  end
79
77
 
@@ -197,8 +195,14 @@ class Mongrel2::Connection
197
195
  def close
198
196
  return if self.closed?
199
197
  self.closed = true
200
- @request_sock.close if @request_sock
201
- @response_sock.close if @response_sock
198
+ if @request_sock
199
+ @request_sock.options.linger = 0
200
+ @request_sock.close
201
+ end
202
+ if @response_sock
203
+ @response_sock.options.linger = 0
204
+ @response_sock.close
205
+ end
202
206
  end
203
207
 
204
208
 
@@ -141,10 +141,10 @@ class Mongrel2::Handler
141
141
  def initialize( app_id, send_spec, recv_spec ) # :notnew:
142
142
  super() # To the signal handler mixin
143
143
 
144
- @app_id = app_id
144
+ @app_id = app_id
145
145
 
146
- @conn = Mongrel2::Connection.new( app_id, send_spec, recv_spec )
147
- @reactor = CZTop::Reactor.new
146
+ @conn = Mongrel2::Connection.new( app_id, send_spec, recv_spec )
147
+ @reactor = nil
148
148
  end
149
149
 
150
150
 
@@ -162,13 +162,14 @@ class Mongrel2::Handler
162
162
 
163
163
  ##
164
164
  # The CZTop::Reactor that manages IO
165
- attr_reader :reactor
165
+ attr_accessor :reactor
166
166
 
167
167
 
168
168
  ### Run the handler.
169
169
  def run
170
170
  self.log.info "Starting up %p" % [ self ]
171
171
 
172
+ self.reactor = CZTop::Reactor.new
172
173
  self.reactor.register( @conn.request_sock, :read, &self.method(:on_socket_event) )
173
174
  self.with_signal_handler( self.reactor, *QUEUE_SIGS ) do
174
175
  self.start_accepting_requests
@@ -232,6 +233,8 @@ class Mongrel2::Handler
232
233
  ### Restart the handler. You should override this if you want to re-establish
233
234
  ### database connections, flush caches, or other restart-ey stuff.
234
235
  def restart
236
+ raise "can't restart: not running" unless self.reactor
237
+
235
238
  self.log.info "Restarting"
236
239
  if (( old_conn = @conn ))
237
240
  self.reactor.unregister( old_conn.request_sock )
@@ -248,6 +248,12 @@ class Mongrel2::Request
248
248
  end
249
249
 
250
250
 
251
+ ### Indicate that a request is never an extended reply.
252
+ def extended_reply?
253
+ return false
254
+ end
255
+
256
+
251
257
  #
252
258
  # :section: Introspection Methods
253
259
  #
@@ -26,42 +26,49 @@ describe Mongrel2::Config::Directory, :db do
26
26
  expect( @dir ).to be_valid()
27
27
  end
28
28
 
29
+
29
30
  it "isn't valid if it doesn't have a base" do
30
31
  @dir.base = nil
31
32
  expect( @dir ).to_not be_valid()
32
33
  expect( @dir.errors.full_messages.first ).to match( /missing or nil/i )
33
34
  end
34
35
 
36
+
35
37
  it "isn't valid when its base starts with '/'" do
36
38
  @dir.base = '/var/www/public/'
37
39
  expect( @dir ).to_not be_valid()
38
40
  expect( @dir.errors.full_messages.first ).to match( %r{shouldn't start with '/'}i )
39
41
  end
40
42
 
43
+
41
44
  it "isn't valid when its base doesn't end with '/'" do
42
45
  @dir.base = 'var/www/public'
43
46
  expect( @dir ).to_not be_valid()
44
47
  expect( @dir.errors.full_messages.first ).to match( %r{must end with '/'}i )
45
48
  end
46
49
 
50
+
47
51
  it "isn't valid if it doesn't have an index file" do
48
52
  @dir.index_file = nil
49
53
  expect( @dir ).to_not be_valid()
50
54
  expect( @dir.errors.full_messages.first ).to match( /must not be nil/i )
51
55
  end
52
56
 
57
+
53
58
  it "isn't valid if it doesn't have a default content-type" do
54
59
  @dir.default_ctype = nil
55
60
  expect( @dir ).to_not be_valid()
56
61
  expect( @dir.errors.full_messages.first ).to match( /must not be nil/i )
57
62
  end
58
63
 
64
+
59
65
  it "isn't valid if its cache TTL is set to a negative value" do
60
66
  @dir.cache_ttl = -5
61
67
  expect( @dir ).to_not be_valid()
62
68
  expect( @dir.errors.full_messages.first ).to match( /not a positive integer/i )
63
69
  end
64
70
 
71
+
65
72
  it "is valid if its cache TTL is set to zero" do
66
73
  @dir.cache_ttl = 0
67
74
  expect( @dir ).to be_valid()
@@ -17,6 +17,7 @@ describe Mongrel2::Config::DSL, :db do
17
17
 
18
18
 
19
19
  describe 'servers' do
20
+
20
21
  it "can generate a default server config using the 'server' declarative" do
21
22
  result = server '965A7196-99BC-46FA-945B-3478AE92BFB5'
22
23
 
@@ -42,6 +43,7 @@ describe Mongrel2::Config::DSL, :db do
42
43
  expect( result.error_log ).to eq( '/var/log/errors' )
43
44
  expect( result.control_port ).to eq( '/var/run/intranet.sock' )
44
45
  end
46
+
45
47
  end
46
48
 
47
49
  describe 'hosts' do
@@ -61,6 +63,7 @@ describe Mongrel2::Config::DSL, :db do
61
63
  expect( host.name ).to eq( 'localhost' )
62
64
  end
63
65
 
66
+
64
67
  it "can add several elaborately-configured hosts to a server via a block" do
65
68
  result = server '965A7196-99BC-46FA-945B-3478AE92BFB5' do
66
69
 
@@ -138,9 +141,9 @@ describe Mongrel2::Config::DSL, :db do
138
141
  expect( host2.routes.first ).to be_a( Mongrel2::Config::Route )
139
142
  end
140
143
 
141
-
142
144
  end
143
145
 
146
+
144
147
  describe 'settings' do
145
148
 
146
149
  before( :all ) do
@@ -151,6 +154,7 @@ describe Mongrel2::Config::DSL, :db do
151
154
  Mongrel2::Config::Setting.dataset.exclude( :id => @ids ).delete
152
155
  end
153
156
 
157
+
154
158
  it "can set the expert tweakable settings en masse" do
155
159
  result = settings(
156
160
  "zeromq.threads" => 8,
@@ -169,6 +173,7 @@ describe Mongrel2::Config::DSL, :db do
169
173
  expect( result[2].value ).to eq( '0666' )
170
174
  end
171
175
 
176
+
172
177
  it "can set a single expert setting" do
173
178
  result = setting "zeromq.threads", 16
174
179
  expect( result ).to be_a( Mongrel2::Config::Setting )
@@ -195,6 +200,7 @@ describe Mongrel2::Config::DSL, :db do
195
200
  expect( result[1].mimetype ).to eq( 'text/x-textile' )
196
201
  end
197
202
 
203
+
198
204
  it "can set a single mimetype mapping" do
199
205
  result = mimetype '.tmpl', 'text/x-inversion-template'
200
206
  expect( result ).to be_a( Mongrel2::Config::Mimetype )
@@ -204,6 +210,7 @@ describe Mongrel2::Config::DSL, :db do
204
210
 
205
211
  end
206
212
 
213
+
207
214
  describe 'filters' do
208
215
 
209
216
  it "can add a filter to a server" do
@@ -216,6 +223,7 @@ describe Mongrel2::Config::DSL, :db do
216
223
  expect( result.filters.first.settings ).to eq( {} )
217
224
  end
218
225
 
226
+
219
227
  it "can add a filter with settings to a server" do
220
228
  result = server '965A7196-99BC-46FA-945B-3478AE92BFB5' do
221
229
  filter '/usr/lib/mongrel2/null.so',
@@ -231,6 +239,7 @@ describe Mongrel2::Config::DSL, :db do
231
239
 
232
240
  end
233
241
 
242
+
234
243
  describe 'xrequests' do
235
244
 
236
245
  it "can add an xrequest to a server" do
@@ -243,6 +252,7 @@ describe Mongrel2::Config::DSL, :db do
243
252
  expect( result.xrequests.first.settings ).to eq( {} )
244
253
  end
245
254
 
255
+
246
256
  it "can add a filter with settings to a server" do
247
257
  result = server '965A7196-99BC-46FA-945B-3478AE92BFB5' do
248
258
  xrequest '/usr/lib/mongrel2/null.so',
@@ -24,7 +24,6 @@ describe Mongrel2::Config::Handler, :db do
24
24
  end
25
25
 
26
26
 
27
-
28
27
  it "is valid if its specs and identities are all valid" do
29
28
  expect( @handler ).to be_valid()
30
29
  end
@@ -36,6 +35,7 @@ describe Mongrel2::Config::Handler, :db do
36
35
  expect( @handler.errors.full_messages.first ).to match( /must not be nil/i )
37
36
  end
38
37
 
38
+
39
39
  it "isn't valid if it doesn't have a recv_spec" do
40
40
  @handler.recv_spec = nil
41
41
  expect( @handler ).to_not be_valid()
@@ -49,6 +49,7 @@ describe Mongrel2::Config::Handler, :db do
49
49
  expect( @handler.errors.full_messages.first ).to match( /not a uri/i )
50
50
  end
51
51
 
52
+
52
53
  it "isn't valid if it doesn't have a valid URL in its recv_spec" do
53
54
  @handler.recv_spec = 'smoke signals'
54
55
  expect( @handler ).to_not be_valid()
@@ -62,6 +63,7 @@ describe Mongrel2::Config::Handler, :db do
62
63
  expect( @handler.errors.full_messages.first ).to match( /invalid 0mq transport/i )
63
64
  end
64
65
 
66
+
65
67
  it "isn't valid if has an unsupported transport in its recv_spec" do
66
68
  @handler.recv_spec = 'inproc://application'
67
69
  expect( @handler ).to_not be_valid()
@@ -75,6 +77,7 @@ describe Mongrel2::Config::Handler, :db do
75
77
  expect( @handler.errors.full_messages.first ).to match( /invalid sender identity/i )
76
78
  end
77
79
 
80
+
78
81
  it "*is* valid if it doesn't have a recv_ident" do
79
82
  @handler.recv_ident = nil
80
83
  expect( @handler ).to be_valid()
@@ -86,17 +89,20 @@ describe Mongrel2::Config::Handler, :db do
86
89
  expect( @handler ).to be_valid()
87
90
  end
88
91
 
92
+
89
93
  it "is valid if it has 'tnetstring' set as the protocol" do
90
94
  @handler.protocol = 'tnetstring'
91
95
  expect( @handler ).to be_valid()
92
96
  end
93
97
 
98
+
94
99
  it "isn't valid if it has an invalid protocol" do
95
100
  @handler.protocol = 'morsecode'
96
101
  expect( @handler ).to_not be_valid()
97
102
  expect( @handler.errors.full_messages.first ).to match( /invalid/i )
98
103
  end
99
104
 
105
+
100
106
  it "isn't valid if its send_spec isn't unique" do
101
107
  dup = @handler.dup
102
108
  @handler.save
@@ -29,6 +29,7 @@ describe Mongrel2::Config::Log, :db do
29
29
  expect( log.how ).to eq( how )
30
30
  end
31
31
 
32
+
32
33
  it "has reasonable defaults for 'where' and 'how'" do
33
34
  what = 'load etc/mongrel2.conf'
34
35
  why = 'updating'
@@ -39,6 +40,7 @@ describe Mongrel2::Config::Log, :db do
39
40
  expect( log.how ).to eq( File.basename( $0 ) )
40
41
  end
41
42
 
43
+
42
44
  describe "an entry" do
43
45
 
44
46
  before( :each ) do
@@ -66,6 +68,7 @@ describe Mongrel2::Config::Log, :db do
66
68
  }x)
67
69
  end
68
70
 
71
+
69
72
  it "stringifies with a reason if it has one" do
70
73
  @log.why = 'Because'
71
74
 
@@ -30,6 +30,7 @@ describe Mongrel2::Config::Route, :db do
30
30
  expect( @route.target ).to eq( dir )
31
31
  end
32
32
 
33
+
33
34
  it "returns a Mongrel2::Config::Proxy if its target_type is 'proxy'" do
34
35
  proxy = Mongrel2::Config::Proxy.create( :addr => '10.2.18.8' )
35
36
 
@@ -39,6 +40,7 @@ describe Mongrel2::Config::Route, :db do
39
40
  expect( @route.target ).to eq( proxy )
40
41
  end
41
42
 
43
+
42
44
  it "returns a Mongrel2::Config::Handler if its target_type is 'handler'" do
43
45
  handler = Mongrel2::Config::Handler.create(
44
46
  :send_ident => TEST_UUID,
@@ -51,6 +53,7 @@ describe Mongrel2::Config::Route, :db do
51
53
  expect( @route.target ).to eq( handler )
52
54
  end
53
55
 
56
+
54
57
  it "raises an exception if its target_type is set to something invalid" do
55
58
  @route.target_type = 'giraffes'
56
59
 
@@ -30,30 +30,35 @@ describe Mongrel2::Config::Server, :db do
30
30
  expect( @server ).to be_valid()
31
31
  end
32
32
 
33
+
33
34
  it "isn't valid if it doesn't have an access_log path" do
34
35
  @server.access_log = nil
35
36
  expect( @server ).to_not be_valid()
36
37
  expect( @server.errors.full_messages.first ).to match( /missing or nil/i )
37
38
  end
38
39
 
40
+
39
41
  it "isn't valid if it doesn't have an error_log path" do
40
42
  @server.error_log = nil
41
43
  expect( @server ).to_not be_valid()
42
44
  expect( @server.errors.full_messages.first ).to match( /missing or nil/i )
43
45
  end
44
46
 
47
+
45
48
  it "isn't valid if it doesn't have an pid_file path" do
46
49
  @server.pid_file = nil
47
50
  expect( @server ).to_not be_valid()
48
51
  expect( @server.errors.full_messages.first ).to match( /missing or nil/i )
49
52
  end
50
53
 
54
+
51
55
  it "isn't valid if it doesn't have a default_host" do
52
56
  @server.default_host = nil
53
57
  expect( @server ).to_not be_valid()
54
58
  expect( @server.errors.full_messages.first ).to match( /missing or nil/i )
55
59
  end
56
60
 
61
+
57
62
  it "isn't valid if it doesn't specify a port" do
58
63
  @server.port = nil
59
64
  expect( @server ).to_not be_valid()
@@ -68,6 +73,7 @@ describe Mongrel2::Config::Server, :db do
68
73
  expect( @server.control_socket_uri ).to eq( 'ipc:///usr/local/www/run/control' )
69
74
  end
70
75
 
76
+
71
77
  it "knows where its control socket is if there is a setting for control_port" do
72
78
  Mongrel2::Config::Setting.dataset.truncate
73
79
  allow( FileTest ).to receive( :socket? ).with( '/usr/local/www/var/run/control.sock' ).
@@ -76,12 +82,14 @@ describe Mongrel2::Config::Server, :db do
76
82
  expect( @server.control_socket_uri ).to eq( 'ipc:///usr/local/www/var/run/control.sock' )
77
83
  end
78
84
 
85
+
79
86
  it "raises an error if the control socket path doesn't point to a UNIX socket" do
80
87
  expect {
81
88
  @server.control_socket
82
89
  }.to raise_error( RuntimeError, /unable to find the socket/i )
83
90
  end
84
91
 
92
+
85
93
  it "can create a Mongrel2::Control for its control port" do
86
94
  Mongrel2::Config::Setting.dataset.truncate
87
95
  allow( FileTest ).to receive( :socket? ).with( '/usr/local/www/run/control' ).
@@ -91,12 +99,14 @@ describe Mongrel2::Config::Server, :db do
91
99
  sock.close
92
100
  end
93
101
 
102
+
94
103
  it "knows what the Pathname of its PID file is" do
95
104
  pidfile = @server.pid_file_path
96
105
  expect( pidfile ).to be_a( Pathname )
97
106
  expect( pidfile.to_s ).to eq( '/run/mongrel2.pid' )
98
107
  end
99
108
 
109
+
100
110
  it "has a predicate that understands the use_ssl value" do
101
111
  expect( @server.use_ssl ).to be_falsey()
102
112
  @server.use_ssl = true
@@ -38,12 +38,14 @@ describe Mongrel2::Config do
38
38
  end
39
39
  end
40
40
 
41
+
41
42
  it "can reset the database handle for the config classes" do
42
43
  db = Mongrel2::Config.in_memory_db
43
44
  Mongrel2::Config.db = db
44
45
  expect( Mongrel2::Config::Directory.db ).to equal( db )
45
46
  end
46
47
 
48
+
47
49
  it "has a convenience method for fetching an Array of all of its configured servers" do
48
50
  Mongrel2::Config.init_database
49
51
  Mongrel2::Config::Server.truncate
@@ -60,6 +62,7 @@ describe Mongrel2::Config do
60
62
  expect( Mongrel2::Config.servers.first.uuid ).to eq( TEST_UUID )
61
63
  end
62
64
 
65
+
63
66
  it "has a convenience method for getting a setting's value" do
64
67
  Mongrel2::Config.init_database
65
68
  Mongrel2::Config::Setting.dataset.truncate
@@ -69,10 +72,12 @@ describe Mongrel2::Config do
69
72
  expect( Mongrel2::Config.settings[ :control_port ] ).to eq( 'ipc://var/run/control.sock' )
70
73
  end
71
74
 
75
+
72
76
  it "can read the configuration schema from a data file" do
73
77
  expect( Mongrel2::Config.load_config_schema ).to match( /create table server/i )
74
78
  end
75
79
 
80
+
76
81
  it "knows whether or not its database has been initialized" do
77
82
  Mongrel2::Config.db = Mongrel2::Config.in_memory_db
78
83
  expect( Mongrel2::Config.database_initialized? ).to be_falsey()
@@ -80,6 +85,7 @@ describe Mongrel2::Config do
80
85
  expect( Mongrel2::Config.database_initialized? ).to be_truthy()
81
86
  end
82
87
 
88
+
83
89
  it "doesn't re-initialize the database if the non-bang version of init_database is used" do
84
90
  Mongrel2::Config.db = Mongrel2::Config.in_memory_db
85
91
  Mongrel2::Config.init_database
@@ -88,22 +94,26 @@ describe Mongrel2::Config do
88
94
  Mongrel2::Config.init_database
89
95
  end
90
96
 
97
+
91
98
  it "can return the path to the config DB as a Pathname if it's pointing at a file" do
92
99
  Mongrel2::Config.db = Sequel.
93
100
  connect( adapter: Mongrel2::Config.sqlite_adapter, database: 'config-spec.sqlite' )
94
101
  expect( Mongrel2::Config.dbname ).to eq( 'config-spec.sqlite' )
95
102
  end
96
103
 
104
+
97
105
  it "returns nil if asked for the pathname to an in-memory database" do
98
106
  Mongrel2::Config.db = Mongrel2::Config.in_memory_db
99
107
  expect( Mongrel2::Config.dbname ).to be_nil()
100
108
  end
101
109
 
110
+
102
111
  describe "Configurability support", :if => defined?( Configurability ) do
103
112
  require 'configurability/behavior'
104
113
 
105
114
  it_should_behave_like "an object with Configurability"
106
115
 
116
+
107
117
  it "uses the 'mongrel2' config section" do
108
118
  expect( Mongrel2::Config.config_key ).to eq( :mongrel2 )
109
119
  end