Pregunta Sugerencias para formas sencillas de procesar asincrónicamente en Grails


Digamos que tengo un controlador simple como este:

class FooController {

  def index = {
     someVeryLongCompution() //e.g crawl a set of web pages
     render "Long computation was launched."
  }
}

Cuando se invoca la acción de índice, quiero que el método vuelva inmediatamente al usuario mientras se ejecuta el cálculo largo de forma asíncrona.

Entiendo que la forma más sólida de hacer esto sería usar un intermediario de mensajes en la arquitectura, pero me preguntaba si existe una forma más sencilla de hacerlo.

Probé el complemento Ejecutor, pero eso bloquea el retorno de la solicitud http hasta que se complete el cálculo largo.

Probé el complemento Quartz, pero parece ser bueno para las tareas periódicas (a menos que haya una forma de ejecutar un trabajo solo una vez).

¿Cómo están manejando esas solicitudes en Grails?


10
2018-05-28 18:13


origen


Respuestas:


¿Dónde desea procesar veryLongComputation (), en el mismo servidor de Grails, o en un servidor diferente?

Si el mismo servidor no necesita JMS, otra opción es simplemente crear un nuevo hilo y procesar el cálculo de forma asincrónica.

def index = {
     def asyncProcess = new Thread({
          someVeryLongComputation()
     } as Runnable )
     asyncProcess.start()

     render "Long computation was launched."
  }

5
2018-02-14 15:44



Si usa un desencadenador simple en Grails Quartz y configura el repeatCount en 0, el trabajo solo se ejecutará una vez. Se ejecuta por separado de las solicitudes de los usuarios, sin embargo, por lo que necesitaría encontrar una forma de comunicarse con el usuario cuando se complete.


3
2018-05-28 18:23



Sé que esta es una pregunta muy antigua, solo quería dar una respuesta actualizada.

Desde grills 2.3, el framework soporta llamadas asincrónicas usando el manejo asíncrono de solicitudes de Servlet 3.0 (por supuesto, se debe usar un contenedor de servlet 3.0 y la versión del servlet debe ser 3.0 en la configuración, que es por defecto)

Está documentado aquí: http://grails.org/doc/latest/guide/async.html

En general, hay dos formas de lograr lo que solicitó:

import static grails.async.Promises.*
   def index() {
      tasks books: Book.async.list(),
            totalBooks: Book.async.count(),
            otherValue: {
              // do hard work
            }
   }

o la forma Servlet Async:

def index() {
    def ctx = startAsync()
    ctx.start {
        new Book(title:"The Stand").save()
        render template:"books", model:[books:Book.list()]
        ctx.complete()
    }
}

Nota pequeña: el método de Grails está usando promesas, que es un gran avance (asincrónico). Cualquier Promesa se puede encadenar a otra promesa, tener una devolución de llamada en caso de éxito y error, etc.


3
2017-11-26 21:57



¿Has probado Grails? Promesas API? Debería ser tan simple como

import static grails.async.Promise
import static grails.async.Promises

class FooController {

  def index = {
     Promise p = Promises.task {
         someVeryLongCompution() //e.g crawl a set of web pages
     }
     render "Long computation was launched."
  }
}

2
2018-03-19 02:38



Tratar Plugin de eventos de primavera - Admite escuchas de eventos asincrónicos.


1
2018-02-14 16:20



Si desea utilizar el complemento Quartz (como siempre lo hacemos), puede hacerlo así. Funciona bien para nosotros:

DEFINE A JOB (sin disparadores programados)


1
2018-02-17 10:27



La mejor solución para este tipo de problema es usar JMS, a través del Plugin JMS.

Para una implementación más simple, que no requiere un servidor / servicio externo, puede intentar Eventos de primavera enchufar.


0
2018-05-28 21:34