Files
chatroom/app/Console/Commands/CloseStaleDutyLogs.php

66 lines
2.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:自动关闭掉线职务日志指令
*
* 每 15 分钟由 Laravel Scheduler 调用,扫描 position_duty_logs 表中:
* - logout_at IS NULL尚未结算的开放日志
* - updated_at 超过 15 分钟未刷新(说明心跳已中断,用户已掉线/关闭浏览器)
*
* 对此类日志写入 logout_at = NOW(),保留 duration_seconds 现有值不清零,
* 确保累计时长计算准确,不因掉线而永久悬空。
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Console\Commands;
use App\Models\PositionDutyLog;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class CloseStaleDutyLogs extends Command
{
/**
* Artisan 指令名称
*/
protected $signature = 'duty:close-stale-logs';
/**
* 指令描述(在 artisan list 中显示)
*/
protected $description = '自动关闭 15 分钟内无心跳的开放职务日志(解决掉线不结算问题)';
/**
* 指令入口:将长时间无心跳刷新的开放日志判定为掉线,写入 logout_at 完成结算。
*
* 判定标准updated_at 超过 15 分钟(心跳间隔约 30 秒5 分钟自动存点最长 5 分钟,
* 留足 10 分钟容差,总计 15 分钟无刷新即认为掉线)
*/
public function handle(): int
{
// 15 分钟无心跳 = 掉线判定阈值
$threshold = now()->subMinutes(15);
// 批量关闭符合条件的开放日志,保留现有 duration_seconds
$affected = PositionDutyLog::query()
->whereNull('logout_at')
->where('updated_at', '<=', $threshold)
->update([
'logout_at' => DB::raw('NOW()'),
// 补算最终在线时长,避免日榜 SUM 使用过时的旧值
'duration_seconds' => DB::raw('GREATEST(0, TIMESTAMPDIFF(SECOND, login_at, NOW()))'),
]);
if ($affected > 0) {
$this->info("共关闭 {$affected} 条掉线职务日志。");
} else {
$this->info('无需处理,无掉线日志。');
}
return Command::SUCCESS;
}
}