2017-04-11 7 views
0


私はパラレルサービスをプログラミングするのに苦労しています。目標は、非同期APIコールを使用してFacebookからデータを取得し、その後、GORMアクションを同期的に実行して、取得したデータを繰り返し処理することです。Grails:非同期Webリクエスト後にオブジェクトをDBに保存する方法は?

データをフェッチする最初のステップは、非同期で正常に動作するようです:

List<Activity> activityList = Activity.findAllByFacebookPageIsNotNullAndFetchEvents(true, [max: 100]) 
PromiseList promiseList = new PromiseList() 
activityList.each { Activity activity-> 
    promiseList << { fetchEventData(activity.facebookPage, null) } 
} 

のように今私は、結果を反復処理しようとしています:createEvent()方法はしようとし

promiseList.onComplete { List results -> 
    results.each { ArrayList eventSet -> 
     eventSet.each { LazyMap eventData -> 
      createEvent(eventData) 
     } 
    } 
} 

新しいEventを保存してください。この操作はで失敗します。

2017-04-11 10:56:47.018 ERROR --- [ctor Thread 129] o.h.engine.jdbc.spi.SqlExceptionHelper : No operations allowed after statement closed. 2017-04-11 10:56:47.024 ERROR --- [ctor Thread 124] o.h.engine.jdbc.spi.SqlExceptionHelper : No operations allowed after statement closed. 2017-04-11 10:56:47.024 ERROR --- [ctor Thread 125] o.h.engine.jdbc.spi.SqlExceptionHelper : Cannot convert value '2017-01-11 23:31:39' from column 3 to TIMESTAMP. 2017-04-11 10:56:47.025 ERROR --- [ctor Thread 105] o.h.engine.jdbc.spi.SqlExceptionHelper : No operations allowed after statement closed. 2017-04-11 10:56:47.026 ERROR --- [ctor Thread 103] o.h.engine.jdbc.spi.SqlExceptionHelper : No operations allowed after statement closed. 2017-04-11 10:56:47.026 ERROR --- [ctor Thread 107] o.h.engine.jdbc.spi.SqlExceptionHelper : No operations allowed after statement closed.

だから私はcreateEvent()がさまざまなスレッドの代わりに「メイン」スレッドから呼び出されると思います。

誰かがこれを正しい方法で教えてもらえますか?

編集:

私も試してみました:

List<ArrayList> promiseResult = promiseList.get() 
promiseResult.each { ArrayList<LazyMap> eventList -> 
    eventList.each { 
     Event.findByFacebookId((String) it['id']) 
     //createEvent(it) 
    } 
} 

java.lang.NullPointerException

+0

このコードが呼び出されていますか?新しいスレッドごとに、Eventを使用して新しいGORMトランザクションを作成する必要があります。 withNewTransaction {//ここに更新コード} –

+0

トランザクションサービスです。 – Fmeuer

+0

今私はエラーなしで 'withNewTransaction {}'を使用しています:-)しかし、オブジェクトはDBに永続化されません。 '.save(flush:true、failOnError:true)'を使う – Fmeuer

答えて

0

感謝を試してみてください。彼らは私が正しい道を私に与えたと思う。多分私は達成したいと思ったものをクリアしていないかもしれません。 GORM呼び出しが非同期である必要はありませんでした。これはまだ良いアイデアのようですが!私の方法は遅くする方法です:D

しかし、私はwaitAll()を使用して、その後、DBの処理を行って、望ましい動作を達成しました。

A実施例は以下のとおりです。あなたのGrailsアプリケーションで

List<Activity> activityList = Activity.findAllByFacebookPageIsNotNullAndFetchEvents(true, [max: 100]) 
List promises = [] 
activityList.each { Activity activity-> 
    promises << task { fetchEventData(activity.facebookPage, null) } // query website asynchronously; this is really fast! 
} 

def promisesResults = waitAll(promises) 

promisesResults.each { ArrayList<LazyMap> eventList -> 
    eventList.each { LazyMap eventData -> 
     try { 
      createEvent(eventData) // DB actions; this is pretty slow 
     } catch (e) { 
      log.error(e.toString()) 
     } 
    } 
} 
1

で失敗するあなたの答えのために、この

Event.withNewSession { 
    Event.withNewTransaction { 
     // Event update code here 
    } 
} 
関連する問題