031055-修复农场灾害生成空指针异常和WebHook处理器注册问题.md 4.8 KB

修复农场灾害生成空指针异常和WebHook处理器注册问题

任务时间: 2025年07月03日 10:55-11:35
任务类型: Bug修复
模块: Farm/DisasterLogic, ThirdParty/WebhookDispatchService

任务描述

修复两个关键问题:

  1. 农场灾害生成过程中的空指针异常
  2. URS WebHook处理器注册丢失问题

问题1:农场灾害生成空指针异常

错误详情

  • 错误位置: app/Module/Farm/Logics/DisasterLogic.php 第386行
  • 错误信息: Attempt to read property "buffs" on null
  • 涉及作物: ID 890,关联用户ID 9999(不存在)
  • 错误代码: $activeBuffs = $crop->user->buffs->pluck('buff_type')->toArray();

根本原因

作物数据中存在孤儿记录,关联的用户不存在,导致 $crop->user 返回 null

修复方案

generateDisasters 方法中添加用户存在性检查:

// 检查用户是否存在,如果不存在则跳过
if (!$crop->user) {
    $crop->save(); // 仍需更新检查时间
    Log::warning('作物关联的用户不存在,跳过灾害生成', [
        'crop_id' => $crop->id,
        'user_id' => $crop->user_id
    ]);
    return 'skipped';
}

测试结果

  • 命令执行成功:docker exec -it kku_laravel php artisan farm:generate-disasters
  • 日志显示正确处理:跳过了作物890(用户9999不存在)
  • 无空指针异常,系统稳定运行

问题2:URS WebHook处理器注册丢失

问题描述

用户报告:"包 urs 的处理器 register_farm_user 不存在"

调查过程

  1. 初步分析: 以为是签名验证问题
  2. 深入调查: 发现处理器确实存在且已注册
  3. 根本原因: 静态变量 $packageHandlers 在某些情况下被重置

技术细节

  • 处理器类 UrsRegisterFarmUserWebhook 存在且正确
  • UrsServiceProvider 中已正确注册
  • 问题出现在运行时静态变量丢失

修复方案

WebhookDispatchService::dispatch 方法中添加自动重新注册机制:

// 获取处理器类
$handlerClass = $this->getPackageHandler($packageName, $handlerRoute);

if (!$handlerClass) {
    // 尝试重新注册处理器(防止静态变量被重置的情况)
    $this->tryReregisterPackageHandlers($packageName);
    $handlerClass = $this->getPackageHandler($packageName, $handlerRoute);
    
    if (!$handlerClass) {
        throw new \Exception("包 {$packageName} 的处理器 {$handlerRoute} 不存在");
    }
}

添加 tryReregisterPackageHandlers 方法:

protected function tryReregisterPackageHandlers(string $packageName): void
{
    try {
        switch ($packageName) {
            case 'urs':
                if (class_exists('\ThirdParty\Urs\UrsServiceProvider')) {
                    $provider = new \ThirdParty\Urs\UrsServiceProvider(app());
                    $provider->boot();
                    Log::info("重新注册URS包处理器成功");
                }
                break;
            default:
                Log::warning("未知包名,无法重新注册处理器", ['package_name' => $packageName]);
                break;
        }
    } catch (\Exception $e) {
        Log::error("重新注册包处理器失败", [
            'package_name' => $packageName,
            'error' => $e->getMessage()
        ]);
    }
}

测试验证

  1. 清空处理器注册: 使用 clearAllHandlers() 模拟问题
  2. 测试自动恢复: 发送WebHook请求触发自动重新注册
  3. 验证结果: 错误信息从"处理器不存在"变为正确的"签名验证失败"

文件变更

修改文件

  1. app/Module/Farm/Logics/DisasterLogic.php - 添加用户存在性检查
  2. app/Module/ThirdParty/Services/WebhookDispatchService.php - 添加自动重新注册机制

提交信息

第一次提交

修复农场灾害生成空指针异常

- 在DisasterLogic::generateDisasters方法中添加用户存在性检查
- 当作物关联的用户不存在时,记录警告日志并跳过该作物
- 避免访问null对象的buffs属性导致的异常
- 修复作物ID 890关联用户ID 9999不存在的问题

第二次提交

修复WebHook处理器注册丢失问题

- 在WebhookDispatchService中添加自动重新注册机制
- 当处理器不存在时,尝试重新注册该包的处理器
- 解决静态变量被重置导致的'处理器不存在'错误
- 添加tryReregisterPackageHandlers方法支持URS包自动重新注册
- 测试验证:清空处理器后能自动恢复注册状态

总结

成功修复了两个关键问题:

  1. 农场灾害生成: 通过添加用户存在性检查,避免了空指针异常
  2. WebHook处理器: 通过自动重新注册机制,解决了处理器丢失问题

两个修复都经过了充分的测试验证,确保系统稳定性和可靠性。