From 1830891c6223f5e030cb00b3c2598c4be88479ed Mon Sep 17 00:00:00 2001 From: "iVampireSP.com" Date: Wed, 8 Mar 2023 08:25:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E6=89=A3=E8=B4=B9?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Kernel.php | 7 +- ...eJob.php => DispatchHostCostHourlyJob.php} | 26 +++---- app/Jobs/Host/DispatchHostCostMonthlyJob.php | 68 +++++++++++++++++++ app/Models/Host.php | 6 +- 4 files changed, 84 insertions(+), 23 deletions(-) rename app/Jobs/Host/{DispatchHostCostQueueJob.php => DispatchHostCostHourlyJob.php} (52%) create mode 100644 app/Jobs/Host/DispatchHostCostMonthlyJob.php diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 8cbdbf7..d3484b2 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -4,7 +4,8 @@ use App\Jobs\Host\CancelExpiredHostJob; use App\Jobs\Host\DeleteHostJob; -use App\Jobs\Host\DispatchHostCostQueueJob; +use App\Jobs\Host\DispatchHostCostHourlyJob; +use App\Jobs\Host\DispatchHostCostMonthlyJob; use App\Jobs\Host\ScanErrorHostsJob; use App\Jobs\Module\DispatchFetchModuleJob; use App\Jobs\Module\SendModuleEarningsJob; @@ -31,8 +32,8 @@ protected function schedule(Schedule $schedule): void $schedule->command('sanctum:prune-expired --hours=24')->daily()->runInBackground()->onOneServer()->name('清理过期的 Token。'); // 扣费 - $schedule->job(new DispatchHostCostQueueJob(now(), null, 'hourly'))->everyMinute()->withoutOverlapping()->onOneServer()->name('部署扣费任务 (小时)'); - $schedule->job(new DispatchHostCostQueueJob(now(), null, 'monthly'))->hourly()->withoutOverlapping()->onOneServer()->name('部署扣费任务 (月度)'); + $schedule->job(new DispatchHostCostHourlyJob(now()->minute, null))->everyMinute()->withoutOverlapping()->onOneServer()->name('部署扣费任务 (小时)'); + $schedule->job(new DispatchHostCostMonthlyJob(now()->day, now()->hour, null))->hourly()->withoutOverlapping()->onOneServer()->name('部署扣费任务 (月度)'); $schedule->job(new CancelExpiredHostJob())->hourly()->withoutOverlapping()->onOneServer()->name('部署清理到期主机任务'); // 获取模块暴露的信息(服务器等,检查模块状态) diff --git a/app/Jobs/Host/DispatchHostCostQueueJob.php b/app/Jobs/Host/DispatchHostCostHourlyJob.php similarity index 52% rename from app/Jobs/Host/DispatchHostCostQueueJob.php rename to app/Jobs/Host/DispatchHostCostHourlyJob.php index 2a8c071..25d6c7f 100644 --- a/app/Jobs/Host/DispatchHostCostQueueJob.php +++ b/app/Jobs/Host/DispatchHostCostHourlyJob.php @@ -3,32 +3,29 @@ namespace App\Jobs\Host; use App\Models\Host; -use Carbon\Carbon; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -class DispatchHostCostQueueJob implements ShouldQueue +class DispatchHostCostHourlyJob implements ShouldQueue { - use InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - protected Carbon $now; + protected int $minute; protected ?Host $host; - protected string $type; - /** * Create a new job instance. * * @return void */ - public function __construct(Carbon $now, Host $host = null, $type = 'hourly') + public function __construct(int $minute, Host $host = null) { - $this->now = $now; + $this->minute = $minute; $this->host = $host; - $this->type = $type; $this->onQueue('host-cost'); } @@ -41,21 +38,16 @@ public function handle(): void if (! $this->host) { $host = new Host(); - if ($this->type == 'monthly') { - // 月度计费,需要精确到天和小时 - $host = $host->where('day_at', $this->now->day); - $host = $host->where('hour_at', $this->now->hour); - $host = $host->where('cancel_at_period_end', false); - } elseif (app()->environment() != 'local') { + if (app()->environment() != 'local') { $host = $host->where('minute_at', $this->minute); } - $host->where('billing_cycle', $this->type)->whereIn('status', ['running', 'stopped'])->with(['user', 'module'])->chunk(500, function ($hosts) { + $host->where('billing_cycle', 'hourly')->whereIn('status', ['running', 'stopped'])->with(['user', 'module'])->chunk(500, function ($hosts) { $hosts->each(function ($host) { /* @var Host $host */ if ($host->module->isUp()) { - dispatch(new self($this->now, $host, $this->type)); + dispatch(new self($this->minute, $host)); } }); }); diff --git a/app/Jobs/Host/DispatchHostCostMonthlyJob.php b/app/Jobs/Host/DispatchHostCostMonthlyJob.php new file mode 100644 index 0000000..ae46fde --- /dev/null +++ b/app/Jobs/Host/DispatchHostCostMonthlyJob.php @@ -0,0 +1,68 @@ +day = $day; + $this->hour = $hour; + + $this->host = $host; + + $this->onQueue('host-cost'); + } + + /** + * Execute the job. + */ + public function handle(): void + { + if (! $this->host) { + $host = new Host(); + + // 月度计费,需要精确到天和小时 + $host = $host->where('day_at', $this->day); + $host = $host->where('hour_at', $this->hour); + $host = $host->where('cancel_at_period_end', false); + + $host->where('billing_cycle', 'monthly')->whereIn('status', ['running', 'stopped'])->with(['user', 'module'])->chunk(500, function ($hosts) { + $hosts->each(function ($host) { + /* @var Host $host */ + + if ($host->module->isUp()) { + dispatch(new self($this->day, $this->hour, $host)); + } + }); + }); + } else { + if (! $this->host->isNextMonthCancel() && ! $this->host->isTrial()) { + $this->host->cost($this->host->getPrice()); + } + } + } +} diff --git a/app/Models/Host.php b/app/Models/Host.php index 1ab4af9..20b9d60 100644 --- a/app/Models/Host.php +++ b/app/Models/Host.php @@ -215,9 +215,9 @@ public function isNextMonthCancel(): bool public function cost( string $amount = null, $auto = true, $description = null ): bool { - // if ($this->isTrial() && $this->trial_ends_at->()) { - // return true; - // } + if ($this->isTrial() && ! $this->trial_ends_at->isPast()) { + return true; + } $this->load('user'); $user = $this->user;