New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sinatra + Thin + ActiveRecord ConnectionManagement do not work #62

Closed
mrrusof opened this Issue Apr 20, 2016 · 3 comments

Comments

Projects
None yet
1 participant
@mrrusof
Copy link

mrrusof commented Apr 20, 2016

Consider the following example Sinatra 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.

Do you think it makes sense to provide the following version of ConnectionManagement in gem sinatra-activerecord?

class ConnectionManagement
  def initialize(app)
    @app = app
  end

  def call(env)
    testing = env['rack.test']
    response = @app.call(env)
    ActiveRecord::Base.clear_active_connections! unless testing
    response
  rescue Exception
    ActiveRecord::Base.clear_active_connections! unless testing
    raise
  end
end
@mrrusof

This comment has been minimized.

Copy link
Author

mrrusof commented Apr 20, 2016

Corresponding issue in Thin: macournoyer/thin#307

@mrrusof

This comment has been minimized.

Copy link
Author

mrrusof commented Jul 26, 2016

Resolved by in corresponding issue in Thin.

@mrrusof mrrusof closed this Jul 26, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment