5

Tengo un bookmarklet que, cuando se usa, envía todas las URL en la página actual del navegador a una aplicación de Rails 3 para su procesamiento. Detrás de escena estoy usando Typhoeus para verificar que cada URL devuelva un código de estado 2XX. Actualmente inicio este proceso a través de una solicitud de AJAX al servidor Rails y simplemente espero mientras procesa y devuelve los resultados. Para un conjunto pequeño, esto es muy rápido, pero cuando el número de URL es bastante grande, el usuario puede esperar hasta, por ejemplo, 10-15 segundos.¿Práctica recomendada para procesar una gran cantidad de datos mientras el usuario espera (en Rails)?

He considerado utilizar el trabajo diferido para procesar esto fuera del hilo del usuario, pero este no parece el caso de uso correcto. Dado que el usuario debe esperar hasta que finalice el procesamiento para ver los resultados, y el Trabajo diferido puede demorar hasta cinco segundos antes de que el trabajo se inicie, no puedo garantizar que el procesamiento se realice lo antes posible. Este tiempo de espera no es aceptable en este caso, lamentablemente.

Idealmente, lo que creo que debería suceder es lo siguiente:

  • usuario pulsa bookmarklet
  • Los datos se envían al servidor para su procesamiento
  • Una página de espera se devuelve al instante, mientras que la escisión de un hilo que hacer el procesamiento
  • La página de espera sondea periódicamente a través de ajax los resultados del procesamiento y actualiza la página de espera (por ejemplo: "4 de 567 URL procesadas ...")
  • la página de espera se actualiza con los resultados una vez que estén listos

Algunos detalles adicionales:

  • estoy usando Heroku (procesos de larga ejecución mueren al cabo de 30 segundos)
  • Tanto iniciado la sesión y los usuarios anónimos pueden use esta característica

¿Es esta una forma típica de hacer esto, o hay una manera mejor? ¿Debo simplemente rodar mi propio proceso fuera de subproceso que actualiza la base de datos durante el procesamiento o hay algo así como el trabajo diferido que puedo utilizar para esto (y que funciona en Heroku)? Cualquier empuje en la dirección correcta sería muy apreciado.

+0

¿Qué hiciste al final? – Ari

+0

@Ari Ha pasado mucho tiempo desde que trabajé en esto, pero en general usé un procesador de fondo (usaría sidekiq hoy) junto con una máquina de estado que rastreaba el progreso. Luego, acabo de sondear usando xhr en la interfaz hasta que el estado esté "completo" o lo que sea que necesite. – markquezada

+0

Gracias. ¿Entonces supongo que Thread.new no funcionaría solo? – Ari

Respuesta

1

Creo que su última idea tiene más sentido. Simplemente descargaría el procesamiento de cada url-check a su propio hilo (para que todas las revisiones de URL se ejecuten simultáneamente, lo que debería ser mucho más rápido que las verificaciones secuenciales de todos modos). A medida que finaliza, actualiza la base de datos (asegurándose de que los hilos no se pisan las escrituras). Un punto final AJAX, que como dijiste, sondeas periódicamente del lado del cliente, captará y devolverá el recuento de los procesos completados desde la base de datos. Este es un método bastante simple que realmente no veo la necesidad de ningún componente adicional.

+0

Afortunadamente, Typhoeus procesa las URL en paralelo, por lo que es mucho más rápido que hacerlo en serie. También proporciona una devolución de llamada on_complete que puedo conectar. (Actualmente, lo estoy usando para almacenar en caché los resultados en Memcache.) Creo que lo que no entiendo es esto: ¿cómo adjunto estos datos a un usuario? Especialmente si el usuario es anónimo. ID de la sesión, ¿supongo? De alguna manera no quiero que estos datos se almacenen en mi base de datos si es un usuario anónimo. – markquezada

+0

Parece que ya tiene el sistema en su lugar. Simplemente agregue una ID de sesión a la (s) clave (s) que configuró en sus controladores Typhoeus on_complete. Y luego, en el punto final de la encuesta, que accede a estas claves de Memcache basadas en la identificación de la sesión, puede (una vez que todo se procesa y devuelve al usuario) purgar las claves relevantes de la base de datos. Pero en base a su comentario, estoy seguro de que ya lo pensó y tiene algún problema, pero realmente no estoy siguiendo el tema. –

+0

Ah, supongo que simplemente no pensé usar Memcache directamente como una tienda temporal para los datos de resultados completados. Solo lo estoy usando ahora para almacenar en caché el resultado del rastreo de url individual. (No está vinculado a un usuario específico.) Pero tiene razón, podría usar totalmente Memcache para almacenar temporalmente el resultado completo de la solicitud de un usuario específico. De esta forma, no destruirá la base de datos para usuarios anónimos, ya que no se trata de datos críticos. (Se guardará persistentemente para los usuarios registrados). Gran idea. Gracias por ayudarme a pensar en esto. – markquezada

Cuestiones relacionadas