aramirez.es

Alberto Ramírez Website


9 de noviembre de 2010

Enviar emails con Symfony (en background)

5 comentarios >>

Hoy en día, la mayoria de aplicaciones web hacen uso de tareas o comandos de optimización, limpieza de datos, captura de eventos, etc. Estas tareas se lanzan a nivel de sistema operativo mediante una tarea Cron (Cron jobs) que hace llamada a una dirección URL o programa.

Planteando el escenario: en uno de los últimos proyectos en los que estoy trabajando he necesitado la ejecución de una tarea para que libere la cola de envío de emails del tipo Newsletter, es decir, el usuario genera un Newsletter asociado a un listado de suscriptores y lo lanza, una vez landazo, éste queda almacenado en una cola de envío. Para liberar esta cola es necesario lanzar la tarea de Symfony project:send-emails.

Esta tarea se puede ejecutar de forma muy sencilla mediante un Cron un par de veces al día, pero ¿qué ocurre si por impedimentos del sistema no puedo depender de un sistema de Cron? No voy a entrar a explicar ahora el porqué no puedo disponer del Cron del sistema, voy a centrarme en comentar cómo lo he solventado.

Básicamente, lo que he hecho ha sido hacer uso de la función exec() de PHP pero con la peculiaridad de lanzarla en segundo plano. Esto es muy sencillo de hacer y el usuario no depende de la finalización de la tarea para que el navegador le devuelva respuesta sino que, la respuesta es inmediata y la tarea queda en ejecución de forma transparente para el usuario.

Veamos el pequeño script PHP:

<?php
    $symfonyPath = sfConfig::get('sf_root_dir');
    $symfonyCommand = '/symfony project:send-emails --application=backend';
    $output = ' > /dev/null &';
    exec($symfonyPath . $symfonyCommand . $output);
?>

Vamos a explicarlo línea a línea:

    $symfonyPath = sfConfig::get('sf_root_dir');
    $symfonyCommand = '/symfony project:send-emails --application=backend';

Esto no es más que la ruta donde se encuentra el ejecutable de Symfony y la llamada al task en sí, poco más..

    $output = ' > /dev/null &';

Aquí está el punto más interesante. Con esta línea desviamos la salida que produce la tarea hacia una ruta que actúa como "papelera". Con esto y el caracter &, se consigue que la tarea se ejecute en background y el script PHP no requiera estar esperando la ejecución completa del task hasta tener de nuevo el control sino que, la tarea Symfony la va a gestionar directamente el SO como hilo aparte.

Por último, solo queda lanzar la tarea:

    exec($symfonyPath . $symfonyCommand . $output);

De esta forma he conseguido vaciar la cola de envío de emails sin necesidad de una ejecución por medio de Cron y además tengo el control de cuando hacerlo. De esta forma, tras el click del usuario en "Enviar Newsletter" no solo se almacena la cola de envío sino que acto seguido el sistema empieza a procesarla y la gracia de todo esto es que todo queda transparente para el usuario que ejecuta la acción.

Tags: | |


Comentarios

  • Jose Manuel
  • #1 Jose Manuel (11/11/2010 20:22)
  • Que crack....estaba buscando algo parecido.
    Un abrazo.
  • aramirez
  • #2 aramirez (12/11/2010 20:07)
  • Buenas Jose Manuel, me alegra que te sea de ayuda el artículo.

    Un abrazo!
  • Viviana
  • #3 Viviana (23/11/2010 09:07)
  • Pues también agradezco mucho esta información. Tengo que crear una lista que maneje miles de correos y luego los pueda enviar poco a poco. Me resulta raro que con lo común de este tema, no se tengan más clases especializadas en Symfony o que brinde php. Muchas gracias.
  • sergio
  • #4 sergio (23/11/2010 17:12)
  • Sin duda que es muy util, seguimos esperando mas posts de Alberto
  • aramirez
  • #5 aramirez (23/11/2010 17:34)
  • Gracias Viviana y Sergio por los comentarios.

    Viviana, Symfony incorpora una serie de clases (para Doctrine, Propel y File) que gestionan la pila de emails a enviar. Yo uso habitualmente Swift_DoctrineSpool. Puedes verlo en http://librosweb.es/mas-con-symfony/capitulo5/la-estrategia-de-envio.html

    Normalmente, por política de los ISP y sysadmin, los servidores cortan el envío de emails cuando sobrepasan un límite pre-establecido. Por ello, muchas personas usan aplicaciones creadas específicamente para este fin. No obstante, se puede hacer el envío de una larga cola de emails con Symfony, la tarea que se describe en el post "project:send-emails" puede recibir parámetros como el número de correos a enviar o el tiempo límite.

    Si usas ésto sumado a la gestión de la cola mediante Symfony, podrás ejecutar algoritmos eficientes.

    Por otro lado, creo recordar que la función exec de PHP no se ejecuta con el safe_mode activo, por lo que es algo a tener en cuenta.

    Más info en http://es2.php.net/manual/es/function.exec.php
Deja tu comentario

zukeidigital 2008