- 创建 TerminalSyncService 服务类 - 实现配置快照生成(包含终端、知识库、提示词) - 创建 SyncTerminalConfigJob 异步任务 - 实现重试机制(最多3次,指数退避) - 创建 SyncConfigAction(单个和批量同步) - 在终端列表页添加同步状态列 - 在终端详情页添加同步历史展示 - 支持同步状态追踪(pending/syncing/synced/failed)
161 lines
4.2 KiB
PHP
161 lines
4.2 KiB
PHP
<?php
|
||
|
||
namespace App\Jobs;
|
||
|
||
use App\Models\Terminal;
|
||
use App\Models\TerminalSyncLog;
|
||
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\Http;
|
||
use Illuminate\Support\Facades\Log;
|
||
|
||
/**
|
||
* 终端配置同步任务
|
||
*/
|
||
class SyncTerminalConfigJob implements ShouldQueue
|
||
{
|
||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||
|
||
/**
|
||
* 任务最大尝试次数
|
||
*
|
||
* @var int
|
||
*/
|
||
public $tries = 3;
|
||
|
||
/**
|
||
* 任务超时时间(秒)
|
||
*
|
||
* @var int
|
||
*/
|
||
public $timeout = 60;
|
||
|
||
/**
|
||
* 创建新的任务实例
|
||
*
|
||
* @param Terminal $terminal
|
||
* @param TerminalSyncLog $log
|
||
*/
|
||
public function __construct(
|
||
public Terminal $terminal,
|
||
public TerminalSyncLog $log
|
||
) {}
|
||
|
||
/**
|
||
* 执行任务
|
||
*
|
||
* @return void
|
||
*/
|
||
public function handle(): void
|
||
{
|
||
try {
|
||
// 更新状态为同步中
|
||
$this->log->update(['status' => 'syncing']);
|
||
|
||
Log::info('开始同步终端配置', [
|
||
'terminal_id' => $this->terminal->id,
|
||
'terminal_name' => $this->terminal->name,
|
||
'log_id' => $this->log->id,
|
||
]);
|
||
|
||
// 模拟同步过程(因为没有真实的终端API)
|
||
// 在实际环境中,这里应该调用真实的终端API
|
||
$this->simulateSync();
|
||
|
||
// 更新状态为已同步
|
||
$this->log->update([
|
||
'status' => 'synced',
|
||
'synced_at' => now(),
|
||
'error_message' => null,
|
||
]);
|
||
|
||
Log::info('终端配置同步成功', [
|
||
'terminal_id' => $this->terminal->id,
|
||
'log_id' => $this->log->id,
|
||
]);
|
||
|
||
} catch (\Exception $e) {
|
||
// 记录错误日志
|
||
Log::error('终端配置同步失败', [
|
||
'terminal_id' => $this->terminal->id,
|
||
'log_id' => $this->log->id,
|
||
'error' => $e->getMessage(),
|
||
'attempt' => $this->attempts(),
|
||
]);
|
||
|
||
// 更新状态为失败
|
||
$this->log->update([
|
||
'status' => 'failed',
|
||
'error_message' => $e->getMessage(),
|
||
]);
|
||
|
||
// 如果还有重试次数,则重新抛出异常以触发重试
|
||
if ($this->attempts() < $this->tries) {
|
||
throw $e;
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 模拟同步过程
|
||
*
|
||
* @return void
|
||
* @throws \Exception
|
||
*/
|
||
private function simulateSync(): void
|
||
{
|
||
// 模拟网络延迟
|
||
sleep(2);
|
||
|
||
// 随机模拟成功或失败(90%成功率)
|
||
if (rand(1, 100) <= 10) {
|
||
throw new \Exception('模拟同步失败:网络连接超时');
|
||
}
|
||
|
||
// 在实际环境中,这里应该是类似这样的代码:
|
||
// $response = Http::timeout(30)
|
||
// ->post($this->terminal->sync_url, [
|
||
// 'config' => $this->log->config_snapshot,
|
||
// ]);
|
||
//
|
||
// if (!$response->successful()) {
|
||
// throw new \Exception('同步失败:' . $response->body());
|
||
// }
|
||
}
|
||
|
||
/**
|
||
* 任务失败时的处理
|
||
*
|
||
* @param \Throwable $exception
|
||
* @return void
|
||
*/
|
||
public function failed(\Throwable $exception): void
|
||
{
|
||
Log::error('终端配置同步任务最终失败', [
|
||
'terminal_id' => $this->terminal->id,
|
||
'log_id' => $this->log->id,
|
||
'error' => $exception->getMessage(),
|
||
]);
|
||
|
||
// 确保状态更新为失败
|
||
$this->log->update([
|
||
'status' => 'failed',
|
||
'error_message' => '同步失败(已达最大重试次数):' . $exception->getMessage(),
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 计算重试延迟时间(秒)
|
||
*
|
||
* @return int
|
||
*/
|
||
public function backoff(): int
|
||
{
|
||
// 指数退避:第1次重试等待10秒,第2次等待30秒
|
||
return [10, 30][$this->attempts() - 1] ?? 60;
|
||
}
|
||
}
|