新增 主机 锁定 和 不可用状态
This commit is contained in:
parent
6f6f5669e4
commit
a7ade7843d
@ -2,10 +2,10 @@
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use App\Jobs\Host\DeleteSuspendedHostJob;
|
||||
use App\Jobs\Host\DeleteHostJob;
|
||||
use App\Jobs\Host\DispatchHostCostQueueJob;
|
||||
use App\Jobs\Host\ScanAllHostsJob;
|
||||
use App\Jobs\Module\FetchModuleJob;
|
||||
use App\Jobs\Module\DispatchFetchModuleJob;
|
||||
use App\Jobs\Module\SendModuleEarningsJob;
|
||||
use App\Jobs\User\CheckAndChargeBalanceJob;
|
||||
use App\Jobs\User\ClearTasksJob;
|
||||
@ -33,8 +33,8 @@ protected function schedule(Schedule $schedule): void
|
||||
// 扣费
|
||||
$schedule->job(new DispatchHostCostQueueJob(now()->minute))->everyMinute()->withoutOverlapping()->onOneServer();
|
||||
|
||||
// 获取模块暴露的信息(服务器等)
|
||||
$schedule->job(new FetchModuleJob())->withoutOverlapping()->everyMinute();
|
||||
// 获取模块暴露的信息(服务器等,检查模块状态)
|
||||
$schedule->job(new DispatchFetchModuleJob())->withoutOverlapping()->everyMinute();
|
||||
|
||||
// 推送工单
|
||||
$schedule->job(new PushWorkOrderJob())->everyMinute()->onOneServer();
|
||||
@ -45,7 +45,7 @@ protected function schedule(Schedule $schedule): void
|
||||
$schedule->job(new ClearTasksJob())->weekly();
|
||||
|
||||
// 删除暂停或部署时间超过 3 天以上的主机
|
||||
$schedule->job(new DeleteSuspendedHostJob())->hourly();
|
||||
$schedule->job(new DeleteHostJob())->hourly();
|
||||
|
||||
// 检查主机是否存在于模块
|
||||
$schedule->job(new ScanAllHostsJob())->everyThirtyMinutes()->withoutOverlapping()->onOneServer();
|
||||
|
@ -58,7 +58,7 @@ public function update(Request $request, Host $host): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'sometimes|string|max:255',
|
||||
'status' => 'sometimes|in:running,stopped,suspended,pending',
|
||||
'status' => 'sometimes|in:running,stopped,suspended,pending,locked,unavailable',
|
||||
'price' => 'sometimes|numeric',
|
||||
'managed_price' => 'nullable|numeric',
|
||||
]);
|
||||
|
@ -30,6 +30,10 @@ public function update(HostRequest $request, Host $host): JsonResponse
|
||||
'status' => 'required|in:running,stopped',
|
||||
]);
|
||||
|
||||
if ($host->status === 'locked' || $host->status === 'unavailable') {
|
||||
return $this->error('当前主机状态不允许操作');
|
||||
}
|
||||
|
||||
$user = $request->user();
|
||||
|
||||
if ($user->balance < 0.5) {
|
||||
|
@ -7,6 +7,7 @@
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class ModuleController extends Controller
|
||||
{
|
||||
@ -17,6 +18,13 @@ public function index(): JsonResponse
|
||||
return $this->success($modules);
|
||||
}
|
||||
|
||||
public function servers(Module $module): JsonResponse
|
||||
{
|
||||
$servers = Cache::get('module:' . $module->id . ':servers', []);
|
||||
|
||||
return $this->success($servers);
|
||||
}
|
||||
|
||||
public function call(Request $request, Module $module): JsonResponse|Response
|
||||
{
|
||||
return (new \App\Http\Controllers\Module\ModuleController())->call($request, $module);
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
|
||||
class DeleteSuspendedHostJob implements ShouldQueue
|
||||
class DeleteHostJob implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -38,11 +38,25 @@ public function handle(): void
|
||||
}
|
||||
});
|
||||
|
||||
// 查找部署时间超过3天以上的 host
|
||||
// 查找部署时间超过 3 天以上的 host
|
||||
(new Host)->where('status', 'pending')->where('created_at', '<', now()->subDays(3))->chunk(100, function ($hosts) {
|
||||
foreach ($hosts as $host) {
|
||||
dispatch(new HostJob($host, 'delete'));
|
||||
}
|
||||
});
|
||||
|
||||
// 查找不可用时间超过 3 天以上的 host
|
||||
(new Host)->where('status', 'unavailable')->where('unavailable_at', '<', now()->subDays(3))->chunk(100, function ($hosts) {
|
||||
foreach ($hosts as $host) {
|
||||
dispatch(new HostJob($host, 'delete'));
|
||||
}
|
||||
});
|
||||
|
||||
// 查找锁定时间超过 3 天以上的 host
|
||||
(new Host)->where('status', 'locked')->where('locked_at', '<', now()->subDays(3))->chunk(100, function ($hosts) {
|
||||
foreach ($hosts as $host) {
|
||||
dispatch(new HostJob($host, 'delete'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -38,6 +38,13 @@ public function __construct(HostModel $host, $type = 'post')
|
||||
public function handle(): void
|
||||
{
|
||||
$host = $this->host;
|
||||
|
||||
// 忽略 unavailable 状态的 host
|
||||
if ($host->status === 'unavailable') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$host->load(['module']);
|
||||
|
||||
switch ($this->type) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UpdateOrSuspendedHostJob implements ShouldQueue
|
||||
class UpdateOrDeleteHostJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -41,8 +41,10 @@ public function handle(): void
|
||||
if ($response['status'] === 200) {
|
||||
$host->update(Arr::except($response['json'], ['id', 'user_id', 'module_id', 'created_at', 'updated_at']));
|
||||
} else if ($response['status'] === 404) {
|
||||
Log::warning($host->module->name . ' ' . $host->name . ' ' . $host->id . ' 不存在,标记为暂停。');
|
||||
dispatch(new HostJob($host, 'delete'));
|
||||
Log::warning($host->module->name . ' ' . $host->name . ' ' . $host->id . ' 不存在,标记为不可用。');
|
||||
// dispatch(new HostJob($host, 'delete'));
|
||||
$host->status = 'unavailable';
|
||||
$host->save();
|
||||
}
|
||||
}
|
||||
}
|
41
app/Jobs/Module/DispatchFetchModuleJob.php
Normal file
41
app/Jobs/Module/DispatchFetchModuleJob.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs\Module;
|
||||
|
||||
use App\Models\Module;
|
||||
use Exception;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class DispatchFetchModuleJob implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
(new Module)->whereNotNull('url')->chunk(100, function ($modules) {
|
||||
foreach ($modules as $module) {
|
||||
dispatch(new FetchModuleJob($module));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -2,10 +2,12 @@
|
||||
|
||||
namespace App\Jobs\Module;
|
||||
|
||||
use App\Jobs\Host\UpdateOrDeleteHostJob;
|
||||
use App\Models\Module;
|
||||
use Exception;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
@ -13,16 +15,19 @@
|
||||
|
||||
class FetchModuleJob implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, Queueable, SerializesModels;
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
|
||||
protected Module $module;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
public function __construct(Module $module)
|
||||
{
|
||||
//
|
||||
$this->module = $module;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,30 +37,18 @@ public function __construct()
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
// 获取运行完成的时间
|
||||
$module = $this->module;
|
||||
|
||||
// $last_run = Cache::get('servers_updated_at', false);
|
||||
// if ($last_run !== false) {
|
||||
// // 如果和上次运行时间间隔小于一分钟,则不运行
|
||||
// if (now()->diffInMinutes($last_run) < 1) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
$servers = Cache::get('module:' . $module->id . ':servers', []);
|
||||
|
||||
//
|
||||
(new Module)->whereNotNull('url')->chunk(100, function ($modules) {
|
||||
$servers = [];
|
||||
|
||||
foreach ($modules as $module) {
|
||||
try {
|
||||
$response = $module->http()->get('remote');
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
if ($response->successful()) {
|
||||
|
||||
// 如果模块状态不为 up,则更新为 up
|
||||
if ($module->status !== 'up') {
|
||||
$module->status = 'up';
|
||||
@ -83,9 +76,9 @@ public function handle(): void
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// if module return maintenance, then set module status to maintenance
|
||||
if ($response->status() == 503) {
|
||||
$status = $response->status();
|
||||
if ($status == 503 || $status == 429 || $status == 502) {
|
||||
$module->status = 'maintenance';
|
||||
} else {
|
||||
$module->status = 'down';
|
||||
@ -93,17 +86,13 @@ public function handle(): void
|
||||
}
|
||||
|
||||
$module->save();
|
||||
}
|
||||
|
||||
// if local
|
||||
if (config('app.env') === 'local') {
|
||||
Cache::forever('servers', $servers);
|
||||
Cache::forever('module:' . $module->id . ':servers', $servers);
|
||||
} else {
|
||||
Cache::put('servers', $servers, now()->addMinutes(10));
|
||||
Cache::put('module:' . $module->id . ':servers', $servers, now()->addMinutes(10));
|
||||
}
|
||||
|
||||
// 缓存运行完成的时间
|
||||
// Cache::put('servers_updated_at', now(), now()->addMinutes(10));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
use App\Events\Users;
|
||||
use App\Jobs\Host\HostJob;
|
||||
use App\Jobs\Host\UpdateOrSuspendedHostJob;
|
||||
use App\Jobs\Host\UpdateOrDeleteHostJob;
|
||||
use App\Notifications\WebNotification;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
@ -54,23 +54,35 @@ protected static function boot()
|
||||
});
|
||||
|
||||
static::created(function (self $model) {
|
||||
|
||||
$model->user->notify(new WebNotification($model, 'hosts.created'));
|
||||
|
||||
});
|
||||
|
||||
|
||||
static::updating(function ($model) {
|
||||
static::updating(function (self $model) {
|
||||
if ($model->isDirty('status')) {
|
||||
if ($model->status == 'suspended') {
|
||||
$model->suspended_at = now();
|
||||
} else {
|
||||
$model->suspended_at = null;
|
||||
}
|
||||
|
||||
if ($model->status == 'locked') {
|
||||
$model->locked_at = now();
|
||||
} else {
|
||||
$model->locked_at = null;
|
||||
}
|
||||
|
||||
if ($model->status == 'unavailable') {
|
||||
$model->unavailable_at = now();
|
||||
} else {
|
||||
$model->unavailable_at = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 调度任务
|
||||
if ($model->status !== 'unavailable') {
|
||||
dispatch(new HostJob($model, 'patch'));
|
||||
}
|
||||
|
||||
broadcast(new Users($model->user_id, 'hosts.updating', $model));
|
||||
});
|
||||
@ -307,7 +319,7 @@ public function addLog(string $amount = "0"): bool
|
||||
|
||||
public function updateOrDelete(): bool
|
||||
{
|
||||
dispatch(new UpdateOrSuspendedHostJob($this));
|
||||
dispatch(new UpdateOrDeleteHostJob($this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -20,10 +20,9 @@ class Module extends Authenticatable
|
||||
|
||||
public $incrementing = false;
|
||||
|
||||
// primary key
|
||||
public $timestamps = false;
|
||||
protected $table = 'modules';
|
||||
protected $keyType = 'string';
|
||||
|
||||
protected $fillable = [
|
||||
'id',
|
||||
'name',
|
||||
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
\Illuminate\Support\Facades\DB::statement("ALTER TABLE `hosts` CHANGE `status` `status` ENUM('running','stopped','error','suspended','pending','unavailable', 'locked') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'pending';");
|
||||
|
||||
\Illuminate\Support\Facades\Schema::table('hosts', function (Blueprint $table) {
|
||||
$table->timestamp('unavailable_at')->nullable()->comment('不可用时间')->after('suspended_at');
|
||||
$table->timestamp('locked_at')->nullable()->comment('锁定时间')->after('unavailable_at');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
\Illuminate\Support\Facades\DB::statement("ALTER TABLE `hosts` CHANGE `status` `status` ENUM('running','stopped','error','suspended','pending') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'pending';");
|
||||
|
||||
\Illuminate\Support\Facades\Schema::table('hosts', function (Blueprint $table) {
|
||||
$table->dropColumn('unavailable_at');
|
||||
$table->dropColumn('locked_at');
|
||||
});
|
||||
}
|
||||
};
|
@ -20,6 +20,14 @@
|
||||
<span class="badge bg-danger">错误</span>
|
||||
@break
|
||||
|
||||
@case('unavailable')
|
||||
<span class="badge bg-secondary">不可用</span>
|
||||
@break
|
||||
|
||||
@case('locked')
|
||||
<span class="badge bg-danger">锁定</span>
|
||||
@break
|
||||
|
||||
@default
|
||||
<span class="badge bg-secondary">{{ $status }}</span>
|
||||
@endswitch
|
||||
|
Loading…
Reference in New Issue
Block a user