Estoy tratando de crear un tipo específico de configuración de procesamiento de fondo en una aplicación de grial.Llamando a Hibernate en hilos de fondo en grises
- Existe una tamaño fijo piscina hilo sólo durante la duración del lote de puestos de trabajo
- Un sola sesión es mantenida por cada hilo
- Cada tarea se ejecuta en un transacción separada
Estoy tratando de comenzar el trabajo de la siguiente manera:
int poolSize = 10
ThreadFactory factory = new MyThreadFactory (Executors.defaultThreadFactory())
ExecutorService pool = Executors.newFixedThreadPool (poolSize, factory)
(1..100).each { i ->
pool.submit {
try {
MyDomainClass.withTransaction {
doSomeWork(i)
}
} catch (Exception e) {
log.error "error in job ${i}", e
}
}
}
MyThreadFactory crea roscas que tienen una sesión de hibernación unidos durante la duración de la rosca.
class MyThreadFactory implements ThreadFactory {
ThreadFactory delegate
PersistenceContextInterceptor persistenceInterceptor
MyThreadFactory (ThreadFactory delegate) {
this.delegate = delegate
ApplicationContext applicationContext = ApplicationHolder.getApplication().getMainContext()
persistenceInterceptor = applicationContext.getBean("persistenceInterceptor");
}
Thread newThread (Runnable work) {
return delegate.newThread {
persistenceInterceptor.init()
try {
work.run()
} finally {
persistenceInterceptor.flush()
persistenceInterceptor.destroy()
}
}
}
}
Parece que funciona, sin embargo, obtendré el siguiente error la primera vez que ejecuto el trabajo por lotes. (Trabajos posteriores se ejecutan sin incidentes)
groovy.lang.MissingMethodException: No signature of method: static MyDomainClass.save() is applicable for argument types: (java.util.LinkedHashMap) values: [[flush:false]]
Possible solutions: save(), save(java.util.Map), save(java.lang.Boolean), wait(), any(), wait(long)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at ...
He intentado sustituir el persitanceInterceptor con MyDomainClass.withNewSession {}, sin efecto.
Parece que los métodos GORM no se están inyectando en mis clases de dominio.
¿Alguien puede ver lo que estoy haciendo mal, y por qué ejecutar nuevamente el trabajo por lotes le permite tener éxito?
@fixitagain Para completar el trabajo toma esta forma:
doSomeWork = { id ->
MyDomainClass a = MyDomainClass.findById (id)
a.value = lotsOfWork()
a.save()
}
Creo que la falta ahorra es una cortina de humo, como he tratado de envolver el funcionamiento en una transacción, y luego sale un error que dice " DomainClass.withTransaction (Closure) 'no está definido.
Parece que puede haber una condición de carrera donde el primer trabajo no se ejecuta, pero todos los trabajos siguientes se ejecutan correctamente después de (algo?) ha terminado de iniciarse.
¿En qué punto del ciclo de vida de Grails está iniciando sus trabajos? Parece que está ocurriendo antes de que los dominios se hayan decorado con sus métodos dinámicos, etc. –
Los trabajos se desencadenan a partir de una acción de controlador (por ahora), por lo que es bastante después de que los dominios se hayan decorado. Debo señalar que si llamo a todos los trabajos desde el hilo principal, no ocurre ningún problema. – Akusete
bueno, para mí GORM está "adjuntado" ya que está proponiendo guardar (Mapa) como una posible solución. ¿Puedes poner la línea donde estás usando guardar? BTW flush es falso de manera predeterminada, lo que significa que se vaciará al final de la sesión de Hibernate ... – fixitagain