wip: broadcast

This commit is contained in:
Andras Bacsai 2023-12-04 20:47:32 +01:00
parent 17deff4d86
commit 42ee4ca032
22 changed files with 142 additions and 103 deletions

View File

@ -4,3 +4,11 @@ APP_KEY=
DB_PASSWORD=
REDIS_PASSWORD=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"

View File

@ -1,6 +1,6 @@
<?php
namespace App\Providers;
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
@ -14,14 +14,25 @@ class ApplicationDeploymentFinished implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct()
public ?int $teamId = null;
/**
* Create a new event instance.
*/
public function __construct(public ?string $applicationUuid = null, public ?string $status = null)
{
$this->teamId = auth()->user()->currentTeam()->id;
}
/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new Channel('custom-channel'),
new PrivateChannel("custom.{$this->teamId}"),
];
}
}

View File

@ -10,7 +10,6 @@ class Dashboard extends Component
{
public $projects = [];
public $servers = [];
public function mount()
{
$this->servers = Server::ownedByCurrentTeam()->get();

View File

@ -26,7 +26,7 @@ public function mount()
return redirect()->route('dashboard');
}
$this->application = $application;
$mainServer = $application->destination->server;
$mainServer = $this->application->destination->server;
$servers = Server::ownedByCurrentTeam()->get();
$this->servers = $servers->filter(function ($server) use ($mainServer) {
return $server->id != $mainServer->id;

View File

@ -17,11 +17,7 @@ class DeploymentNavbar extends Component
public Application $application;
public Server $server;
public bool $is_debug_enabled = false;
protected $listeners = ['deploymentFinished','echo:custom-channel,ApplicationDeploymentFinished' => 'notifyNewOrder'];
public function notifyNewOrder() {
ray('New order received');
}
protected $listeners = ['deploymentFinished'];
public function mount()
{
$this->application = Application::find($this->application_deployment_queue->application_id);

View File

@ -11,11 +11,24 @@
class Heading extends Component
{
protected string $deploymentUuid;
public Application $application;
public array $parameters;
public function getListeners()
{
$teamId = auth()->user()->currentTeam()->id;
return [
"echo-private:custom.{$teamId},ApplicationDeploymentFinished" => 'updateStatus',
];
}
protected string $deploymentUuid;
public function updateStatus($message)
{
$applicationUuid = data_get($message, 'applicationUuid');
if ($this->application->uuid === $applicationUuid) {
$this->application->status = data_get($message, 'status');
}
}
public function mount()
{
$this->parameters = get_route_parameters();

View File

@ -44,6 +44,7 @@ public function mount()
{
$this->wildcard_domain = $this->server->settings->wildcard_domain;
$this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage;
$this->validateServer();
}
public function serverRefresh($install = true)
{

View File

@ -4,6 +4,7 @@
use App\Enums\ApplicationDeploymentStatus;
use App\Enums\ProxyTypes;
use App\Events\ApplicationDeploymentFinished;
use App\Models\Application;
use App\Models\ApplicationDeploymentQueue;
use App\Models\ApplicationPreview;
@ -14,7 +15,6 @@
use App\Models\SwarmDocker;
use App\Notifications\Application\DeploymentFailed;
use App\Notifications\Application\DeploymentSuccess;
use App\Providers\ApplicationDeploymentFinished;
use App\Traits\ExecuteRemoteCommand;
use Exception;
use Illuminate\Bus\Queueable;
@ -102,7 +102,7 @@ public function handle()
});
}
$this->next(ApplicationDeploymentStatus::FINISHED->value);
ApplicationDeploymentFinished::dispatch($this->application, $this->deployment);
ApplicationDeploymentFinished::dispatch($this->application->uuid, ApplicationDeploymentStatus::FINISHED->value);
} catch (Throwable $exception) {
$this->fail($exception);
} finally {

View File

@ -382,17 +382,17 @@ public function isSwarm()
public function validateConnection()
{
$server = Server::find($this->id);
if ($this->skipServer()) {
if ($server->skipServer()) {
return false;
}
$uptime = instant_remote_process(['uptime'], $this, false);
$uptime = instant_remote_process(['uptime'], $server, false);
if (!$uptime) {
$this->settings()->update([
$server->settings()->update([
'is_reachable' => false,
]);
return false;
} else {
$this->settings()->update([
$server->settings()->update([
'is_reachable' => true,
]);
$server->update([
@ -400,8 +400,8 @@ public function validateConnection()
]);
}
if (data_get($this, 'unreachable_notification_sent') === true) {
$this->team->notify(new Revived($this));
if (data_get($server, 'unreachable_notification_sent') === true) {
$server->team->notify(new Revived($server));
$server->update(['unreachable_notification_sent' => false]);
}

View File

@ -8,31 +8,15 @@
class EventServiceProvider extends ServiceProvider
{
/**
* The event to listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
// Registered::class => [
// SendEmailVerificationNotification::class,
// ],
ApplicationDeploymentFinished::class => [
SendDeploymentNotification::class,
],
];
/**
* Register any events for your application.
*/
public function boot(): void
{
//
}
/**
* Determine if events and listeners should be automatically discovered.
*/
public function shouldDiscoverEvents(): bool
{
return false;

View File

@ -1,28 +0,0 @@
<?php
namespace App\Providers;
use App\Providers\ApplicationDeploymentFinished;
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SendDeploymentNotification implements ShouldQueue, ShouldHandleEventsAfterCommit
{
use InteractsWithQueue;
/**
* Create the event listener.
*/
public function __construct()
{
//
}
/**
* Handle the event.
*/
public function handle(ApplicationDeploymentFinished $event): void
{
ray('SendDeploymentNotification');
}
}

View File

@ -28,6 +28,7 @@
"nubs/random-name-generator": "^2.2",
"phpseclib/phpseclib": "~3.0",
"poliander/cron": "^3.0",
"pusher/pusher-php-server": "^7.2",
"resend/resend-laravel": "^0.5.0",
"sentry/sentry-laravel": "^3.4",
"spatie/laravel-activitylog": "^4.7.3",

View File

@ -194,7 +194,7 @@
App\Providers\AppServiceProvider::class,
App\Providers\FortifyServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\HorizonServiceProvider::class,
App\Providers\RouteServiceProvider::class,

View File

@ -15,7 +15,7 @@
|
*/
'default' => env('BROADCAST_DRIVER', 'log'),
'default' => env('BROADCAST_DRIVER', 'pusher'),
/*
|--------------------------------------------------------------------------
@ -32,9 +32,9 @@
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'key' => env('PUSHER_APP_KEY', 'coolify'),
'secret' => env('PUSHER_APP_SECRET', 'coolify'),
'app_id' => env('PUSHER_APP_ID', 'coolify'),
'options' => [
'host' => 'coolify-soketi',
'port' => env('PUSHER_PORT', 6001),

View File

@ -13,11 +13,11 @@ class StandaloneDockerSeeder extends Seeder
*/
public function run(): void
{
// StandaloneDocker::create([
// 'id' => 0,
// 'name' => 'Standalone Docker 1',
// 'network' => 'coolify',
// 'server_id' => 0,
// ]);
StandaloneDocker::create([
'id' => 0,
'name' => 'Standalone Docker 1',
'network' => 'coolify',
'server_id' => 0,
]);
}
}

View File

@ -21,6 +21,10 @@ services:
SSL_MODE: "off"
AUTORUN_LARAVEL_STORAGE_LINK: "false"
AUTORUN_LARAVEL_MIGRATION: "false"
PUSHER_HOST: "${PUSHER_HOST:-127.0.0.1}"
PUSHER_APP_ID: "${PUSHER_APP_ID:-coolify}"
PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}"
PUSHER_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}"
volumes:
- .:/var/www/html/:cached
postgres:
@ -45,15 +49,22 @@ services:
- /data/coolify/_volumes/redis/:/data
# - coolify-redis-data-dev:/data
soketi:
env_file:
- .env
ports:
- "${FORWARD_SOKETI_PORT:-6001}:6001"
- "${FORWARD_SOKETI_METRICS_SERVER_PORT:-9601}:9601"
environment:
SOKETI_DEBUG: "true"
SOKETI_METRICS_SERVER_PORT: "${SOKETI_METRICS_SERVER_PORT:-9601}"
SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}"
SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}"
SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}"
vite:
image: node:20
working_dir: /var/www/html
environment:
VITE_PUSHER_HOST: "${PUSHER_HOST:-127.0.0.1}"
VITE_PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}"
VITE_PUSHER_PORT: "${FORWARD_SOKETI_PORT:-6001}"
ports:
- "${VITE_PORT:-5173}:${VITE_PORT:-5173}"
volumes:
@ -67,14 +78,14 @@ services:
- /var/run/docker.sock:/var/run/docker.sock
- /data/coolify/:/data/coolify
# - coolify-data-dev:/data/coolify
remote-host:
<<: *testing-host-base
container_name: coolify-remote-host
volumes:
- /:/host
- /var/run/docker.sock:/var/run/docker.sock
- /data/coolify/:/data/coolify
# - coolify-data-dev:/data/coolify
# remote-host:
# <<: *testing-host-base
# container_name: coolify-remote-host
# volumes:
# - /:/host
# - /var/run/docker.sock:/var/run/docker.sock
# - /data/coolify/:/data/coolify
# # - coolify-data-dev:/data/coolify
mailpit:
image: "axllent/mailpit:latest"
container_name: coolify-mail

View File

@ -1,7 +1,7 @@
version: '3.8'
services:
coolify:
image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-4.0.0-beta.20}"
image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-4.0.0-beta.153}"
volumes:
- type: bind
source: /data/coolify/source/.env
@ -35,6 +35,13 @@ services:
- PHP_PM_START_SERVERS=1
- PHP_PM_MIN_SPARE_SERVERS=1
- PHP_PM_MAX_SPARE_SERVERS=10
- PUSHER_HOST
- PUSHER_APP_ID
- PUSHER_APP_KEY
- PUSHER_APP_SECRET
- VITE_PUSHER_HOST
- VITE_PUSHER_APP_KEY
- VITE_PUSHER_PORT
- SELF_HOSTED
- WAITLIST
- SUBSCRIPTION_PROVIDER
@ -111,6 +118,12 @@ services:
interval: 2s
retries: 5
timeout: 2s
soketi:
environment:
SOKETI_DEBUG: "${SOKETI_DEBUG:-false}"
SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID}"
SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY}"
SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET}"
volumes:
coolify-db:
name: coolify-db

View File

@ -9,14 +9,15 @@ window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
cluster: import.meta.env.VITE_PUSHER_HOST,
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST,
cluster: import.meta.env.VITE_PUSHER_HOST ?? '127.0.0.1',
key: import.meta.env.VITE_PUSHER_APP_KEY ?? 'coolify',
wsHost: import.meta.env.VITE_PUSHER_HOST ?? '127.0.0.1',
wsPort: import.meta.env.VITE_PUSHER_PORT,
wssPort: import.meta.env.VITE_PUSHER_PORT,
forceTLS: false,
encrypted: false,
disableStats: true,
encrypted: true,
disableStats: false,
enableLogging: true,
enabledTransports: ['ws', 'wss'],
});
@ -30,6 +31,4 @@ app.component("magic-bar", MagicBar);
app.mount("#vue");
window.Echo.channel("custom-channel").listen("ApplicationDeploymentFinished", (e) => {
console.log(e);
});

View File

@ -1,4 +1,4 @@
<nav x-init="$wire.check_status" wire:poll.10000ms="check_status">
<nav x-init="$wire.check_status">
<x-resources.breadcrumbs :resource="$application" :parameters="$parameters" />
<x-applications.navbar :application="$application" :parameters="$parameters" />
</nav>

View File

@ -11,6 +11,13 @@
|
*/
// Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
// return (int) $user->id === (int) $id;
// });
use App\Models\Application;
use App\Models\User;
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('custom.{teamId}', function (User $user, int $teamId) {
if ($user->teams->pluck('id')->contains($teamId)) {
return true;
}
return false;
});

View File

@ -1,5 +1,6 @@
<?php
use App\Events\ApplicationDeploymentFinished;
use App\Http\Controllers\ApplicationController;
use App\Http\Controllers\Controller;
use App\Http\Controllers\DatabaseController;
@ -39,6 +40,11 @@
use Laravel\Fortify\Contracts\SuccessfulPasswordResetLinkRequestResponse;
use Laravel\Fortify\Fortify;
Route::get('/fire', function () {
ApplicationDeploymentFinished::dispatch('kk0gg0s', 'stopped');
return 'Event has been sent!';
});
if (isDev()) {
Route::get('/dev/compose', Compose::class)->name('dev.compose');
}

View File

@ -1,11 +1,7 @@
#!/bin/bash
## Do not modify this file. You will lost the ability to autoupdate!
###########
## Always run "php artisan app:sync-to-bunny-cdn --env=secrets" if you update this file.
###########
VERSION="1.0.1"
VERSION="1.1.0"
CDN="https://cdn.coollabs.io/coolify"
curl -fsSL $CDN/docker-compose.yml -o /data/coolify/source/docker-compose.yml
@ -15,6 +11,28 @@ curl -fsSL $CDN/.env.production -o /data/coolify/source/.env.production
# Merge .env and .env.production. New values will be added to .env
sort -u -t '=' -k 1,1 /data/coolify/source/.env /data/coolify/source/.env.production | sed '/^$/d' > /data/coolify/source/.env.temp && mv /data/coolify/source/.env.temp /data/coolify/source/.env
# Check if PUSHER_APP_ID or PUSHER_APP_KEY or PUSHER_APP_SECRET is empty in /data/coolify/source/.env
if grep -q "PUSHER_APP_ID=" /data/coolify/source/.env; then
echo "PUSHER_APP_ID is set in .env"
else
echo "PUSHER_APP_ID is not set in .env"
sed -i "s|PUSHER_APP_ID=.*|PUSHER_APP_ID=$(openssl rand -base64 32)|g" /data/coolify/source/.env
fi
if grep -q "PUSHER_APP_KEY=" /data/coolify/source/.env; then
echo "PUSHER_APP_KEY is set in .env"
else
echo "PUSHER_APP_KEY is not set in .env"
sed -i "s|PUSHER_APP_KEY=.*|PUSHER_APP_KEY=$(openssl rand -base64 32)|g" /data/coolify/source/.env
fi
if grep -q "PUSHER_APP_SECRET=" /data/coolify/source/.env; then
echo "PUSHER_APP_SECRET is set in .env"
else
echo "PUSHER_APP_SECRET is not set in .env"
sed -i "s|PUSHER_APP_SECRET=.*|PUSHER_APP_SECRET=$(openssl rand -base64 32)|g" /data/coolify/source/.env
fi
# Make sure coolify network exists
docker network create --attachable coolify 2>/dev/null
# docker network create --attachable --driver=overlay coolify-overlay 2>/dev/null