mirror of
https://github.com/tiennm99/coolify.git
synced 2026-08-10 06:21:41 +00:00
feat(jobs): optimize async job dispatches and enhance Stripe subscription sync
Reduce unnecessary job queue pressure and improve subscription sync reliability: - Cache ServerStorageCheckJob dispatch to only trigger on disk percentage changes - Rate-limit ConnectProxyToNetworksJob to maximum once per 10 minutes - Add progress callback support to SyncStripeSubscriptionsJob for UI feedback - Implement bulk fetching of valid Stripe subscription IDs for efficiency - Detect and report resubscribed users (same email, different customer ID) - Fix CleanupUnreachableServers query operator (>= 3 instead of = 3) - Improve empty subId validation in PushServerUpdateJob - Optimize relationship access by using properties instead of query methods - Add comprehensive test coverage for all optimizations
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
use App\Jobs\ConnectProxyToNetworksJob;
|
||||
use App\Jobs\PushServerUpdateJob;
|
||||
use App\Jobs\ServerStorageCheckJob;
|
||||
use App\Models\Server;
|
||||
use App\Models\Team;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
Queue::fake();
|
||||
Cache::flush();
|
||||
});
|
||||
|
||||
it('dispatches storage check when disk percentage changes', function () {
|
||||
$team = Team::factory()->create();
|
||||
$server = Server::factory()->create(['team_id' => $team->id]);
|
||||
|
||||
$data = [
|
||||
'containers' => [],
|
||||
'filesystem_usage_root' => ['used_percentage' => 45],
|
||||
];
|
||||
|
||||
$job = new PushServerUpdateJob($server, $data);
|
||||
$job->handle();
|
||||
|
||||
Queue::assertPushed(ServerStorageCheckJob::class, function ($job) use ($server) {
|
||||
return $job->server->id === $server->id && $job->percentage === 45;
|
||||
});
|
||||
});
|
||||
|
||||
it('does not dispatch storage check when disk percentage is unchanged', function () {
|
||||
$team = Team::factory()->create();
|
||||
$server = Server::factory()->create(['team_id' => $team->id]);
|
||||
|
||||
// Simulate a previous push that cached the percentage
|
||||
Cache::put('storage-check:'.$server->id, 45, 600);
|
||||
|
||||
$data = [
|
||||
'containers' => [],
|
||||
'filesystem_usage_root' => ['used_percentage' => 45],
|
||||
];
|
||||
|
||||
$job = new PushServerUpdateJob($server, $data);
|
||||
$job->handle();
|
||||
|
||||
Queue::assertNotPushed(ServerStorageCheckJob::class);
|
||||
});
|
||||
|
||||
it('dispatches storage check when disk percentage changes from cached value', function () {
|
||||
$team = Team::factory()->create();
|
||||
$server = Server::factory()->create(['team_id' => $team->id]);
|
||||
|
||||
// Simulate a previous push that cached 45%
|
||||
Cache::put('storage-check:'.$server->id, 45, 600);
|
||||
|
||||
$data = [
|
||||
'containers' => [],
|
||||
'filesystem_usage_root' => ['used_percentage' => 50],
|
||||
];
|
||||
|
||||
$job = new PushServerUpdateJob($server, $data);
|
||||
$job->handle();
|
||||
|
||||
Queue::assertPushed(ServerStorageCheckJob::class, function ($job) use ($server) {
|
||||
return $job->server->id === $server->id && $job->percentage === 50;
|
||||
});
|
||||
});
|
||||
|
||||
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('uses default queue for PushServerUpdateJob', function () {
|
||||
$team = Team::factory()->create();
|
||||
$server = Server::factory()->create(['team_id' => $team->id]);
|
||||
|
||||
$job = new PushServerUpdateJob($server, ['containers' => []]);
|
||||
|
||||
expect($job->queue)->toBeNull();
|
||||
});
|
||||
Reference in New Issue
Block a user