feat: scheduled task failed notification
This commit is contained in:
parent
98b6aec203
commit
a3d73634e7
@ -6,14 +6,12 @@
|
|||||||
use App\Actions\Proxy\CheckProxy;
|
use App\Actions\Proxy\CheckProxy;
|
||||||
use App\Actions\Proxy\StartProxy;
|
use App\Actions\Proxy\StartProxy;
|
||||||
use App\Actions\Shared\ComplexStatusCheck;
|
use App\Actions\Shared\ComplexStatusCheck;
|
||||||
use App\Models\Application;
|
|
||||||
use App\Models\ApplicationPreview;
|
use App\Models\ApplicationPreview;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\ServiceDatabase;
|
use App\Models\ServiceDatabase;
|
||||||
use App\Notifications\Container\ContainerRestarted;
|
use App\Notifications\Container\ContainerRestarted;
|
||||||
use App\Notifications\Container\ContainerStopped;
|
use App\Notifications\Container\ContainerStopped;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
|
||||||
class GetContainersStatus
|
class GetContainersStatus
|
||||||
|
@ -8,14 +8,13 @@
|
|||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
use App\Models\Team;
|
use App\Models\Team;
|
||||||
|
use App\Notifications\ScheduledTask\TaskFailed;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
class ScheduledTaskJob implements ShouldQueue
|
class ScheduledTaskJob implements ShouldQueue
|
||||||
{
|
{
|
||||||
@ -114,6 +113,7 @@ public function handle(): void
|
|||||||
'message' => $this->task_output ?? $e->getMessage(),
|
'message' => $this->task_output ?? $e->getMessage(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
$this->team?->notify(new TaskFailed($this->task, $e->getMessage()));
|
||||||
// send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage());
|
// send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage());
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@ public function handle(): void
|
|||||||
$payload = [
|
$payload = [
|
||||||
'content' => $this->text,
|
'content' => $this->text,
|
||||||
];
|
];
|
||||||
ray($payload);
|
|
||||||
Http::post($this->webhookUrl, $payload);
|
Http::post($this->webhookUrl, $payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ class Discord extends Component
|
|||||||
'team.discord_notifications_deployments' => 'nullable|boolean',
|
'team.discord_notifications_deployments' => 'nullable|boolean',
|
||||||
'team.discord_notifications_status_changes' => 'nullable|boolean',
|
'team.discord_notifications_status_changes' => 'nullable|boolean',
|
||||||
'team.discord_notifications_database_backups' => 'nullable|boolean',
|
'team.discord_notifications_database_backups' => 'nullable|boolean',
|
||||||
|
'team.discord_notifications_scheduled_tasks' => 'nullable|boolean',
|
||||||
];
|
];
|
||||||
protected $validationAttributes = [
|
protected $validationAttributes = [
|
||||||
'team.discord_webhook_url' => 'Discord Webhook',
|
'team.discord_webhook_url' => 'Discord Webhook',
|
||||||
|
@ -28,6 +28,7 @@ class Email extends Component
|
|||||||
'team.smtp_notifications_deployments' => 'nullable|boolean',
|
'team.smtp_notifications_deployments' => 'nullable|boolean',
|
||||||
'team.smtp_notifications_status_changes' => 'nullable|boolean',
|
'team.smtp_notifications_status_changes' => 'nullable|boolean',
|
||||||
'team.smtp_notifications_database_backups' => 'nullable|boolean',
|
'team.smtp_notifications_database_backups' => 'nullable|boolean',
|
||||||
|
'team.smtp_notifications_scheduled_tasks' => 'nullable|boolean',
|
||||||
'team.use_instance_email_settings' => 'boolean',
|
'team.use_instance_email_settings' => 'boolean',
|
||||||
'team.resend_enabled' => 'nullable|boolean',
|
'team.resend_enabled' => 'nullable|boolean',
|
||||||
'team.resend_api_key' => 'nullable',
|
'team.resend_api_key' => 'nullable',
|
||||||
|
@ -18,10 +18,12 @@ class Telegram extends Component
|
|||||||
'team.telegram_notifications_deployments' => 'nullable|boolean',
|
'team.telegram_notifications_deployments' => 'nullable|boolean',
|
||||||
'team.telegram_notifications_status_changes' => 'nullable|boolean',
|
'team.telegram_notifications_status_changes' => 'nullable|boolean',
|
||||||
'team.telegram_notifications_database_backups' => 'nullable|boolean',
|
'team.telegram_notifications_database_backups' => 'nullable|boolean',
|
||||||
|
'team.telegram_notifications_scheduled_tasks' => 'nullable|boolean',
|
||||||
'team.telegram_notifications_test_message_thread_id' => 'nullable|string',
|
'team.telegram_notifications_test_message_thread_id' => 'nullable|string',
|
||||||
'team.telegram_notifications_deployments_message_thread_id' => 'nullable|string',
|
'team.telegram_notifications_deployments_message_thread_id' => 'nullable|string',
|
||||||
'team.telegram_notifications_status_changes_message_thread_id' => 'nullable|string',
|
'team.telegram_notifications_status_changes_message_thread_id' => 'nullable|string',
|
||||||
'team.telegram_notifications_database_backups_message_thread_id' => 'nullable|string',
|
'team.telegram_notifications_database_backups_message_thread_id' => 'nullable|string',
|
||||||
|
'team.telegram_notifications_scheduled_tasks_thread_id' => 'nullable|string',
|
||||||
];
|
];
|
||||||
protected $validationAttributes = [
|
protected $validationAttributes = [
|
||||||
'team.telegram_token' => 'Token',
|
'team.telegram_token' => 'Token',
|
||||||
|
@ -113,6 +113,18 @@ public function link()
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
public function failedTaskLink($task_uuid)
|
||||||
|
{
|
||||||
|
if (data_get($this, 'environment.project.uuid')) {
|
||||||
|
return route('project.application.scheduled-tasks', [
|
||||||
|
'project_uuid' => data_get($this, 'environment.project.uuid'),
|
||||||
|
'environment_name' => data_get($this, 'environment.name'),
|
||||||
|
'application_uuid' => data_get($this, 'uuid'),
|
||||||
|
'task_uuid' => $task_uuid
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public function settings()
|
public function settings()
|
||||||
{
|
{
|
||||||
return $this->hasOne(ApplicationSetting::class);
|
return $this->hasOne(ApplicationSetting::class);
|
||||||
|
@ -653,6 +653,18 @@ public function link()
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
public function failedTaskLink($task_uuid)
|
||||||
|
{
|
||||||
|
if (data_get($this, 'environment.project.uuid')) {
|
||||||
|
return route('project.service.scheduled-tasks', [
|
||||||
|
'project_uuid' => data_get($this, 'environment.project.uuid'),
|
||||||
|
'environment_name' => data_get($this, 'environment.name'),
|
||||||
|
'application_uuid' => data_get($this, 'uuid'),
|
||||||
|
'task_uuid' => $task_uuid
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public function documentation()
|
public function documentation()
|
||||||
{
|
{
|
||||||
$services = getServiceTemplates();
|
$services = getServiceTemplates();
|
||||||
|
@ -32,6 +32,9 @@ public function send($notifiable, $notification): void
|
|||||||
case 'App\Notifications\Database\BackupFailed':
|
case 'App\Notifications\Database\BackupFailed':
|
||||||
$topicId = data_get($notifiable, 'telegram_notifications_database_backups_message_thread_id');
|
$topicId = data_get($notifiable, 'telegram_notifications_database_backups_message_thread_id');
|
||||||
break;
|
break;
|
||||||
|
case 'App\Notifications\ScheduledTask\TaskFailed':
|
||||||
|
$topicId = data_get($notifiable, 'telegram_notifications_scheduled_tasks_thread_id');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!$telegramToken || !$chatId || !$message) {
|
if (!$telegramToken || !$chatId || !$message) {
|
||||||
return;
|
return;
|
||||||
|
@ -31,7 +31,7 @@ public function toMail(): MailMessage
|
|||||||
$mail->view('emails.container-restarted', [
|
$mail->view('emails.container-restarted', [
|
||||||
'containerName' => $this->name,
|
'containerName' => $this->name,
|
||||||
'serverName' => $this->server->name,
|
'serverName' => $this->server->name,
|
||||||
'url' => $this->url ,
|
'url' => $this->url,
|
||||||
]);
|
]);
|
||||||
return $mail;
|
return $mail;
|
||||||
}
|
}
|
||||||
|
64
app/Notifications/ScheduledTask/TaskFailed.php
Normal file
64
app/Notifications/ScheduledTask/TaskFailed.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications\ScheduledTask;
|
||||||
|
|
||||||
|
use App\Models\ScheduledTask;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
|
class TaskFailed extends Notification implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
public $backoff = 10;
|
||||||
|
public $tries = 2;
|
||||||
|
|
||||||
|
public ?string $url = null;
|
||||||
|
|
||||||
|
public function __construct(public ScheduledTask $task, public string $output)
|
||||||
|
{
|
||||||
|
if ($task->application) {
|
||||||
|
$this->url = $task->application->failedTaskLink($task->uuid);
|
||||||
|
} else if ($task->service) {
|
||||||
|
$this->url = $task->service->failedTaskLink($task->uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function via(object $notifiable): array
|
||||||
|
{
|
||||||
|
|
||||||
|
return setNotificationChannels($notifiable, 'scheduled_tasks');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toMail(): MailMessage
|
||||||
|
{
|
||||||
|
$mail = new MailMessage();
|
||||||
|
$mail->subject("Coolify: [ACTION REQUIRED] Scheduled task ({$this->task->name}) failed.");
|
||||||
|
$mail->view('emails.scheduled-task-failed', [
|
||||||
|
'task' => $this->task,
|
||||||
|
'url' => $this->url,
|
||||||
|
'output' => $this->output,
|
||||||
|
]);
|
||||||
|
return $mail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toDiscord(): string
|
||||||
|
{
|
||||||
|
return "Coolify: Scheduled task ({$this->task->name}, [link]({$this->url})) failed with output: {$this->output}";
|
||||||
|
}
|
||||||
|
public function toTelegram(): array
|
||||||
|
{
|
||||||
|
$message = "Coolify: Scheduled task ({$this->task->name}) failed with output: {$this->output}";
|
||||||
|
if ($this->url) {
|
||||||
|
$buttons[] = [
|
||||||
|
"text" => "Open task in Coolify",
|
||||||
|
"url" => (string) $this->url
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
"message" => $message,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('teams', function (Blueprint $table) {
|
||||||
|
$table->boolean('telegram_notifications_scheduled_tasks')->default(true);
|
||||||
|
$table->boolean('smtp_notifications_scheduled_tasks')->default(false)->after('smtp_notifications_status_changes');
|
||||||
|
$table->boolean('discord_notifications_scheduled_tasks')->default(true)->after('discord_notifications_status_changes');
|
||||||
|
$table->text('telegram_notifications_scheduled_tasks_thread_id')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('teams', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('telegram_notifications_scheduled_tasks');
|
||||||
|
$table->dropColumn('smtp_notifications_scheduled_tasks');
|
||||||
|
$table->dropColumn('discord_notifications_scheduled_tasks');
|
||||||
|
$table->dropColumn('telegram_notifications_scheduled_tasks_thread_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
9
resources/views/emails/scheduled-task-failed.blade.php
Normal file
9
resources/views/emails/scheduled-task-failed.blade.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<x-emails.layout>
|
||||||
|
Scheduled task ({{ $task->name }}) was FAILED with the following error:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
{{ $output }}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
Click [here]({{ $url }}) to view the task.
|
||||||
|
</x-emails.layout>
|
@ -32,6 +32,8 @@
|
|||||||
label="Application Deployments" />
|
label="Application Deployments" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="team.discord_notifications_database_backups"
|
<x-forms.checkbox instantSave="saveModel" id="team.discord_notifications_database_backups"
|
||||||
label="Backup Status" />
|
label="Backup Status" />
|
||||||
|
<x-forms.checkbox instantSave="saveModel" id="team.discord_notifications_scheduled_tasks"
|
||||||
|
label="Scheduled Tasks Status" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -111,6 +111,8 @@
|
|||||||
label="Application Deployments" />
|
label="Application Deployments" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_database_backups"
|
<x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_database_backups"
|
||||||
label="Backup Status" />
|
label="Backup Status" />
|
||||||
|
<x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_scheduled_tasks"
|
||||||
|
label="Scheduled Tasks Status" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -60,6 +60,15 @@
|
|||||||
helper="If you are using Group chat with Topics, you can specify the topics ID. If empty, General topic will be used."
|
helper="If you are using Group chat with Topics, you can specify the topics ID. If empty, General topic will be used."
|
||||||
id="team.telegram_notifications_database_backups_message_thread_id" label="Custom Topic ID" />
|
id="team.telegram_notifications_database_backups_message_thread_id" label="Custom Topic ID" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<h4>Scheduled Tasks Status</h4>
|
||||||
|
<x-forms.checkbox instantSave="saveModel" id="team.telegram_notifications_scheduled_tasks"
|
||||||
|
label="Enabled" />
|
||||||
|
<x-forms.input
|
||||||
|
helper="If you are using Group chat with Topics, you can specify the topics ID. If empty, General topic will be used."
|
||||||
|
id="team.telegram_notifications_scheduled_tasks_thread_id" label="Custom Topic ID" />
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</form>
|
</form>
|
||||||
|
Loading…
Reference in New Issue
Block a user