Pregunta sobre background, parsing, php, symfony – ¿Cómo puedo hacer un análisis de fondo de los datos con Symfony2?

4

Escribo una aplicación web en PHP con Symfony2. El usuario puede cargar un archivo CSV con datos que se guardan en la base de datos. El análisis de cada fila del archivo CSV dura aproximadamente 0,2 segundos porque realizo algunas solicitudes a la API de Google Maps.

Entonces, cuando carga un archivo CSV con 5000 filas, que es un caso realista en mi aplicación, puede tomar 16 minutos analizar todo el archivo.

No quiero que el usuario deba esperar 16 minutos hasta que pueda continuar usando mi aplicación. Entonces, mi pregunta es: ¿cómo puedo analizar el archivo CSV en segundo plano, para que el usuario pueda continuar navegando?

Symfony2 no tiene capacidad de proceso / trabajador en segundo plano fuera de la caja, así que tienes que rodar la tuya. hakre
Me gustaría usar Gearman: es fácil de configurar y funciona con PHP muy bien. halfer

Tu respuesta

3   la respuesta
1

Podría escribir un script que sea solo para procesar el archivo CSV y exec () ese script del script que administra la carga. En los sistemas * IX puede hacer que el comando iniciado por exec () se ejecute en segundo plano agregando un carácter &.

Probablemente también querrá incluir un script que permita al usuario verificar el progreso del procesamiento.

ejecutar un trabajo de larga duración de una solicitud web me parece arriesgado. John Carter
7

Puedes crear unkernel.terminate Escucha el evento y haz tu análisis allí. Este evento se dispara después de que la respuesta se envía al navegador. La implementación de ejemplo sería,

Declaración de servicio,

//services.yml
csv_parse_listener:
    class: FQCN\Of\CsvParseListener
    tags:
        - { name: kernel.event_listener, event: kernel.terminate, method: onKernelTerminate }

Clase de oyente,

namespace Your\namespace;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;

class CsvParseListener
{
    public function onKernelTerminate(PostResponseEvent $event)
    {
        $request = $event->getRequest();
        if($request->get('_route') !== "Your_route"){
            return;
        }

        $csvFile = $request->files->get('file_field_name');

        //move file using $csvFile->move()
        //read and parse
    }
}
La pestaña de eventos no muestra el evento de terminación. Tengo la edición estándar de Symfony 2.0.15 desde aquí:symfony.com/download. ¿Cuál usas? ¿Lo mismo o algo de Github? rotespferd
¿Por qué lo llamaría directamente? Si está registrado entoncesonKernelTerminate El método se llamará automáticamente. ¿Cuál es el mensaje de error? Mun Mun Das
¿El evento "kernel.terminate" es llamable en Symfony2? Mi aplicación web arroja un error cuando quiero usarlo. rotespferd
Raro, debería estar al final de la clase,const TERMINATE = 'kernel.terminate';. ¿Cuál es tu versión de Symfony? Mun Mun Das
4

Haga que la carga inserte un trabajo en una tabla de cola de trabajos y tenga unMando administrado regularmente porcron que maneja cualquier trabajo en la tabla de cola de trabajos.

A medida que avanza el procesamiento de un trabajo, puede actualizar la tabla de trabajos para que un usuario pueda verificar y ver cómo ocurre el progreso (por ejemplo, podría tener una barra de progreso de Ajax) y saber cuándo finaliza el trabajo.

De esta manera, también se despeja la carga del proceso y puede controlar cuántos trabajos se procesan a la vez. Hacer que los trabajos de larga duración se inicien directamente desde la entrada del usuario sin un sistema de limitación / puesta en cola en su lugar es una excelente manera de abrirse a un ataque de denegación de servicio ...

Eso suena como una buena idea. Lo intentaré de esta manera. Gracias :) rotespferd

Preguntas relacionadas