I am trying to add Files to a (Blog)Post Domain Object.
The file uploader allows to send multiple ajax requests one for each file in parallel.
How can I best take care of the synchronization on the server side?
To avoid:
Could not synchronize database state with session org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect):
I am doing this in Grails service with:
static scope = "session"
This didn't do what I needed.
Related
In our application, we have several models which need to connect to different external databases that hold the same tables and columns, but are each separate and cannot be unified.
Currently, the application runs on separate servers, in which each is connected only to a specific external database. However, these are 10+ servers, all serving the exact same application, with the only difference being the external database they connect to.
The goal is to have a single server running the application and have the application decide which database to query based on a certain parameter passed into the controller.
Our current approach is the following. We have an abstract class from which relevant models inherit, with a method to reconnect it to the specific database:
class AbstractRecord < ApplicationRecord
self.abstract_class = true
def self.reconnect
database = Thread.current[:database_name].constantize
self.establish_connection database
end
end
Then, we have every controller inherit from a controller class with a before_action that sets the current database name in Thread.current and calls that method:
class AccessController < ApplicationController
before_action :set_current_database
private
def set_current_database
Thread.current[:database_name] = current_user.database_name
AbstractRecord.reconnect
end
end
Each user has the information on which database they need to connect to, and so the application reconnects the database based on the current user.
This application also serves an API, with controllers inheriting from a similar controller that also reconnects the database based on the current API user.
We know all of the databases we need to connect to and keep them in yml files, and all of them are loaded into constants inside an initializer.
This approach works for the most part. Whenever a request is made, the database is successfully reconnected to the appropiate database, and the application functions as normal.
However, issues arise when a request is sent at the same time that another request is being processed, both in development and production:
ActiveRecord::ConnectionNotEstablished (No connection pool with 'AbstractRecord' found.)
This error is raised whenever any model that needs to query the AbstractRecord database does so after a new connection has been initiated in a different request.
Given enough time to finish, requests don't seem to interfere with each other and the database reconnections work fine.
It is my understanding that Rails handles requests on individual threads for each of them, and each thread uses a different database connection, which raises the question: Why is establish_connection causing other requests to lose their connection? Is there a major misunderstanding on how threads and database connections work in Rails in this case?
Back to the main question: How can I dynamically connect my models to a specific database during a single request in this version of Rails? Is this approach correct, or is there a more adequate solution?
Rails version: 5.2.4.3
Ruby version: 2.6.3p62
#Joaquin for me this is clearly a case of multi-tenancy, where I must have a central database with a customer table and their respective database connection. There are some libraries that do this elegantly, with the ar-octopus gem.
In your case, there is a concorrency failure, as the key you are using in Thread.current is probably being used in two or more simultaneous executions. A change I would make would be to make your Thread.current key more specific as
Thread.current[:"#{current-table-name}_database_name"] = current_user.database_name
where the Person class would have the key Thread.current[:"#{Person.table_name}_database_name"], but this approach is not a silver bullet and is certainly has flaws.
I suggest looking at gem ar-octopus, it will bring you many benefits.
I'm reading the Grails docs on services which make numerous mention of transactions/transactionality, but without really defining what a transactional service method really is.
Given the nature of services, they frequently require transactional behaviour.
What exactly does this mean? Are transactional methods only those that use JPA/JDBC to communicate with a relational DB, or do they apply to anything covered by JTA?
Is there any reason why I just wouldn't make a service class #Transactional in case it evolves to some day use a transaction? In other words, are there performance concerns to making all service methods transactional?
Grails services are transactional by default - if you don't want a service to be transactional, you need to remove all #Transactional annotations (both Grails' #grails.transaction.Transactional and Spring's #org.springframework.transaction.annotation.Transactional) and add
static transactional = false
If you haven't disabled transactions with the transactional property and have no annotations, the service works the same as if it were annotated with Spring's annotation. That is, at runtime Spring creates a CGLIB proxy of your class and registers an instance of the proxy as the Spring bean, and it delegates to an instance of your actual class to do the database access and your business logic. This lets the proxy intercept all public method calls and start a new transaction, join an existing one, create a new one, etc.
The newer Grails annotation has all of the same settings as the Spring annotation, but it works a bit differently. Instead of triggering the creation of a single proxy, each method is rewritten by an AST transform during compilation, essentially creating a mini proxy for each method (this is obviously a simplification). This is better because the database access and transaction semantics are the same, but if you call one annotated method from another annotated with different settings, the different settings will be respected. But with a proxy, it's a direct call inside the delegate instance, and the proxy is bypassed. Since the proxy has all of the logic to create a new transaction or use other different settings, the two methods will use the first method's settings. With the Grails annotation every method works as expected.
There is a small performance hit involved for transactional methods, and this can accumulate if there are a lot of calls and/or a lot of traffic. Before your code runs, a transaction is started (assuming one isn't active) and to do this, a connection must be retrieved from the pool (DataSource) and configured to turn off autocommit, and make the various transaction settings (isolation, timeout, readonly, etc.) have to be made. But the Grails DataSource is actually a smart wrapper around the "real" one. It doesn't get a real JDBC Connection until you start a query, so all of the configuration settings are cached until then, and then "replayed" on the real connection. If the method doesn't do any database work (either because it never does, or because it exits early based on some condition before the db access code fires), then there's basically no database cost. But if it does, then things work as expected.
Don't rely on this DataSource proxying logic though - it's best to be explicit about which services are transactional and which aren't, and within each service which methods are transactional and which aren't. The best way to do this is by annotating methods as needed, or adding a single annotation at the class level if all methods use the same settings.
You can get more info in this talk I did about transactions in Grails.
First, if your performance concerns are due to the fact your services are transactional then you have reached nirvana. I say this because there are going to be plenty of other bottle necks in your application long before this is a major (or even minor) concern. So, don't fret about that.
Typically in Grails a transaction relates to the transactional state of a database connection or hibernate session. Though it could be anything managed by the JTA with the proper Spring configuration.
In simple terms, it's usually means (by default) a database transaction.
I have an ASP.NET MVC application that uses NHibernate to persist data into a SQL Server database.
There are cases where I want to save an entry into a database (initially triggered by a call into an action method on a controller) but there's no need to block the caller.
Is it "safe" to try to implement a fire-and-forget mechanism into the database that will put the database call into a Task and then invoke it on the background so control can return immediately to the caller? (OR accomplish the same thing with BackgroundWorker or the "async/await" keywords) I need a solution where NHibernate will not get tripped up by ASP.NET trying to clean up its ISession, which is per-request. I'm using Autofac for lifetime management on the session. I assume that the database operation would have a slightly longer lifetime than the web request itself, and I'm not sure how smoothly that would work.
It is not safe to do this; I have a blog post on the subject. The problem is that when you have no requests in progress, it is possible that your entire AppDomain can be torn down. Also, consider what would happen if the database insert failed for some reason? If you return early, then there's no way to notify the client of an error.
A reliable solution must store the data in some kind of persistent place before returning success to the caller. This can be directly in the database, or in a queue of some kind (to be later processed by an independent worker).
I know if a Grails service is transactional a call to save(flush: true) can be rolled back. My question is if there is ever a need to call flush whilst in a service.
It depends on the working scenario. Ideally, it wont be necessary to flush every time you save something in the service class because the session gets flushed once returned back from the service class.
But think of a scenario where you have two different hibernate sessions working separately but data from one depends on another, then you would need to flush.
For example, Session 2 needs data read from db which frequently gets updated by Session 1 at the same time then that information has to be flushed to underlying persistence to make it available for session 2.
You can get granularity about how transactions can be handled by using #Transactional in service class explicitly and specifying the Propagation/Isolation Strategy, if required.
If you are doing bulk inserts using Hibernate then you will want to flush the Session periodically in order to prevent an OutOfMemoryException as the Session will keep growing until it is flushed (and cleared). Flushing writes the objects queued in the Hibernate Session cache to the database (in other words, doing SQL inserts), but the inserts are within the scope of a DB transaction so they can be rolled back.
The Hibernate docs have further discussion on this topic.
I've just run into a problem with a Quartz job that I'm invoking through Spring. My ExecuteInternal method had a [Transaction] attribute (because it does a load of DB calls) but when it runs, I get the 'No NHibernate session bound to thread' error.
Just wondering if that's because Spring.NET doesn't support the [Transaction] attribute in Quartz objects?
If not, that's fine... I can start a transaction manually, but wanted to check that it was the case, and not a silly error in my config somewhere.
[Update]
I figured it out actually. In the API docs, it says the preferable way to do this is use transactions on the service layer. My job was using DAOs to do its work, but my transactions are on my service layer, so I just called service methods from my job instead to do the same work (saving, updating records etc) since they already existed.
It also suggests that if you give the SchedulerFactoryObject a DbProvider, you can use transactions in the job itself, but when I did that it seemed to want to find my triggers configured in a special table in the DB (which I haven't set up since my triggers are all in XML) but that's possibly another way to do it.
Calling service methods works fine for me though.
The transaction attribute works using aop. Spring.NET creates an aop proxy for the decorated object. This proxy creates the session and starts the transaction.
In the ExecuteInternal method, you don't call the method on a proxy, but on the target itself. Therefore spring cannot intercept the call and do its transaction magic.
Your services are injected and therefore the transaction attribute works for them.
There's a good explanation in the spring docs on this subject: http://www.springframework.net/doc-latest/reference/html/transaction.html#tx-understandingimpl