Quiero activar un correo electrónico cuando se agregan nuevas filas a una tabla en mi solicitud de Laravel. Sin embargo, quiero agregar un tipo de búfer, por lo que si se agregan 5 filas en rápida sucesión, solo se envía 1 correo electrónico.

El método que he elegido es programar un cheque cada 15 minutos y ver si hay nuevas filas agregadas. Si hay que entonces haré cola un correo electrónico.

Actualmente estoy recibiendo un error en el horario. Voy a pasar por mi código a continuación:

En kernel.php donde configuramos los horarios que tengo:

        $schedule->job(new ProcessActivity)
        ->everyFifteenMinutes()
        ->when(function () {
            return \App\JobItem::whereBetween('created_at', array(Carbon::now()->subMinutes(15), Carbon::now()))->exists();
        })
        ->onSuccess(function () {
            Log::debug(
                'Success'
            );
        })
        ->onFailure(function () {
            Log::debug(
                'Fail'
            );
        });

Que uso para activar el trabajo encontrado en: app \ trabajos \ processactivity.php :

 public function __construct()
{

    $this->jobs = \App\JobItem::whereBetween('created_at', array(Carbon::now()->subMinutes(15), Carbon::now()))->get();
}

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
{


    Log::debug('Activity Job Run',  ['jobs' => $this->jobs]);

    $this->jobs->each(function ($item, $key) {
        Log::debug('loop');

        // get project
        $project = $item->project;

        // get project email
        $user_id = $project->user_id;
        $email = \App\User::find($user_id)->email;

        // get project UUID
        $projectUuid = $project->public_id;

        // emails
        $subscriberEmails = \App\ProjectSubscription::where('project_id', $project->id)->get();

        // create activity email
        Notification::route('mail', $subscriberEmails)->notify(new Activity($project, $projectUuid));
    });

    return true;
}

He publicado mi código completo arriba, que también muestra una relación entre mis empleos y modelos de proyectos. No hago elaborar eso como he comentado en el código.

El problema

Cuando agrego una nueva fila a mi tabla Jobitem, puedo ver que el trabajo está programado y procesado (usando Laravel Telescope para inspeccionar esto).

Sin embargo, también puedo ver en mi registro que para cada trabajo obtengo dos mensajes de registro:

Primero: ' Fallo ' y luego ' Actividad Trabajo ejecutado '

Mi correo electrónico no se envía y no estoy seguro de cómo determinar por qué está fallando esto.

Así que parece que se está activando OnFailure y hay un problema con mi proceso.

Cualquier pista sobre dónde me voy mal y cómo determinar el error sería muy apreciado.

1
raison 15 jul. 2019 a las 03:39

1 respuesta

La mejor respuesta

Tengo una solución, pero primero, aquí hay algunas cosas que aprendí que obstaculizó mi progreso:

Estaba usando este comando artesanal para procesar mis trabajos programados:

php artisan queue:work

El problema con el desarrollo mientras usa ese comando es que si hay cambios de código, entonces esos cambios no se reconocen.

Para que pueda comandar + C para volver a la consola y usar esto cada vez que haya un cambio de código:

php artisan queue:restart
php artisan queue:work

O simplemente puede usar esto y permitirá los cambios de código:

php artisan queue:listen

¡Como se puede imaginar sin saberlo, tendrá un proceso de depuración lento!

Como resultado de esto y agregar una excepción a mi trabajo, hice algún progreso. Pegaré en el código a continuación para comparar el código original:

    public function __construct()
{
}

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
{
    try {

        $jobs = \App\JobItem::whereBetween('created_at', array(Carbon::now()->subMinutes(20), Carbon::now()))->get();

        Log::debug('Activity Job',  ['jobs' => $jobs]);

        // collection start
        $collection = collect();

        // loop jobs to get emails
        foreach ($jobs as $key => $value) {

            // get project UUID
            $project = $value->project;
            $projectUuid = $project->public_id;

            // get emails subscribed to projects
            $subscriberEmails = \App\ProjectSubscription::where('project_id', $project->id)->get();

            // merge into a single collection via the loop
            if ($key != 0) {
                $merge = $collection->merge($subscriberEmails);
                $collection = collect($merge);
            } else {
                $collection = $subscriberEmails;
            }

            // Log::debug('emails_project in loop', ['emails' => $subscriberEmails]);
        };

        // clean object with uniques only
        $subscriberEmailsCleaned = $collection->unique();

        // debug
        Log::debug('Project Emails to Notify', ['emails' => $subscriberEmailsCleaned]);

        // create activity email
        Notification::route('mail', $subscriberEmailsCleaned)->notify(new Activity($project, $projectUuid));
    } catch (\Exception $e) {
        \Log::info($e->getMessage());
    }
}

Lo primero a tener en cuenta, es que, como __construct () se ejecuta inicialmente y se enoja. Luego, el método de la manija se llama cuando se procesa el trabajo. Así que tuve que mover mi consulta elocuente al método de asa.

También usé un foreach en lugar de. Cada vez se lova y creo una nueva colección de correos electrónicos. Tal vez haya una manera más elegante, pero necesitaba crear una colección de correos electrónicos y de esta manera me permitió mover las variables en el bucle externo para ser utilizado en el método.

Puedes verme fusionar esto en la parte inferior del bucle.

También he agregado algunos registros :: Artículos que son útiles para la depuración.

no se fija 100% Con este código, ahora puedo programar automáticamente un correo electrónico cada X minutos cuando se agregan nuevos artículos. Sin embargo, todavía estoy obteniendo el registro Fallo en el OnFailure () desde mi archivo Kernal.php:

        ->onFailure(function () {
        Log::debug(
            'Fail'
        );

Todavía estoy confundido en cuanto a lo que indica y cómo puedo determinar más información sobre cómo esto ha fallado y lo que eso significa. Sin embargo, funciona, por lo que seguiré adelante con cautela (con un ojo abierto en los comentarios, en caso de que alguien tenga una idea que pueda ayudar).

1
raison 17 jul. 2019 a las 19:20