skip to Main Content

I am having a hard time programming parallel services. The goal is to retrieve data from Facebook with asynchronous API calls and afterwards iterate over the retrieved data synchronously performing GORM actions.

The first step of fetching data asynchronously seems to work fine with:

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

Now I am trying to iterate over the results, like:

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

The createEvent() method tries to save new a Event. This operation fails with:

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.

So I guess createEvent() is called from various threads instead of the “main” thread.

Can someone please tell me how to do this the right way?

Edit:

I also tried:

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

Fails with java.lang.NullPointerException

2

Answers


  1. Chosen as BEST ANSWER

    Thanks for your answers. I think they got me on the right track. Maybe I wasn't to clear with what I wanted to achieve. It wasn't necessary that GORM calls are asynchronous. Although this still seems a good idea! My method is way to slow :D

    However I achieved the desired behaviour using waitAll() and afterwards doing the DB handling.

    A working example is:

    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())
            }
        }
    }
    

  2. Try this

    Event.withNewSession {
        Event.withNewTransaction {
            // Event update code here
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search