Retry failed email jobs

This commit is contained in:
FreeScout
2018-12-09 01:53:36 -08:00
parent 8e978b7b17
commit 1d8f79f3a2
7 changed files with 72 additions and 20 deletions

View File

@@ -16,6 +16,8 @@ class SendNotificationToUsers implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 5;
public $users;
public $conversation;
@@ -68,10 +70,25 @@ class SendNotificationToUsers implements ShouldQueue
$global_exception = null;
foreach ($this->users as $user) {
// If for one user sending fails the job is marked as failed and retried after some time.
// So we have to check if notification email has already been successfully sent to this user.
if ($this->attempts() > 1) {
// Maybe add indexes to the table.
$already_sent = SendLog::where('thread_id', $last_thread->id)
->where('mail_type', SendLog::MAIL_TYPE_USER_NOTIFICATION)
->where('user_id', $user->id)
->whereIn('status', SendLog::$sent_success)
->exists();
if ($already_sent) {
continue;
}
}
$message_id = \App\Misc\Mail::MESSAGE_ID_PREFIX_NOTIFICATION.'-'.$last_thread->id.'-'.$user->id.'-'.time().'@'.$mailbox->getEmailDomain();
$headers['Message-ID'] = $message_id;
// If this is notification on message from customer set customer as sender name
// If this is notification on message from customer, set customer as sender name
$from_name = '';
if ($last_thread->type == Thread::TYPE_CUSTOMER) {
$from_name = $last_thread->customer->getFullName();
@@ -125,7 +142,14 @@ class SendNotificationToUsers implements ShouldQueue
}
if ($global_exception) {
throw $global_exception;
// Retry job with delay.
// https://stackoverflow.com/questions/35258175/how-can-i-create-delays-between-failed-queued-job-attempts-in-laravel
if ($this->attempts() <= $this->tries) {
$this->release(3600);
throw $global_exception;
} else {
$this->fail($global_exception);
}
}
}

View File

@@ -16,6 +16,8 @@ class SendReplyToCustomer implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 5;
public $conversation;
public $threads;
@@ -123,7 +125,14 @@ class SendReplyToCustomer implements ShouldQueue
// Save to send log
$this->saveToSendLog($e->getMessage());
throw $e;
// Retry job with delay.
// https://stackoverflow.com/questions/35258175/how-can-i-create-delays-between-failed-queued-job-attempts-in-laravel
if ($this->attempts() <= $this->tries) {
$this->release(3600);
throw $e;
} else {
$this->fail($e);
}
}
// In message_id we are storing Message-ID of the incoming email which created the thread

View File

@@ -22,6 +22,20 @@ class SendLog extends Model
const STATUS_UNSUBSCRIBED = 8;
const STATUS_COMPLAINED = 9;
/**
* Status determining successfull sending.
*
* @var [type]
*/
public static $sent_success = [
self::STATUS_ACCEPTED,
self::STATUS_DELIVERY_SUCCESS,
self::STATUS_OPENED,
self::STATUS_CLICKED,
self::STATUS_UNSUBSCRIBED,
self::STATUS_COMPLAINED,
];
/**
* Mail types.
*/

View File

@@ -177,9 +177,12 @@ return [
/*
|--------------------------------------------------------------------------
| Parameters used to run queued jobs processing.
| Checks for new jobs every 5 seconds.
| Do not set more than 1 retry, as it may lead to sending repeated emails if one recipient fails
| and another succeeds.
| Checks for new jobs every --sleep seconds.
| If --tries is set and job fails it is being processed right away without any delay.
| --delay parameter does not work to set delays between retry attempts.
/
| Jobs sending emails are retried manually in handle().
| Number of retries is set in each job class.
|-------------------------------------------------------------------------
*/
'queue_work_params' => ['--queue' => 'emails,default', '--sleep' => '5', '--tries' => '1'],

View File

@@ -38,6 +38,7 @@ return [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
// Retry after does not work as delay between retry attempts.
'retry_after' => 90,
],

View File

@@ -354,20 +354,21 @@
@if ( $thread->opened_at )
<div class='thread-opened-at'><i class="glyphicon glyphicon-eye-open"></i> {{ __("Customer viewed") }} {{ App\User::dateDiffForHumansWithHours($thread->opened_at) }}</div>
@endif
@if ($thread->has_attachments)
<div class="thread-attachments">
<i class="glyphicon glyphicon-paperclip"></i>
<ul>
@foreach ($thread->attachments as $attachment)
<li>
<a href="{{ $attachment->url() }}" class="break-words" target="_blank">{{ $attachment->file_name }}</a>
<span class="text-help">({{ $attachment->getSizeName() }})</span>
</li>
@endforeach
</ul>
</div>
@endif
</div>
@if ($thread->has_attachments)
<div class="thread-attachments">
<i class="glyphicon glyphicon-paperclip"></i>
<ul>
@foreach ($thread->attachments as $attachment)
<li>
<a href="{{ $attachment->url() }}" class="break-words" target="_blank">{{ $attachment->file_name }}</a>
<span class="text-help">({{ $attachment->getSizeName() }})</span>
</li>
@endforeach
</ul>
</div>
@endif
</div>
<div class="dropdown thread-options">
<span class="dropdown-toggle glyphicon glyphicon-option-vertical" data-toggle="dropdown"></span>

View File

@@ -198,7 +198,7 @@
</tr>
<tr>
<td>{{ __('Failed At') }}</td>
<td>{{ App\User::dateFormat($job->failed_at) }}</td>
<td>{{ App\User::dateFormat($job->failed_at, 'M j, Y H:i:s') }}</td>
</tr>
</tbody>
</table>