fix: service navbar using new realtime events

This commit is contained in:
Andras Bacsai 2023-12-08 12:12:44 +01:00
parent 86c2415210
commit b55bd298f2
16 changed files with 107 additions and 33 deletions

View File

@ -39,7 +39,7 @@ public function __construct(CoolifyTaskArgs $remoteProcessArgs)
public function __invoke(): Activity
{
$job = new CoolifyTask($this->activity, ignore_errors: $this->remoteProcessArgs->ignore_errors);
$job = new CoolifyTask($this->activity, ignore_errors: $this->remoteProcessArgs->ignore_errors, call_event_on_finish: $this->remoteProcessArgs->call_event_on_finish);
dispatch($job);
$this->activity->refresh();
return $this->activity;

View File

@ -21,6 +21,8 @@ class RunRemoteProcess
public bool $ignore_errors;
public $call_event_on_finish = null;
protected $time_start;
protected $current_time;
@ -34,7 +36,7 @@ class RunRemoteProcess
/**
* Create a new job instance.
*/
public function __construct(Activity $activity, bool $hide_from_output = false, bool $is_finished = false, bool $ignore_errors = false)
public function __construct(Activity $activity, bool $hide_from_output = false, bool $is_finished = false, bool $ignore_errors = false, $call_event_on_finish = null)
{
if ($activity->getExtraProperty('type') !== ActivityTypes::INLINE->value) {
@ -45,6 +47,7 @@ public function __construct(Activity $activity, bool $hide_from_output = false,
$this->hide_from_output = $hide_from_output;
$this->is_finished = $is_finished;
$this->ignore_errors = $ignore_errors;
$this->call_event_on_finish = $call_event_on_finish;
}
public static function decodeOutput(?Activity $activity = null): string
@ -79,12 +82,18 @@ public function __invoke(): ProcessResult
if ($this->activity->properties->get('status') === ProcessStatus::ERROR->value) {
$status = ProcessStatus::ERROR;
} else {
if (($processResult->exitCode() == 0 && $this->is_finished) || $this->activity->properties->get('status') === ProcessStatus::FINISHED->value) {
if ($processResult->exitCode() == 0 && $this->is_finished) {
$status = ProcessStatus::FINISHED;
}
if ($processResult->exitCode() != 0 && !$this->ignore_errors) {
$status = ProcessStatus::ERROR;
}
// if (($processResult->exitCode() == 0 && $this->is_finished) || $this->activity->properties->get('status') === ProcessStatus::FINISHED->value) {
// $status = ProcessStatus::FINISHED;
// }
// if ($processResult->exitCode() != 0 && !$this->ignore_errors) {
// $status = ProcessStatus::ERROR;
// }
}
$this->activity->properties = $this->activity->properties->merge([
@ -97,7 +106,16 @@ public function __invoke(): ProcessResult
if ($processResult->exitCode() != 0 && !$this->ignore_errors) {
throw new \RuntimeException($processResult->errorOutput(), $processResult->exitCode());
}
if ($this->call_event_on_finish) {
try {
event(resolve("App\\Events\\$this->call_event_on_finish", [
'userId' => $this->activity->causer_id,
'typeUuid' => $this->activity->getExtraProperty('type_uuid'),
]));
} catch (\Throwable $e) {
ray($e);
}
}
return $processResult;
}

View File

@ -23,12 +23,12 @@ public function handle(Service $service)
$commands[] = "echo 'Starting containers.'";
$commands[] = "docker compose up -d --remove-orphans --force-recreate --build";
$commands[] = "docker network connect $service->uuid coolify-proxy >/dev/null 2>&1 || true";
$compose = data_get($service,'docker_compose',[]);
$serviceNames = data_get(Yaml::parse($compose),'services',[]);
foreach($serviceNames as $serviceName => $serviceConfig){
$compose = data_get($service, 'docker_compose', []);
$serviceNames = data_get(Yaml::parse($compose), 'services', []);
foreach ($serviceNames as $serviceName => $serviceConfig) {
$commands[] = "docker network connect --alias {$serviceName}-{$service->uuid} $network {$serviceName}-{$service->uuid} || true";
}
$activity = remote_process($commands, $service->server);
$activity = remote_process($commands, $service->server, type_uuid: $service->uuid, callEventOnFinish: 'ServiceStatusChanged');
return $activity;
}
}

View File

@ -19,6 +19,7 @@ public function __construct(
public ?Model $model = null,
public ?string $status = null ,
public bool $ignore_errors = false,
public $call_event_on_finish = null,
) {
if(is_null($status)){
$this->status = ProcessStatus::QUEUED->value;

View File

@ -0,0 +1,28 @@
<?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 ServiceStatusChanged implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $userId;
public function __construct($userId = null)
{
$this->userId = $userId;
}
public function broadcastOn(): array
{
return [
new PrivateChannel("custom.{$this->userId}"),
];
}
}

View File

@ -21,6 +21,7 @@ class CoolifyTask implements ShouldQueue, ShouldBeEncrypted
public function __construct(
public Activity $activity,
public bool $ignore_errors = false,
public $call_event_on_finish = null
) {
}
@ -32,6 +33,7 @@ public function handle(): void
$remote_process = resolve(RunRemoteProcess::class, [
'activity' => $this->activity,
'ignore_errors' => $this->ignore_errors,
'call_event_on_finish' => $this->call_event_on_finish
]);
$remote_process();

View File

@ -3,7 +3,6 @@
namespace App\Livewire\Modal;
use App\Models\Service;
use Livewire\Component;
use LivewireUI\Modal\ModalComponent;
class EditCompose extends ModalComponent

View File

@ -133,13 +133,13 @@ public function setServer(Server $server)
public function setDestination(string $destination_uuid)
{
$this->destination_uuid = $destination_uuid;
return $this->redirectRoute('project.resources.new', [
return redirect()->route('project.resources.new', [
'project_uuid' => $this->parameters['project_uuid'],
'environment_name' => $this->parameters['environment_name'],
'type' => $this->type,
'destination' => $this->destination_uuid,
'server_id' => $this->server_id,
], navigate: true);
]);
}
public function loadServers()

View File

@ -13,7 +13,15 @@ class Index extends Component
public $databases;
public array $parameters;
public array $query;
protected $listeners = ["refreshStacks", "checkStatus"];
public function getListeners()
{
$userId = auth()->user()->id;
return [
"echo-private:custom.{$userId},ServiceStatusChanged" => 'checkStatus',
"refreshStacks",
"checkStatus",
];
}
public function render()
{
return view('livewire.project.service.index');
@ -28,7 +36,7 @@ public function mount()
}
public function checkStatus()
{
dispatch(new ContainerStatusJob($this->service->server));
dispatch_sync(new ContainerStatusJob($this->service->server));
$this->refreshStacks();
}
public function refreshStacks()

View File

@ -6,9 +6,6 @@
class Modal extends Component
{
public function checkStatus() {
$this->dispatch('checkStatus');
}
public function render()
{
return view('livewire.project.service.modal');

View File

@ -4,25 +4,53 @@
use App\Actions\Service\StartService;
use App\Actions\Service\StopService;
use App\Jobs\ContainerStatusJob;
use App\Models\Service;
use Livewire\Component;
use Spatie\Activitylog\Models\Activity;
class Navbar extends Component
{
public Service $service;
public array $parameters;
public array $query;
protected $listeners = ["checkStatus"];
public $isDeploymentProgress = false;
public function checkDeployments() {
$activity = Activity::where('properties->type_uuid', $this->service->uuid)->latest()->first();
$status = data_get($activity, 'properties.status');
if ($status === 'queued' || $status === 'in_progress') {
$this->isDeploymentProgress = true;
} else {
$this->isDeploymentProgress = false;
}
}
public function getListeners()
{
$userId = auth()->user()->id;
return [
"echo-private:custom.{$userId},ServiceStatusChanged" => 'serviceStatusChanged',
];
}
public function serviceStatusChanged()
{
$this->service->refresh();
}
public function render()
{
return view('livewire.project.service.navbar');
}
public function checkStatus() {
public function checkStatus()
{
$this->service->refresh();
}
public function deploy()
{
$this->checkDeployments();
if ($this->isDeploymentProgress) {
$this->dispatch('error', 'There is a deployment in progress.');
return;
}
$this->service->parse();
$activity = StartService::run($this->service);
$this->dispatch('newMonitorActivity', $activity->id);

View File

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

View File

@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
use Symfony\Component\Yaml\Yaml;
use Illuminate\Support\Str;
class Service extends BaseModel
@ -207,7 +206,6 @@ public function extraFields()
break;
}
}
ray($fields);
$databases = $this->databases()->get();
foreach ($databases as $database) {

View File

@ -24,6 +24,7 @@ function remote_process(
?string $type_uuid = null,
?Model $model = null,
bool $ignore_errors = false,
$callEventOnFinish = null
): Activity {
if (is_null($type)) {
$type = ActivityTypes::INLINE->value;
@ -47,18 +48,12 @@ function remote_process(
type: $type,
type_uuid: $type_uuid,
model: $model,
ignore_errors: $ignore_errors
ignore_errors: $ignore_errors,
call_event_on_finish: $callEventOnFinish,
),
])();
}
// function removePrivateKeyFromSshAgent(Server $server)
// {
// if (data_get($server, 'privateKey.private_key') === null) {
// throw new \Exception("Server {$server->name} does not have a private key");
// }
// // processWithEnv()->run("echo '{$server->privateKey->private_key}' | ssh-add -d -");
// }
function savePrivateKeyToFs(Server $server)
{
if (data_get($server, 'privateKey.private_key') === null) {

View File

@ -1,5 +1,5 @@
<div>
<x-modal submitWireAction="checkStatus" modalId="startService">
<x-modal noSubmit modalId="startService">
<x-slot:modalBody>
<livewire:activity-monitor header="Service Startup Logs" />
</x-slot:modalBody>

View File

@ -48,7 +48,7 @@
if (auth()->user()?->currentTeam()->id !== 0) {
return redirect('/');
}
event(new \App\Events\TestEvent());
event(new \App\Events\TestEvent('asd'));
return 'Look at your other tab.';
})->middleware('auth');