fix(proxy): stop automatic proxy network reconnects on status checks

Remove the periodic ConnectProxyToNetworksJob dispatch from
PushServerUpdateJob, the synchronous connect in ServerCheckJob when the
proxy is found running, and the connect-on-add in the server
Destinations component. Drop the now-unused
proxy.connect_networks_interval_seconds config option.

Replace the rate-limit/interval tests with a test asserting that no
jobs are pushed when the proxy is running.
This commit is contained in:
Andras Bacsai
2026-10-04 00:36:28 +02:00
parent 9eb666e982
commit 22900b6d12
5 changed files with 2 additions and 104 deletions
-8
View File
@@ -811,14 +811,6 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue, Silenced
}
} catch (\Throwable $e) {
}
} else {
// Connect proxy to networks periodically as a safety net to avoid excessive job dispatches.
// On-demand triggers (new network, service deploy) use dispatchSync() and bypass this.
$proxyCacheKey = 'connect-proxy:'.$this->server->id;
if (! Cache::has($proxyCacheKey)) {
Cache::put($proxyCacheKey, true, config('constants.proxy.connect_networks_interval_seconds', 3600));
ConnectProxyToNetworksJob::dispatch($this->server);
}
}
}
}
-1
View File
@@ -92,7 +92,6 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
} else {
$this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
$this->server->save();
ConnectProxyToNetworksJob::dispatchSync($this->server);
}
}
}
-7
View File
@@ -2,7 +2,6 @@
namespace App\Livewire\Server;
use App\Jobs\ConnectProxyToNetworksJob;
use App\Models\Server;
use App\Models\StandaloneDocker;
use App\Models\SwarmDocker;
@@ -28,11 +27,6 @@ class Destinations extends Component
}
}
private function createNetworkAndAttachToProxy()
{
ConnectProxyToNetworksJob::dispatchSync($this->server);
}
public function add($name)
{
if ($this->server->isSwarm()) {
@@ -63,7 +57,6 @@ class Destinations extends Component
'server_id' => $this->server->id,
]);
}
$this->createNetworkAndAttachToProxy();
}
}
-8
View File
@@ -109,14 +109,6 @@ return [
],
'proxy' => [
// How often (seconds) PushServerUpdateJob periodically re-connects the
// proxy to Docker networks as a safety net. Real network-layout changes
// already connect the proxy on-demand; this only covers gaps (Swarm
// networks added via UI, proxy crash recovery).
'connect_networks_interval_seconds' => env('PROXY_CONNECT_NETWORKS_INTERVAL_SECONDS', 3600),
],
'github_runner' => [
// GitHub stops sending jobs to runners that are more than 30 days behind, so the default follows
// "latest" and is pulled for every runner. Users can pin a tag in the runner settings.
@@ -1,6 +1,5 @@
<?php
use App\Jobs\ConnectProxyToNetworksJob;
use App\Jobs\PushServerUpdateJob;
use App\Jobs\ServerStorageCheckJob;
use App\Models\Server;
@@ -121,81 +120,7 @@ it('dispatches storage check when disk percentage changes from cached value', fu
});
});
it('rate-limits ConnectProxyToNetworksJob dispatch to every 10 minutes', function () {
$team = Team::factory()->create();
$server = Server::factory()->create(['team_id' => $team->id]);
$server->settings->update(['is_reachable' => true, 'is_usable' => true]);
// First push: should dispatch ConnectProxyToNetworksJob
$containersWithProxy = [
[
'name' => 'coolify-proxy',
'state' => 'running',
'health_status' => 'healthy',
'labels' => ['coolify.managed' => true],
],
];
$data = [
'containers' => $containersWithProxy,
'filesystem_usage_root' => ['used_percentage' => 10],
];
$job = new PushServerUpdateJob($server, $data);
$job->handle();
Queue::assertPushed(ConnectProxyToNetworksJob::class, 1);
// Second push: should NOT dispatch ConnectProxyToNetworksJob (rate-limited)
Queue::fake();
$job2 = new PushServerUpdateJob($server, $data);
$job2->handle();
Queue::assertNotPushed(ConnectProxyToNetworksJob::class);
});
it('dispatches ConnectProxyToNetworksJob again after cache expires', function () {
$team = Team::factory()->create();
$server = Server::factory()->create(['team_id' => $team->id]);
$server->settings->update(['is_reachable' => true, 'is_usable' => true]);
$containersWithProxy = [
[
'name' => 'coolify-proxy',
'state' => 'running',
'health_status' => 'healthy',
'labels' => ['coolify.managed' => true],
],
];
$data = [
'containers' => $containersWithProxy,
'filesystem_usage_root' => ['used_percentage' => 10],
];
// First push
$job = new PushServerUpdateJob($server, $data);
$job->handle();
Queue::assertPushed(ConnectProxyToNetworksJob::class, 1);
// Clear cache to simulate expiration
Cache::forget('connect-proxy:'.$server->id);
// Next push: should dispatch again
Queue::fake();
$job2 = new PushServerUpdateJob($server, $data);
$job2->handle();
Queue::assertPushed(ConnectProxyToNetworksJob::class, 1);
});
it('respects the configured proxy connect interval', function () {
// Interval 0 → the connect-proxy gate key expires immediately, so every
// push re-dispatches without a manual Cache::forget. Proves the TTL is
// driven by config('constants.proxy.connect_networks_interval_seconds').
config(['constants.proxy.connect_networks_interval_seconds' => 0]);
it('does not dispatch proxy network work when the proxy is running', function () {
$team = Team::factory()->create();
$server = Server::factory()->create(['team_id' => $team->id]);
$server->settings->update(['is_reachable' => true, 'is_usable' => true]);
@@ -213,11 +138,8 @@ it('respects the configured proxy connect interval', function () {
];
(new PushServerUpdateJob($server, $data))->handle();
Queue::assertPushed(ConnectProxyToNetworksJob::class, 1);
Queue::fake();
(new PushServerUpdateJob($server, $data))->handle();
Queue::assertPushed(ConnectProxyToNetworksJob::class, 1);
Queue::assertNothingPushed();
});
it('uses default queue for PushServerUpdateJob', function () {