2023-09-20 13:42:41 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
2023-12-13 11:08:12 +00:00
|
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
2023-09-20 13:42:41 +00:00
|
|
|
|
|
|
|
|
class ServiceDatabase extends BaseModel
|
|
|
|
|
{
|
2023-12-13 11:08:12 +00:00
|
|
|
use HasFactory, SoftDeletes;
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-09-20 13:42:41 +00:00
|
|
|
protected $guarded = [];
|
|
|
|
|
|
2023-11-06 17:04:18 +00:00
|
|
|
protected static function booted()
|
|
|
|
|
{
|
|
|
|
|
static::deleting(function ($service) {
|
|
|
|
|
$service->persistentStorages()->delete();
|
|
|
|
|
$service->fileStorages()->delete();
|
2025-05-05 07:04:09 +00:00
|
|
|
$service->scheduledBackups()->delete();
|
2023-11-06 17:04:18 +00:00
|
|
|
});
|
2024-11-03 08:02:14 +00:00
|
|
|
static::saving(function ($service) {
|
|
|
|
|
if ($service->isDirty('status')) {
|
|
|
|
|
$service->forceFill(['last_online_at' => now()]);
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-11-06 17:04:18 +00:00
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2024-11-07 10:09:38 +00:00
|
|
|
public static function ownedByCurrentTeamAPI(int $teamId)
|
|
|
|
|
{
|
2025-01-07 14:31:43 +00:00
|
|
|
return ServiceDatabase::whereRelation('service.environment.project.team', 'id', $teamId)->orderBy('name');
|
2024-11-07 10:09:38 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-08 12:39:33 +00:00
|
|
|
/**
|
|
|
|
|
* Get query builder for service databases owned by current team.
|
|
|
|
|
* If you need all service databases without further query chaining, use ownedByCurrentTeamCached() instead.
|
|
|
|
|
*/
|
2024-11-07 10:09:38 +00:00
|
|
|
public static function ownedByCurrentTeam()
|
|
|
|
|
{
|
2025-01-07 14:31:43 +00:00
|
|
|
return ServiceDatabase::whereRelation('service.environment.project.team', 'id', currentTeam()->id)->orderBy('name');
|
2024-11-07 10:09:38 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-08 12:39:33 +00:00
|
|
|
/**
|
|
|
|
|
* Get all service databases owned by current team (cached for request duration).
|
|
|
|
|
*/
|
|
|
|
|
public static function ownedByCurrentTeamCached()
|
|
|
|
|
{
|
|
|
|
|
return once(function () {
|
|
|
|
|
return ServiceDatabase::ownedByCurrentTeam()->get();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-25 10:33:38 +00:00
|
|
|
public function restart()
|
|
|
|
|
{
|
2024-09-23 17:51:31 +00:00
|
|
|
$container_id = $this->name.'-'.$this->service->uuid;
|
2024-03-25 10:33:38 +00:00
|
|
|
remote_process(["docker restart {$container_id}"], $this->service->server);
|
|
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2024-09-16 13:35:44 +00:00
|
|
|
public function isRunning()
|
|
|
|
|
{
|
|
|
|
|
return str($this->status)->contains('running');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function isExited()
|
|
|
|
|
{
|
|
|
|
|
return str($this->status)->contains('exited');
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-04 10:01:14 +00:00
|
|
|
public function isLogDrainEnabled()
|
2023-11-17 19:08:21 +00:00
|
|
|
{
|
|
|
|
|
return data_get($this, 'is_log_drain_enabled', false);
|
|
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2024-03-04 10:01:14 +00:00
|
|
|
public function isStripprefixEnabled()
|
2024-02-15 19:44:01 +00:00
|
|
|
{
|
2024-03-04 10:01:14 +00:00
|
|
|
return data_get($this, 'is_stripprefix_enabled', true);
|
|
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2024-03-04 10:01:14 +00:00
|
|
|
public function isGzipEnabled()
|
|
|
|
|
{
|
|
|
|
|
return data_get($this, 'is_gzip_enabled', true);
|
2024-02-15 19:44:01 +00:00
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-09-22 09:23:49 +00:00
|
|
|
public function type()
|
|
|
|
|
{
|
|
|
|
|
return 'service';
|
|
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-11-13 14:19:49 +00:00
|
|
|
public function serviceType()
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-11-07 11:11:47 +00:00
|
|
|
public function databaseType()
|
|
|
|
|
{
|
2025-05-05 07:04:09 +00:00
|
|
|
if (filled($this->custom_type)) {
|
|
|
|
|
return 'standalone-'.$this->custom_type;
|
|
|
|
|
}
|
2023-11-07 11:11:47 +00:00
|
|
|
$image = str($this->image)->before(':');
|
2025-03-10 14:47:59 +00:00
|
|
|
if ($image->contains('supabase/postgres')) {
|
|
|
|
|
$finalImage = 'supabase/postgres';
|
2025-11-11 23:36:38 +00:00
|
|
|
} elseif ($image->contains('timescale')) {
|
|
|
|
|
$finalImage = 'postgresql';
|
|
|
|
|
} elseif ($image->contains('pgvector')) {
|
|
|
|
|
$finalImage = 'postgresql';
|
2025-03-10 14:47:59 +00:00
|
|
|
} elseif ($image->contains('postgres') || $image->contains('postgis')) {
|
|
|
|
|
$finalImage = 'postgresql';
|
|
|
|
|
} else {
|
|
|
|
|
$finalImage = $image;
|
2023-11-07 11:11:47 +00:00
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2025-03-10 14:47:59 +00:00
|
|
|
return "standalone-$finalImage";
|
2023-11-07 11:11:47 +00:00
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-11-13 14:19:49 +00:00
|
|
|
public function getServiceDatabaseUrl()
|
|
|
|
|
{
|
2023-11-09 13:59:38 +00:00
|
|
|
$port = $this->public_port;
|
2023-11-09 14:05:42 +00:00
|
|
|
$realIp = $this->service->server->ip;
|
2023-11-16 13:29:01 +00:00
|
|
|
if ($this->service->server->isLocalhost() || isDev()) {
|
2023-11-09 14:05:42 +00:00
|
|
|
$realIp = base_ip();
|
|
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2024-03-25 11:13:43 +00:00
|
|
|
return "{$realIp}:{$port}";
|
2023-11-09 13:59:38 +00:00
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2024-05-28 12:49:03 +00:00
|
|
|
public function team()
|
|
|
|
|
{
|
2026-02-23 12:23:12 +00:00
|
|
|
return data_get($this, 'service.environment.project.team');
|
2024-05-28 12:49:03 +00:00
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
|
|
|
|
public function workdir()
|
|
|
|
|
{
|
2024-09-23 17:51:31 +00:00
|
|
|
return service_configuration_dir()."/{$this->service->uuid}";
|
2024-05-24 15:26:05 +00:00
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-09-22 10:08:51 +00:00
|
|
|
public function service()
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsTo(Service::class);
|
|
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-09-22 09:23:49 +00:00
|
|
|
public function persistentStorages()
|
|
|
|
|
{
|
|
|
|
|
return $this->morphMany(LocalPersistentVolume::class, 'resource');
|
|
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-09-25 10:49:55 +00:00
|
|
|
public function fileStorages()
|
|
|
|
|
{
|
|
|
|
|
return $this->morphMany(LocalFileVolume::class, 'resource');
|
|
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-10-02 16:02:32 +00:00
|
|
|
public function getFilesFromServer(bool $isInit = false)
|
2023-09-25 10:49:55 +00:00
|
|
|
{
|
2023-10-02 16:02:32 +00:00
|
|
|
getFilesystemVolumesFromServer($this, $isInit);
|
2023-09-25 10:49:55 +00:00
|
|
|
}
|
2024-06-10 20:43:34 +00:00
|
|
|
|
2023-11-07 11:11:47 +00:00
|
|
|
public function scheduledBackups()
|
|
|
|
|
{
|
|
|
|
|
return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
|
|
|
|
|
}
|
2024-10-03 08:48:25 +00:00
|
|
|
|
|
|
|
|
public function isBackupSolutionAvailable()
|
|
|
|
|
{
|
2025-01-07 14:31:43 +00:00
|
|
|
return str($this->databaseType())->contains('mysql') ||
|
|
|
|
|
str($this->databaseType())->contains('postgres') ||
|
|
|
|
|
str($this->databaseType())->contains('postgis') ||
|
|
|
|
|
str($this->databaseType())->contains('mariadb') ||
|
2025-05-05 07:04:09 +00:00
|
|
|
str($this->databaseType())->contains('mongo') ||
|
|
|
|
|
filled($this->custom_type);
|
2024-10-03 08:48:25 +00:00
|
|
|
}
|
2023-09-20 13:42:41 +00:00
|
|
|
}
|