active record stand alone: connection pooling - ruby

Using activerecord outside rails, may I be confident all the connection drudgework is performed behind the curtains the same as inside rails?
In rails, activerecord does a great job establishing a connection pool and activating or closing connection as needed.
If I have a ruby daemon which calls a class file with:
ActiveRecord::Base.establish_connection(:production)
# more active_record tasks
can I assume on the following calls a connection from a pool is used?

Yup, calling ActiveRecord::Base.establish_connection will create a connection pool according to: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#L842

Related

How to configure puma to establish rom-rb database connection?

If I were using ActiveRecord, my puma config would establish the database connection as described in Heroku's guide Deploying Rails Applications with the Puma Web Server.
on_worker_boot do
ActiveRecord::Base.establish_connection
end
However, I am using ROM (Ruby Object Mapper).
I tried omitting the on_worker_boot block, but (predictably) the database connection is either not established, or is not established correctly, and the following error is raised.
PG::ConnectionBad: PQconsumeInput() SSL error: decryption failed or bad record mac
I've read the ROM Setup Guide but did not see anything relevant.
How do I establish the ROM connection in puma?
The solution seems to be to disconnect the gateway connection.
on_worker_boot do
ROM.env.gateways[:default].connection.disconnect
end

Ruby Mongo Driver 2.0.0 connection status

Read the docs, searched the stack, but I can't find a very simple
function: How do I check if the connection has been established or not?
establishing DB connection with
db = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'test')
From time to time I forget to launch the mongodb database and then the driver tries to connect and well... does not say's a lot about the connection itself.
Is there some kind of .isConnected? method or anything to find
the connection status of current Mongo::Client instance?
Thanks in advance
Version 1.x of the Mongo ruby driver did expose a connected? method on Mongo::Connection, but it's been moved in v2 to live on Mongo::Server, however its meaning has changed somewhat.
Here's an example of using this method:
mongo = Mongo::Client.new('mongodb://localhost/mycollection')
#=> #<Mongo::Client:0x70279909414900 cluster=localhost:27017>
mongo.cluster.servers.first.connected?
#=> true
In v2 of the Mongo ruby driver, it will raise an exception when trying to use an invalid connection, for example, Mongo::Error::NoServerAvailable, based on the connection parameters about timeouts. For your purposes of simply checking whether the connection has been established, maybe something like:
mongo = Mongo::Client.new('mongodb://localhost/mycollection')
mongo.list_databases => # raise error or return an array

Heroku PostgreSQL database connection pooling in Ruby for Rack with Puma

UPDATE: I tried changing the storage of the PostgreSQL connection object from a constant POSTGRES to a class variable ##pg. That didn't fix the issue. Then, I tried changing it to a global variable $pg. That seems to have worked! I still would like to eventually implement database connection pooling, however, so that I can have a pool of up to 5 (or so) database connections handling requests instead of just one global connection for all requests. END UPDATE
I'm hosting the Acani Chats REST Server on Heroku.
The first request works OK, but subsequent requests fail to connect to the PostgreSQL database.
I get the following errors:
Rack app error: #<PG::UnableToSend: SSL error: decryption failed or bad record mac>
Rack app error: #<PG::UnableToSend: no connection to the server>
What's going on?
In /config/application.rb, I define the constant POSTGRES to be the PostgreSQL connection object.
Should I be using a global or class variable instead of a constant to hold onto the connection instance?
In /config/routes.rb, I define the Rack call method.
I want to learn how to implement database connection pooling in Ruby for Rack with Puma and PostgreSQL.
Puma is threaded so you need a thread safe pool of connections to PostgreSQL, otherwise concurrent requests will all use the same connection concurrently, which is unexpected.
Please have a look to the connection_pool gem. It should help.

Long-running Redshift transaction from Ruby

I run several sql statements in a transaction using Ruby pg gem. The problem that I bumped in is that connection times out on these queries due to firewall setup. Solution proposed here does not work, because it requires jdbc connections string, and I'm in Ruby (jRuby is not an option). Moving driver program to AWS to remove firewall is not an option either.
The code that I have is along the following lines:
conn = RedshiftHelper.get_redshift_connection
begin
conn.transaction do
# run my queries
end
ensure
conn.flush
conn.finish
end
I'm now looking into PG asynchronous API. I'm wondering if I can use is_busy to prevent firewall from timing out, or something to that effect. I can't find good documentation on the topic though. Appreciate any hints on that.
PS: I have solved this problem for a single query - I can trigger it asynchronously and track its completion using system STV_INFLIGHT Redshift table.Transaction does not work this way as I have to keep connection open.
Ok, I nailed it down. Here are the facts:
Redshift is based on Postgres 8.0. To check that, connect to Redshift instance using psql and see that it says "server version 8.0"
Keepalive requests are specified on the level of tcp socket (link).
Postgres 8.0 does not support keepalive option when specifying a connection string (link to 9.0 release changes, section E.19.3.9.1 on libpq)
PG gem in Ruby is a wrapper about libpq
Based on the facts above, tcp keepalive is not supported by Redshift. However, PG allows you to retrieve a socket that is used in the established connection. This means that even though libpq does not set keepalive feature, we still can use it manually. The solution thus:
class Connection
attr_accessor :socket, :pg_connection
def initialize(conn, socket)
#socket = socket
#pg_connection = conn
end
def method_missing(m, *args, &block)
#pg_connection.send(m, *args, &block)
end
def close
#socket.close
#pg_connection.close
end
def finish
#socket.close
#pg_connection.close
end
end
def get_connection
conn = PGconn.open(...)
socket_descriptor = conn.socket
socket = Socket.for_fd(socket_descriptor)
# Use TCP keep-alive feature
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
# Maximum keep-alive probes before asuming the connection is lost
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPCNT, 5)
# Interval (in seconds) between keep-alive probes
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPINTVL, 2)
# Maximum idle time (in seconds) before start sending keep-alive probes
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPIDLE, 2)
socket.autoclose = true
return Connection.new(conn, socket)
end
The reason why I introduce a proxy Connection class is because of Ruby tendency to garbage-collect IO objects (like sockets) when they get out of scope. This means that we now need connection and socket to be in the same scope, which is achieved through this proxy class. My Ruby knowledge is not deep, so there may be a better way to handle the socket object.
This approach works, but I would be happy to learn if there are better/cleaner solutions.
The link you provided has the answer. I think you just want to follow the section at the top, which has settings for 3 different OS'es, pick the one you are running the code on (the client to the Amazon service).
Look in this section: To change TCP/IP timeout settings - this is the OS that your code is running on (i.e. The client for the Amazon Service is your Server probably)
Linux — If your client is running on Linux, run the following command as the root user.
-- details omitted --
Windows — If your client runs on Windows, edit the values for the following registry settings under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters:
-- details omitted --
Mac — If your client is a Mac, create or modify the /etc/sysctl.conf file with the following values:
-- Details omitted --

ActiveRecord connection pooling

I have multiple database connection in my Sinatra Application. It should switch the database intelligently according to the params.
For example:
get '/:project/details' do
...
end
It should connect to the database 'project1' if the url is 0.0.0.0:3000/project1/details, 'project2' if the url is 0.0.0.0:3000/project2/details, and so on.
I am using active_record for database connection.
I want to keep the connection in a pool, so that I can use the same connection if more than one hit to the same project. And shift the connection in the pool according to the project with out establishing a new connection for each each and every hit.
How to implement this?

Resources