-
-
Notifications
You must be signed in to change notification settings - Fork 358
Description
I was playing around with Sinatra and ActiveRecord when I found that a connections are not reused automatically by this simple API.
#!/usr/bin/env ruby
require 'sinatra'
require 'active_record'
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3',
database: 'newsletter.db'
)
ActiveRecord::Schema.define do
create_table :subscribers do |t|
t.string :email
t.timestamps
end
end
class Subscriber < ActiveRecord::Base
validates :email, presence: true
end
class Newsletter < Sinatra::Base
set :server, :thin
use ActiveRecord::ConnectionAdapters::ConnectionManagement
get '/subscribers/:email' do
s = Subscriber.find_by_email(params[:email])
if s == nil
status 404
else
content_type 'application/json'
s.to_json
end
end
post '/subscribers/:email' do
Subscriber.create(email: params[:email])
end
end
Newsletter.run!
The API returns either a subscriber or a 404 the first 5 times I GET a subscriber. The 6th time I get a timeout. After each of the first 5 GETs, there is one more read+write file descriptor open for newsletter.db. I would expect there to be only one all the time.
The reason for the timeout is that Thin starts processing each request in a thread and finishes processing the request in another thread. ConnectionManagement
only returns to the pool those connections that are active for the current thread and Thin applies ConnectionManagement
in the second thread instead of the first.
Is it responsibility of Thin to process each request in a single thread or is it responsibility of ConnectionManagement
to close active connections for a given thread instead of the current thread?