2011-08-25 13 views
5

Sto provando a creare un tipo specifico di impostazione di elaborazione in background in un'applicazione Grails.Chiamata Hibernate in background thread in grails

  • Un dimensione fissa filo piscina esiste solo per la durata del lotto di posti di lavoro
  • Un singola sessione viene mantenuto da ogni thread
  • Ogni lavoro viene eseguito in un transazione separata

Sto tentando di avviare il lavoro nel modo seguente:

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 fili che hanno una sessione sospensione attaccati per la durata del filo.

Sembra funzionare, tuttavia verrà visualizzato il seguente errore la prima volta che eseguo il processo batch. (Lavori successivi eseguiti senza incidenti)

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 ... 

Ho provato a sostituire il persitanceInterceptor con MyDomainClass.withNewSession {}, senza alcun effetto.

Sembra che i metodi GORM non vengano iniettati nelle mie classi di dominio.

Qualcuno può vedere cosa sto facendo male e perché eseguire di nuovo il processo batch consente di avere successo?

@fixitagain Per completezza il lavoro assume questa forma:

doSomeWork = { id -> 
    MyDomainClass a = MyDomainClass.findById (id) 
    a.value = lotsOfWork() 
    a.save() 
} 

Credo che la mancanza di salvataggio è una falsa pista, come ho cercato avvolgendo il sistema operativo in una transazione, e quindi ottenere un errore che dice ' DomainClass.withTransaction (Closure) "non è definito.

sembra che ci potrebbe essere una condizione di competizione in cui il primo lavoro non riesce a correre, ma tutti i seguenti posti di lavoro eseguito con successo dopo (qualcosa?) ha terminato l'avvio.

+0

A che punto egli int Grails ciclo di vita stanno iniziando i lavori? Suona come è che si verificano prima che i domini sono stati decorati con i loro metodi dinamici ecc –

+0

I lavori sono stati attivati ​​da un'azione di controllo (per ora), quindi è bene dopo i domini sono stati decorati. Devo notare che se richiamo tutti i lavori dal thread principale, non si verificano problemi. – Akusete

+0

bene, per me GORM è "attaccato" dal momento che propone save (Map) come una possibile soluzione. Puoi mettere la linea dove stai usando save. BTW colore è false per impostazione predefinita, il che significa che saranno svuotati al termine della sessione di Hibernate ... – fixitagain

risposta

1

Invece di provare a creare il proprio thread, potrebbe essere consigliabile utilizzare il plugin executor per Grails. Inietta la sessione di sospensione necessaria ai thread che si creano, inoltre è configurabile rispetto all'esecutore che utilizza, al numero di thread, ecc. Lo uso in produzione con processi al quarzo e altri scenari e funziona perfettamente.

Grails Executor Plugin Se si dispone di prenotazioni in uso, è possibile dare un'occhiata al suo codice prima di scrivere la propria strategia di threading.

+0

Ho preso uno sguardo al plug-esecutore, utilizza anche il persistenceInterceptor per creare una sessione in nuove discussioni. Al momento sono probabilmente più interessato ad assicurarmi di capire completamente come funziona Grails/Hibernate prima di usare un plugin. Ma grazie per averlo menzionato. – Akusete

+0

Dopo una seconda occhiata al plugin executor, creerà sempre una nuova sessione per lavoro. Il che ha senso in generale, ma non per il compito specifico che sto cercando. Sto cercando di utilizzare lo stesso meccanismo per creare la sessione come il plugin però. – Akusete

+0

Perché non usi il plug-in Quartz? http://grails.org/plugin/quartz – felipenasc

0

Non riesco a distinguere dal codice o dalla convenzione di denominazione, ma sei sicuro che stai chiamando salva su un'istanza della classe dominio?

+0

ho pensato che era un 'capriccio' con il messaggio di errore, io sto con aria di sfida chiamando save() su un'istanza di classe di dominio. Inoltre, immagino che se questo fosse il problema, non spiegherebbe perché il lavoro terminerebbe correttamente quando lo eseguirò una seconda volta. – Akusete

+0

prima di chiamare a.save(), fa una guida a = a.merge()? – bluesman

0

L'eccezione del metodo mancante implica che si chiami il salvataggio sulla classe, non sull'istanza.

edit: GORM ha già applicato i metodi aggiuntivi, come si può vedere nei nomi dei metodi soluzione suggerita.

Problemi correlati