Managine ActiveRecord connection pools - ruby-on-rails

I have an extremely unusual case where I need to connect to a sqlite database using an anonymous class. This class in created on every request, and then connects to a database using ActiveRecord's establish_connection. My issue is that every time establish_connection is called, ActiveRecord creates a new connection pool to track the connections made through the class. Since these are one time use classes, this is actually a memory leak and the number of connection pools tracked by ActiveRecord grows with each request. One way to solve this is to call
model_copy = Class.new Model { ... }
model_copy.establish_connection ...
# Do work
model_copy.connection.disconnect!
model_copy.connection_handler.remove_connection model_copy
I would like to do this without the explicit disconnect! and remove_connection calls because it is annoying and very prone to errors and memory leaks. Does anyone have any guidance here?
Thanks!

Assuming the # Do work part is the only part that changes, this looks like a classic use case for a method that takes a block:
def hit_the_db
model_copy = Class.new Model { ... }
model_copy.establish_connection ...
yield
model_copy.connection.disconnect!
model_copy.connection_handler.remove_connection model_copy
end
...
hit_the_db { block of code that does work }

Related

Rails class method is thread safe?

I have this method in a class:
class User < ApplicationRecord
...
def answers
#answers ||= HTTParty.get("http://www.example.com/api/users/#{self.id}/answers.json")
end
...
end
Since I'm using Puma as a web server I'm wondering if this code is thread safe? can someone confirm it and if possible explain why this is thread safe?
This in an instance method, not to be confused with a class method. The answers method is on an instance of User, as opposed to being on the User class itself. This method is caching the answers on the instance of a User, but as long as this User instance is being instantiated with each web request (such as a User.find()or User.find_by()), you’re fine because the instance is not living between threads. It’s common practice to look records up every web request in the controller, so you’re likely doing that.
If this method was on the User class directly (such as User.answers), then you’d need to evaluate whether it’s safe for that cached value to be maintained across threads and web requests.
To recap, the your only concern for thread safety is class methods, class variables (instance variables that use two at signs such as ##answers), and instance methods where the instance lives on past a single web request.
If you ever find yourself needing to use a class-level variable safely, you can use Thread.current, which is essentially a per-thread Hash (like {}) that you can store values in. For example Thread.current[:foo] = 1 would be an example. ActiveSupport uses this when setting Time.zone.
Alternatively you may find times where you need a single array that you need to safely share across threads, in which case you’d need to look into Mutex, which basically lets you have an array that you lock and unlock to give threads safe access to reading and writing in it. The Sidekiq gem uses a Mutex to manage workers, for example. You lock the Mutex, so that no one else can change it, then you write to it, and then unlock it. It’s important to note that if any other thread wants to write to the Mutex while it’s locked, it’ll have to wait for it to become unlocked (like, the thread just pauses while the other thread writes), so it’s important to lock as short as possible.

Thread safe counter inside a method

I saw some retry code written like this, it tries to call a service 3 times if some exception is raised, Im trying to understand in a non-MRI multi-threaded server, is this counter thread safe? is it necessary to lock the process using Mutex?
This is how its been called
MyClass.new.my_method
class MyClass
def my_method
counter = 3
begin
call_some_service_raise_some_exception
rescue SomeException => e
retry if counter.positive?
end
end
end
Assuming the variable counter is scoped to that method only, and that there is no funny shenanigans going on with Singleton or any other weird stuff, then yes, that method should be thread safe in its current form.
If, however, counter is an instance variable and you are using an accessor to set it, then that method is not thread safe. You may never encounter the race condition if you're using every MyClass once only, but all it takes is one well-meaning refactoring to reuse MyClass and suddenly you've got a race condition there.
Basically - if your method is self-contained, uses variables scoped to it only, and references no external shared data then it is thread safe by default.
As soon as you use something that could be accessed at the same time by another thread, you have a potential race condition in the making and you should start thinking about synchronising access to the shared resources.

Does groovy.sql.Sql.firstRow Closes Connection After Execution?

In MyService I have the following:
import groovy.sql.Sql
class MyService {
Sql groovySql
def serviceMethod(){
groovySql.firstRow("some query.....")
}
}
In resources.groovy groovySql inject as follows:
groovySql(groovy.sql.Sql, ref('dataSource'))
This is a Grails 2.4.5 application. Now, the question is when serviceMethod is called, is the connection closed automatically?
Every method in Sql creates and releases resources if necessary.
Under the covers the facade hides away details associated with getting
connections, constructing and configuring statements, interacting with
the connection, closing resources and logging errors.
If you create a Sql with a DataSource, it will get a new connection every time, and close it at the end of the operation.
If we are using a DataSource and we haven't enabled statement caching,
then strictly speaking the final close() method isn't required - as
all connection handling is performed transparently on our behalf;
however, it doesn't hurt to have it there as it will return silently
in that case.

Redis vs Class variables in Rails

Im using Sidekiq, Redis, Websocket-rails inside of Rails. With sidekiq having server-side Class. Now, when adding more functionality, i cant anymore use instance variables inside my Sidekiq Class's methods, i need to share information between methods. Sidekiq class also inherits from Websocket class, to be available websockets.
Right now, i have 2000/per second data change for objects. Using 95% instance variables, 5% pushing/getting from Redis, to make lower I/O.
Im considering, using class variables or making all 100% on Redis. Im not sure about or it wont overload my background jobs with that big data transfer count, which goes bigger with every new client. I'm using heroku free Dyno, dont want to buy better server yet. But using class variables would be less I/O, and probably unsafe, becouse it inherits from Websocket-rails? Im doing this project partly to show something to employers, that i can program, to get my 1-st IT job. I care how they react to those class variables. What employers would say about class variables? And which one to choose?
You can absolutely use instance variables in your Sidekiq worker. You cannot use class or class-instance variables.
class MyWorker
include Sidekiq::Worker
def perform(a, b)
#a = a # instance variable, no problem!
##a = a # class variable, big problem!
self.set_a(a)
end
def self.set_a(a)
#a = a # class instance variable, big problem!
end
end
Class variables have their places, if they represent a concept that is unchangeable and should live as a definition of something, like a configuration throughout the application, or some fundamental multiplier of a part of the application domain/business.
But, just because things are unchanging, that doesn't mean they have to be a class variable. You can have an instance of a class to be always setup with the same values, and then share the instance. Kind of like a singleton, but not necessarily being a singleton, just being a widely shared variable that is part of the input on the start of a given process.
So instead of using Sidekiq to store data for this unchanging thing, and rather than using class variables, you can achieve a cleaner design by doing something like
class ImportantThing
def initialize(name, other_property)
#name = name
#other_property = other_property
end
# Other methods you wish to define the behavior of the thing
end
then you can
the_important_thing = ImportantThing.new("foobar", 3.46)
do_important_process(the_important_thing)
then as far as the important process you are running is concerned, the important thing is anything that behaves like a important thing, and it doesn't matter if it is a globally setup or ever unchanging.
This makes for a easy to test architecture which is generally a sign of clear and decoupled design.

Why callbacks for the after_find and after_initialize events is to define them as methods?

The only way to define callbacks for the after_find and after_initialize events is to define them as methods. If you try declaring them as handlers using the second technique, they’ll be silently ignored.
Can anybody explain why is it so?
Why specifically for these two callbacks?
EDIT
From the book:--
Rails has to use reflec- tion to determine whether there are callbacks to be invoked. When doing real database operations, the cost of doing this is normally not significant com- pared to the database overhead. However, a single database select statement could return hundreds of rows, and both callbacks would have to be invoked for each. This slows the query down significantly. The Rails team decided that performance trumps consistency in this case.
What the hell...!!!! Thats all.. Just this as explanation...!!!
From the API:
The after_find and after_initialize exceptions
Because after_find and after_initialize are called for each object found and instantiated by a finder, such as Base.find(:all), we‘ve had to implement a simple performance constraint (50% more speed on a simple test case). Unlike all the other callbacks, after_find and after_initialize will only be run if an explicit implementation is defined (def after_find). In that case, all of the callback types will be called.

Resources