5

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

  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.

How do I tell ActiveRecord to reuse a connection?

mrrusof
  • 362
  • 2
  • 8
  • 1
    Have a look at this answer http://stackoverflow.com/questions/10191531/activerecord-connection-warning-database-connections-will-not-be-closed-automa?rq=1 – Angie Rabelero Apr 18 '16 at 18:42
  • By looking at that answer, I eventually found that calling `ActiveRecord::Base.clear_active_connections!` works for me. I did try `ActiveRecord::Base.connection.close` and found that that way I close the connection instead of return the connection to the connection pool. I did not try the `config.ru` approach. – mrrusof Apr 19 '16 at 03:14

1 Answers1

1

One way of cleaning connections is to call ActiveRecord::Base.clear_active_connections! after each use of Subscriber.find_by_email and Subscriber.create, like so.

after do
    ActiveRecord::Base.clear_active_connections!
end

Somewhere else, some people suggest using middleware ActiveRecord::ConnectionAdapters::ConnectionManagement. That does not work in Thin because 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.

EDIT:

I made an explanation of why using middleware ActiveRecord::Connectionadapters::ConnectionManagement won't work with Thin in threaded mode, which you can find here.

2016.05.18 EDIT:

I followed up this issue with Thin author and this issue is not resolved after issue 307.

Community
  • 1
  • 1
mrrusof
  • 362
  • 2
  • 8