Я пытаюсь создать определенный тип настройки фоновой обработки в приложении Grails.
- A фиксированный размер пул потоков существует только на время пакета заданий
- A поддерживается один сеанс каждым потоком
- Каждое задание выполняется в отдельной транзакции
Я пытаюсь запустить задание следующим образом:
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 создает потоки, к которым присоединен сеанс гибернации на время потока.
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()
}
}
}
}
Кажется, это работает, однако я получу следующую ошибку при первом запуске пакетного задания.(Последующие задания выполняются без инцидентов)
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 ...
Я попытался заменить persitanceInterceptor на MyDomainClass.withNewSession {} , без эффекта.
Похоже, что GORMметоды не внедряются в классы моего домена.
Кто-нибудь может увидеть, что я делаю неправильно, и почему повторное выполнение пакетного задания позволяет ему успешно завершиться?
@ fixitagain Для полноты работы это выглядит следующим образом:
doSomeWork = { id ->
MyDomainClass a = MyDomainClass.findById (id)
a.value = lotsOfWork()
a.save()
}
Я считаю, что отсутствующее сохранение - это красная сельдь, поскольку я попытался обернуть операцию в транзакции, а затем получил сообщение об ошибке «DomainClass.withTransactionЗакрытие) 'не определено.
Похоже, что может быть условие гонки, при котором не удается выполнить первое задание, но все последующие задания успешно выполняются после того, как ( что-то? ) завершило запускдо.