针对日志并发问题,在自动存点中增加Redis分布式冷却锁,杜绝进程重复触发导致经验暴涨,完善单元测试

This commit is contained in:
pllx
2026-07-06 22:43:32 +08:00
parent a20bcf13be
commit 01a8e116a3
2 changed files with 43 additions and 1 deletions
+32
View File
@@ -155,4 +155,36 @@ class AutoSaveExpCommandTest extends TestCase
$user->refresh();
$this->assertEquals(15, $user->exp_num);
}
/**
* 测试自动存点命令会通过 Redis 冷却锁,防止在短时间内并发重复调度执行。
*/
public function test_auto_save_cooldown_prevents_overlapping_process(): void
{
Sysparam::updateOrCreate(['alias' => 'exp_per_heartbeat'], ['body' => '5']);
Cache::flush();
$room = Room::create(['room_name' => 'cd']);
$user = User::factory()->create([
'username' => 'cooldown-user',
'exp_num' => 10,
]);
Redis::hset("room:{$room->id}:users", $user->username, json_encode(['username' => $user->username], JSON_UNESCAPED_UNICODE));
Redis::setex("room:{$room->id}:alive:{$user->username}", 90, 1);
// 第一次执行自动存点
$this->artisan('chatroom:auto-save-exp')->assertSuccessful();
// 验证第一次加了经验 (10 + 5 = 15)
$user->refresh();
$this->assertEquals(15, $user->exp_num);
// 紧接着在冷却时间内(200秒内)模拟第二次并发执行
$this->artisan('chatroom:auto-save-exp')->assertSuccessful();
// 验证因为有 Redis 冷却锁,第二次执行被拦截,经验仍为 15,并未再次增加
$user->refresh();
$this->assertEquals(15, $user->exp_num);
}
}