Files
coolify/app/Jobs/ConfigureDnsRecordJob.php
T
Andras Bacsai 9e7cb60b0d feat: add import restore options, OAuth confirmation, and fixes
- database import: add keep_owners (restore PostgreSQL owners and
  privileges) and sqlite_database (pick the target SQLite file) to the
  API, OpenAPI spec, and import form
- oauth: require password confirmation and support team selection on
  OAuth login
- remote process: send team broadcast events to the team of the server
  that ran the process instead of the causer's user id
- servers API: handle the legacy build server setting
- compose: support parent bind paths and volume driver options
- dns: improve record hints and provider management
- notifications: fix throttling and missing backup notifications
- ui: rework the confirmation modal
- add feature and unit tests for the new behavior
2026-09-30 13:35:22 +02:00

108 lines
3.2 KiB
PHP

<?php
namespace App\Jobs;
use App\Events\DnsRecordConfigurationFinished;
use App\Models\DnsProviderZone;
use App\Services\Dns\CloudflareDnsProvider;
use App\Support\DnsRecordHints;
use Illuminate\Contracts\Cache\LockTimeoutException;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Queue\SerializesModels;
use Throwable;
class ConfigureDnsRecordJob implements ShouldQueue
{
use Queueable, SerializesModels;
/** Only a busy hostname lock is retried; any other exception fails the job at once. */
public int $tries = 3;
public int $maxExceptions = 1;
public int $timeout = 30;
public function __construct(
public int $teamId,
public int $zoneId,
public ?string $resourceType,
public int|string|null $resourceId,
public string $hostname,
public string $content,
) {}
public function handle(CloudflareDnsProvider $provider): void
{
$zone = DnsProviderZone::query()
->with('integrationToken')
->whereKey($this->zoneId)
->whereHas('integrationToken', fn ($query) => $query->where('team_id', $this->teamId))
->firstOrFail();
if (! DnsRecordHints::isPublicAddress($this->content)) {
$this->finished($zone, false, DnsRecordHints::NO_PUBLIC_ADDRESS_MESSAGE);
return;
}
try {
$provider->createRecord($zone, $this->hostname, $this->content, $this->resource());
} catch (LockTimeoutException) {
if ($this->attempts() < $this->tries) {
$this->release(10 * $this->attempts());
return;
}
$this->finished($zone, false, 'Another DNS change for this hostname is still in progress. Try again later.');
return;
} catch (Throwable $exception) {
$this->finished($zone, false, $exception->getMessage());
return;
}
$this->finished($zone, true, "DNS record added for {$this->hostname}.");
}
private function finished(DnsProviderZone $zone, bool $successful, string $message): void
{
DnsRecordConfigurationFinished::dispatch(
$this->teamId,
$this->resourceType,
$this->resourceId,
$this->hostname,
$successful,
$zone->integrationToken->name,
$message,
);
}
public function failed(?Throwable $exception): void
{
DnsRecordConfigurationFinished::dispatch(
$this->teamId,
$this->resourceType,
$this->resourceId,
$this->hostname,
false,
'',
'The DNS zone is no longer available.',
);
}
private function resource(): ?Model
{
$resourceClass = $this->resourceType === null ? null : (Relation::getMorphedModel($this->resourceType) ?? $this->resourceType);
if ($resourceClass === null || $this->resourceId === null || ! is_subclass_of($resourceClass, Model::class)) {
return null;
}
return $resourceClass::query()->find($this->resourceId);
}
}