ActiveRecord: deferir save's en una transaccion

Quiero extender transaction para que en vez de hacer esto

Tabla.transaction do
llaves do |key|
fila = Tabla.find key
fila.calculo_u_operacion
fila.save
end
end

Haga esto

filas = []
Tabla.transaction do
llaves.each do |key|
fila = Tabla.find key
fila.proceso
filas << fila
end
filas.each do |f|
f.save
end
end

O sea, deferir los save para que guarde todas la filas al final de la
transaccion, o sea los proceso como un solo “bulto”

Alguien me puede decir si ya hay algo similar a esto escrito?

Su finalidad no es obvia, se utiliza para sistemas para bases de datos
con alta concurrencia de transacciones. En estos sistemas los bloqueos
sobre registros deben durar la menor cantidad de tiempo posible. Cuando
una transaccion actualiza mas de una fila en un tabla cada fila queda
bloqueda para el resto de la aplicaciones hasta que la transaccion
finalice.
En sistemas de alta concurrencia de transacciones cada transaccion debe
ser lo mas corta en tiempo posible, o sea todos los updates/inserts
deben ejecutarse sin tiempos “muertos”.

Estoy implementando esta funcionalidad para un sistema que ya esta en
produccion, que cada manana corre un proceso de calculos que duran
varios minutos. Y que ha trabado (unas cuantas veces) otras
aplicaciones.

Gracias de antemano

Quiero extender transaction para que en vez de hacer esto

Tabla.transaction do
llaves do |key|
fila = Tabla.find key
fila.calculo_u_operacion
fila.save
end
end

Haga esto

filas = []
Tabla.transaction do
llaves.each do |key|
fila = Tabla.find key
fila.calculo_u_operacion
filas << fila
end
filas.each do |f|
f.save
end
end

O sea, deferir los save para que guarde todas la filas al final de la
transaccion, o sea los proceso como un solo “bulto”

Alguien me puede decir si ya hay algo similar a esto escrito?

Su finalidad no es obvia, es importante para sistemas para bases de
datos con alta concurrencia de transacciones. En estos sistemas los
bloqueos sobre registros deben durar la menor cantidad de tiempo
posible, o sea todos los DML que bloquean filas (update mas que todo)
deben ejecutarse sin tiempos “muertos” entre si. Cada fila que una
transaccion actualiza queda bloqueda hasta que la transaccion finalice,
o sea cualquier otra aplicacion(es) que trate de obtener un bloqueo
sobre una de esas filas esperara hasta que el bloqueo sea liberado.

Estoy implementando esta funcionalidad para un sistema que ya esta en
produccion, que cada manana corre un proceso de calculos que duran
varios minutos. Y que ha trabado (unas cuantas veces) otras
aplicaciones.

Su implementacion no es trivial, implica parchar transaction, save y
save!.
Ahora save y save! en vez de guardar a DB meten a self en un array de
models y transaction debe despues de ejecutar el bloque “do end”
recorrer dicho array del models y ejecutar el save y save! originales.

Ademas mi codigo se parece mas a esto que al de arriba,

filas = ActiveRecord::Base.find_by_sql sql_complejo
ActiveRecord::Base.transaction do
filas.each do |f|
f.calculo_u_proceso_que_ha_su_vez_actualiza_otra_tabla
end
end

asi que me queda mas “facil” parchar los metodos de AR que modificar mis
models

Gracias de antemano

PS: Disculpen si mande este correo mas de una vez pero el mail server de
simplelogica estuvo caido por un tiempo