feat: long running queue with 1 hour of timeout
This commit is contained in:
parent
ba18c589f0
commit
80af200c9f
@ -17,12 +17,12 @@
|
|||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Notification;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Spatie\Activitylog\Models\Activity;
|
use Spatie\Activitylog\Models\Activity;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Spatie\Url\Url;
|
use Spatie\Url\Url;
|
||||||
|
use Throwable;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
class ApplicationDeploymentJob implements ShouldQueue
|
class ApplicationDeploymentJob implements ShouldQueue
|
||||||
@ -46,7 +46,7 @@ class ApplicationDeploymentJob implements ShouldQueue
|
|||||||
private ApplicationPreview|null $preview = null;
|
private ApplicationPreview|null $preview = null;
|
||||||
|
|
||||||
public static int $batch_counter = 0;
|
public static int $batch_counter = 0;
|
||||||
public $timeout = 10200;
|
public $failOnTimeout = true;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public int $application_deployment_queue_id,
|
public int $application_deployment_queue_id,
|
||||||
@ -128,7 +128,8 @@ public function handle(): void
|
|||||||
"echo '\nOops something is not okay, are you okay? 😢'",
|
"echo '\nOops something is not okay, are you okay? 😢'",
|
||||||
"echo '\n\n{$e->getMessage()}'",
|
"echo '\n\n{$e->getMessage()}'",
|
||||||
]);
|
]);
|
||||||
$this->fail();
|
ray($e);
|
||||||
|
$this->fail($e->getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
if (isset($this->docker_compose)) {
|
if (isset($this->docker_compose)) {
|
||||||
Storage::disk('deployments')->put(Str::kebab($this->application->name) . '/docker-compose.yml', $this->docker_compose);
|
Storage::disk('deployments')->put(Str::kebab($this->application->name) . '/docker-compose.yml', $this->docker_compose);
|
||||||
@ -142,9 +143,15 @@ private function start_builder_image()
|
|||||||
$this->execute_now([
|
$this->execute_now([
|
||||||
"echo -n 'Pulling latest version of the builder image (ghcr.io/coollabsio/coolify-builder)... '",
|
"echo -n 'Pulling latest version of the builder image (ghcr.io/coollabsio/coolify-builder)... '",
|
||||||
]);
|
]);
|
||||||
$this->execute_now([
|
if (isDev()) {
|
||||||
"docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder",
|
$this->execute_now([
|
||||||
], isDebuggable: true);
|
"docker run -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock coolify-builder",
|
||||||
|
], isDebuggable: true);
|
||||||
|
} else {
|
||||||
|
$this->execute_now([
|
||||||
|
"docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder",
|
||||||
|
], isDebuggable: true);
|
||||||
|
}
|
||||||
$this->execute_now([
|
$this->execute_now([
|
||||||
"echo 'Done.'"
|
"echo 'Done.'"
|
||||||
]);
|
]);
|
||||||
@ -291,8 +298,9 @@ private function deploy()
|
|||||||
$this->next(ProcessStatus::FINISHED->value);
|
$this->next(ProcessStatus::FINISHED->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function failed(): void
|
public function failed(Throwable $exception): void
|
||||||
{
|
{
|
||||||
|
ray($exception);
|
||||||
$this->next(ProcessStatus::ERROR->value);
|
$this->next(ProcessStatus::ERROR->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +337,7 @@ private function next(string $status)
|
|||||||
}
|
}
|
||||||
private function execute_in_builder(string $command)
|
private function execute_in_builder(string $command)
|
||||||
{
|
{
|
||||||
return "docker exec {$this->deployment_uuid} bash -c '{$command}'";
|
return "docker exec {$this->deployment_uuid} bash -c '{$command} |& tee -a /proc/1/fd/1'";
|
||||||
}
|
}
|
||||||
private function generate_environment_variables($ports)
|
private function generate_environment_variables($ports)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ function queue_application_deployment(int $application_id, string $deployment_uu
|
|||||||
force_rebuild: $force_rebuild,
|
force_rebuild: $force_rebuild,
|
||||||
rollback_commit: $commit,
|
rollback_commit: $commit,
|
||||||
pull_request_id: $pull_request_id,
|
pull_request_id: $pull_request_id,
|
||||||
));
|
))->onConnection('long-running')->onQueue('long-running');
|
||||||
}
|
}
|
||||||
|
|
||||||
function queue_next_deployment(Application $application)
|
function queue_next_deployment(Application $application)
|
||||||
@ -47,6 +47,6 @@ function queue_next_deployment(Application $application)
|
|||||||
deployment_uuid: $next_found->deployment_uuid,
|
deployment_uuid: $next_found->deployment_uuid,
|
||||||
force_rebuild: $next_found->force_rebuild,
|
force_rebuild: $next_found->force_rebuild,
|
||||||
pull_request_id: $next_found->pull_request_id
|
pull_request_id: $next_found->pull_request_id
|
||||||
));
|
))->onConnection('long-running')->onQueue('long-running');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ function git_api(GithubApp|GitlabApp $source, string $endpoint, string $method =
|
|||||||
}
|
}
|
||||||
$json = $response->json();
|
$json = $response->json();
|
||||||
if ($response->failed() && $throwError) {
|
if ($response->failed() && $throwError) {
|
||||||
throw new \Exception("Failed to get data from {$source->name} with error: " . $json['message']);
|
throw new \Exception("Failed to get data from {$source->name} with error:<br><br>" . $json['message']);
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
'rate_limit_remaining' => $response->header('X-RateLimit-Remaining'),
|
'rate_limit_remaining' => $response->header('X-RateLimit-Remaining'),
|
||||||
|
@ -190,7 +190,18 @@
|
|||||||
'maxJobs' => 0,
|
'maxJobs' => 0,
|
||||||
'memory' => 128,
|
'memory' => 128,
|
||||||
'tries' => 1,
|
'tries' => 1,
|
||||||
'timeout' => 3600,
|
'timeout' => 300,
|
||||||
|
'nice' => 0,
|
||||||
|
],
|
||||||
|
'long-running' => [
|
||||||
|
'connection' => 'redis',
|
||||||
|
'queue' => ['long-running'],
|
||||||
|
'balance' => 'auto',
|
||||||
|
'maxTime' => 0,
|
||||||
|
'maxJobs' => 0,
|
||||||
|
'memory' => 128,
|
||||||
|
'tries' => 1,
|
||||||
|
'timeout' => 3560,
|
||||||
'nice' => 0,
|
'nice' => 0,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -203,6 +214,12 @@
|
|||||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||||
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||||
],
|
],
|
||||||
|
'long-running' => [
|
||||||
|
'autoScalingStrategy' => 'size',
|
||||||
|
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 10),
|
||||||
|
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||||
|
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
'local' => [
|
'local' => [
|
||||||
@ -212,6 +229,12 @@
|
|||||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||||
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||||
],
|
],
|
||||||
|
'long-running' => [
|
||||||
|
'autoScalingStrategy' => 'size',
|
||||||
|
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 10),
|
||||||
|
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||||
|
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -33,7 +33,14 @@
|
|||||||
'sync' => [
|
'sync' => [
|
||||||
'driver' => 'sync',
|
'driver' => 'sync',
|
||||||
],
|
],
|
||||||
|
'long-running' => [
|
||||||
|
'driver' => 'redis',
|
||||||
|
'connection' => 'default',
|
||||||
|
'queue' => 'long-running',
|
||||||
|
'retry_after' => 3600,
|
||||||
|
'block_for' => null,
|
||||||
|
'after_commit' => false,
|
||||||
|
],
|
||||||
'database' => [
|
'database' => [
|
||||||
'driver' => 'database',
|
'driver' => 'database',
|
||||||
'table' => 'jobs',
|
'table' => 'jobs',
|
||||||
@ -66,7 +73,7 @@
|
|||||||
'driver' => 'redis',
|
'driver' => 'redis',
|
||||||
'connection' => 'default',
|
'connection' => 'default',
|
||||||
'queue' => env('REDIS_QUEUE', 'default'),
|
'queue' => env('REDIS_QUEUE', 'default'),
|
||||||
'retry_after' => 90,
|
'retry_after' => 300,
|
||||||
'block_for' => null,
|
'block_for' => null,
|
||||||
'after_commit' => false,
|
'after_commit' => false,
|
||||||
],
|
],
|
||||||
|
@ -35,5 +35,5 @@ RUN if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \
|
|||||||
;fi
|
;fi
|
||||||
|
|
||||||
ENTRYPOINT ["/sbin/tini", "--"]
|
ENTRYPOINT ["/sbin/tini", "--"]
|
||||||
CMD ["sh", "-c", "while true; do sleep 3600 && exit 0; done"]
|
CMD ["sh", "-c", "while true; do sleep 1; done"]
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div class="flex items-center gap-2 pb-4">
|
<div class="flex items-center gap-2 pb-4">
|
||||||
<h2>Logs</h2>
|
<h2>Logs</h2>
|
||||||
@if (data_get($activity, 'properties.status') === 'in_progress')
|
@if (data_get($activity, 'properties.status') === 'in_progress' || data_get($activity, 'properties.status') === 'queued')
|
||||||
<x-forms.button wire:click.prevent="cancel">Cancel deployment</x-forms.button>
|
<x-forms.button wire:click.prevent="cancel">Cancel deployment</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -67,8 +67,8 @@ class="hover:no-underline">
|
|||||||
dayjs.extend(window.dayjs_plugin_relativeTime);
|
dayjs.extend(window.dayjs_plugin_relativeTime);
|
||||||
|
|
||||||
Alpine.data('elapsedTime', (uuid, status, created_at, updated_at) => ({
|
Alpine.data('elapsedTime', (uuid, status, created_at, updated_at) => ({
|
||||||
finished_time: '0s',
|
finished_time: 'calculating...',
|
||||||
started_time: '0s',
|
started_time: 'calculating...',
|
||||||
init() {
|
init() {
|
||||||
if (timers[uuid]) {
|
if (timers[uuid]) {
|
||||||
clearInterval(timers[uuid]);
|
clearInterval(timers[uuid]);
|
||||||
|
2
resources/views/vendor/toaster/hub.blade.php
vendored
2
resources/views/vendor/toaster/hub.blade.php
vendored
@ -71,7 +71,7 @@ class="relative flex duration-300 transform transition ease-in-out max-w-md w-fu
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span x-text="toast.message" />
|
<span x-html="toast.message" />
|
||||||
</i>
|
</i>
|
||||||
|
|
||||||
@if ($closeable)
|
@if ($closeable)
|
||||||
|
Loading…
Reference in New Issue
Block a user