fix: channels

feat: database backup is realtime now
This commit is contained in:
Andras Bacsai 2023-12-11 10:23:10 +01:00
parent 63dff5961e
commit 3ffd3fc819
15 changed files with 81 additions and 26 deletions

View File

@ -0,0 +1,34 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class BackupCreated implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $teamId;
public function __construct($teamId = null)
{
if (is_null($teamId)) {
$teamId = auth()->user()->currentTeam()->id ?? null;
}
if (is_null($teamId)) {
throw new \Exception("Team id is null");
}
$this->teamId = $teamId;
}
public function broadcastOn(): array
{
return [
new PrivateChannel("team.{$this->teamId}"),
];
}
}

View File

@ -28,7 +28,7 @@ class DatabaseStatusChanged implements ShouldBroadcast
public function broadcastOn(): array public function broadcastOn(): array
{ {
return [ return [
new PrivateChannel("custom.{$this->userId}"), new PrivateChannel("user.{$this->userId}"),
]; ];
} }
} }

View File

@ -28,7 +28,7 @@ class ServiceStatusChanged implements ShouldBroadcast
public function broadcastOn(): array public function broadcastOn(): array
{ {
return [ return [
new PrivateChannel("custom.{$this->userId}"), new PrivateChannel("user.{$this->userId}"),
]; ];
} }
} }

View File

@ -22,7 +22,7 @@ class TestEvent implements ShouldBroadcast
public function broadcastOn(): array public function broadcastOn(): array
{ {
return [ return [
new PrivateChannel("custom.{$this->teamId}"), new PrivateChannel("team.{$this->teamId}"),
]; ];
} }
} }

View File

@ -79,6 +79,10 @@ class Controller extends BaseController
if (isInstanceAdmin()) { if (isInstanceAdmin()) {
$settings = InstanceSettings::get(); $settings = InstanceSettings::get();
$database = StandalonePostgresql::whereName('coolify-db')->first(); $database = StandalonePostgresql::whereName('coolify-db')->first();
if ($database->status !== 'running') {
$database->status = 'running';
$database->save();
}
if ($database) { if ($database) {
$s3s = S3Storage::whereTeamId(0)->get(); $s3s = S3Storage::whereTeamId(0)->get();
} }

View File

@ -3,6 +3,7 @@
namespace App\Jobs; namespace App\Jobs;
use App\Actions\Database\StopDatabase; use App\Actions\Database\StopDatabase;
use App\Events\BackupCreated;
use App\Models\S3Storage; use App\Models\S3Storage;
use App\Models\ScheduledDatabaseBackup; use App\Models\ScheduledDatabaseBackup;
use App\Models\ScheduledDatabaseBackupExecution; use App\Models\ScheduledDatabaseBackupExecution;
@ -74,6 +75,7 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
public function handle(): void public function handle(): void
{ {
try { try {
BackupCreated::dispatch($this->team->id);
// Check if team is exists // Check if team is exists
if (is_null($this->team)) { if (is_null($this->team)) {
$this->backup->update(['status' => 'failed']); $this->backup->update(['status' => 'failed']);
@ -307,6 +309,8 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
} catch (\Throwable $e) { } catch (\Throwable $e) {
send_internal_notification('DatabaseBackupJob failed with: ' . $e->getMessage()); send_internal_notification('DatabaseBackupJob failed with: ' . $e->getMessage());
throw $e; throw $e;
} finally {
BackupCreated::dispatch($this->team->id);
} }
} }
private function backup_standalone_mongodb(string $databaseWithCollections): void private function backup_standalone_mongodb(string $databaseWithCollections): void

View File

@ -10,7 +10,15 @@ class BackupExecutions extends Component
public $backup; public $backup;
public $executions; public $executions;
public $setDeletableBackup; public $setDeletableBackup;
protected $listeners = ['refreshBackupExecutions', 'deleteBackup']; public function getListeners()
{
$userId = auth()->user()->id;
return [
"echo-private:team.{$userId},BackupCreated" => 'refreshBackupExecutions',
"refreshBackupExecutions",
"deleteBackup"
];
}
public function deleteBackup($exeuctionId) public function deleteBackup($exeuctionId)
{ {

View File

@ -21,7 +21,7 @@ class Heading extends Component
{ {
$userId = auth()->user()->id; $userId = auth()->user()->id;
return [ return [
"echo-private:custom.{$userId},DatabaseStatusChanged" => 'activityFinished', "echo-private:user.{$userId},DatabaseStatusChanged" => 'activityFinished',
]; ];
} }

View File

@ -17,7 +17,7 @@ class Index extends Component
{ {
$userId = auth()->user()->id; $userId = auth()->user()->id;
return [ return [
"echo-private:custom.{$userId},ServiceStatusChanged" => 'checkStatus', "echo-private:user.{$userId},ServiceStatusChanged" => 'checkStatus',
"refreshStacks", "refreshStacks",
"checkStatus", "checkStatus",
]; ];

View File

@ -8,12 +8,12 @@ class Sponsorship extends Component
{ {
public function getListeners() public function getListeners()
{ {
$userId = auth()->user()->id; $teamId = auth()->user()->currentTeam()->id;
return [ return [
"echo-private:custom.{$userId},TestEvent" => 'testEvent', "echo-private:team.{$teamId},TestEvent" => 'testEvent',
]; ];
} }
public function testEvent($asd) public function testEvent()
{ {
$this->dispatch('success', 'Realtime events configured!'); $this->dispatch('success', 'Realtime events configured!');
} }

View File

@ -22,9 +22,9 @@
if (window.Echo) { if (window.Echo) {
if (window.Echo.connector.pusher.connection.state !== 'connected') { if (window.Echo.connector.pusher.connection.state !== 'connected') {
checkNumber++; checkNumber++;
if (checkNumber > 5) { if (checkNumber > 2) {
clearInterval(checkPusherInterval); clearInterval(checkPusherInterval);
Livewire.emit('error', errorMessage); window.Livewire.dispatch('error', errorMessage);
} }
} else { } else {
console.log('Coolify is now connected to the new realtime service introduced in beta.154.'); console.log('Coolify is now connected to the new realtime service introduced in beta.154.');
@ -32,7 +32,7 @@
} }
} else { } else {
clearInterval(checkPusherInterval); clearInterval(checkPusherInterval);
Livewire.emit('error', errorMessage); window.Livewire.dispatch('error', errorMessage);
} }
}, 2000); }, 2000);
} }

View File

@ -121,7 +121,7 @@
} }
function copyToClipboard(text) { function copyToClipboard(text) {
navigator?.clipboard?.writeText(text) && window.Livewire.emit('success', 'Copied to clipboard.'); navigator?.clipboard?.writeText(text) && window.Livewire.dispatch('success', 'Copied to clipboard.');
} }
document.addEventListener('livewire:init', () => { document.addEventListener('livewire:init', () => {
window.Livewire.on('reloadWindow', (timeout) => { window.Livewire.on('reloadWindow', (timeout) => {

View File

@ -1,10 +1,15 @@
<div class="flex flex-col-reverse gap-2"> <div class="flex flex-col-reverse gap-2">
@forelse($executions as $execution) @forelse($executions as $execution)
<form wire:key="{{ data_get($execution, 'id') }}" class="flex flex-col p-2 border-dotted border-1 bg-coolgray-300" <form wire:key="{{ data_get($execution, 'id') }}" class="relative flex flex-col p-4 border-dotted border-1 bg-coolgray-100"
@class([ @class([
'border-green-500' => data_get($execution, 'status') === 'success', 'border-green-500' => data_get($execution, 'status') === 'success',
'border-red-500' => data_get($execution, 'status') === 'failed', 'border-red-500' => data_get($execution, 'status') === 'failed',
])> ])>
@if (data_get($execution, 'status') === 'running')
<div class="absolute top-2 right-2">
<x-loading />
</div>
@endif
<div>Database: {{ data_get($execution, 'database_name', 'N/A') }}</div> <div>Database: {{ data_get($execution, 'database_name', 'N/A') }}</div>
<div>Status: {{ data_get($execution, 'status') }}</div> <div>Status: {{ data_get($execution, 'status') }}</div>
<div>Started At: {{ data_get($execution, 'created_at') }}</div> <div>Started At: {{ data_get($execution, 'created_at') }}</div>
@ -21,18 +26,11 @@
<x-forms.button class=" hover:bg-coolgray-400" <x-forms.button class=" hover:bg-coolgray-400"
wire:click="download({{ data_get($execution, 'id') }})">Download</x-forms.button> wire:click="download({{ data_get($execution, 'id') }})">Download</x-forms.button>
@endif @endif
<x-forms.button isError onclick="sure({{ data_get($execution, 'id') }})">Delete</x-forms.button> <x-forms.button isError wire:click="deleteBackup({{ data_get($execution, 'id') }})"
wire:confirm.prompt="Are you sure?\n\nType DELETE to confirm|DELETE">Delete</x-forms.button>
</div> </div>
</form> </form>
@empty @empty
<div>No executions found.</div> <div>No executions found.</div>
@endforelse @endforelse
<script>
function sure($id) {
const sure = confirm('Are you sure you want to delete this backup?');
if (sure) {
Livewire.emit('deleteBackup', $id);
}
}
</script>
</div> </div>

View File

@ -45,11 +45,11 @@
@endif @endif
<script> <script>
function checkProxy() { function checkProxy() {
Livewire.emit('checkProxy') window.Livewire.dispatch('checkProxy')
} }
Livewire.on('proxyChecked', () => { Livewire.on('proxyChecked', () => {
startProxy.showModal(); startProxy.showModal();
Livewire.emit('startProxy'); window.Livewire.dispatch('startProxy');
}) })
</script> </script>
</div> </div>

View File

@ -15,9 +15,16 @@ use App\Models\Application;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\Broadcast; use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('custom.{teamId}', function (User $user, int $teamId) { Broadcast::channel('team.{teamId}', function (User $user, int $teamId) {
if ($user->teams->pluck('id')->contains($teamId)) { if ($user->teams->pluck('id')->contains($teamId)) {
return true; return true;
} }
return false; return false;
}); });
Broadcast::channel('user.{userId}', function (User $user) {
if ($user->id === auth()->user()->id) {
return true;
}
return false;
});