待定中 2024-06-13 11:35 采纳率: 66.7%
浏览 22
已结题

(标签-laravel|关键词-App)

laravel8 使用队列触发给用户发订阅通知一直报:

local.ERROR: App\Jobs\PostServerMsg has been attempted too many times or run too long. The job many
但是我这个功能又是正常的,微信用户也能收到订阅的通知消息,只是日志里一直会提示这个错误信息。
系统用的宝塔的lnmp,用了进程管理守护器。
我自己找了很久都没解决问题,也在网上搜索了下也没解决,有人知道是什么情况吗?求指导一下代码如下:
这个是队列里的代码

public function handle()
    {
        try {
            $base = new BaseController();
            $res = $base->post_msg($this->info);
            if (empty($res)) {
                throw new \Exception($res);
            }
            $res = json_decode($res,true);
            exit($res['errmsg']);
        }catch (\Exception $e){
            exit($e->getMessage());
        }

    }

这个是对应的操作

function post_msg($info){
        //用户id、预约单id
        $wx_id = DB::table('users')->where(['id'=>$info['user_id']])->value('wx_id');
        // $wx_id = User::query()->where(['id'=>$info['user_id']])->value('wx_id');
        // 传递一个闭包,如果数据不存在
        $token = Cache::get('AccessToken', function() {
            $res = $this->GetAccessToken();
            $expiresAt = Carbon::now()->addSeconds($res['expires_in']);
            Cache::put('AccessToken', $res['access_token'], $expiresAt);
            return $res['access_token'];
        });
        $url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token='.$token;
        $template_id = $info['template_id'];
        $arr = [
            'touser'=>$wx_id,
            'template_id'=>$template_id,
            'page'=>$info['page'],
            "miniprogram_state"=>"formal",//eveloper为开发版;trial为体验版;formal为正式版;默认为正式版
            "lang"=>"zh_CN",
            'data'=>$info['data'],
        ];
        $arr = json_encode($arr);
        $res = $this->https_curl($url,'post','json',$arr);
        return $res;
    }

  • 写回答

2条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-06-13 11:35
    关注

    引自免费微信小程序:皆我百晓生

    从你提供的代码来看,Laravel 队列处理任务时抛出的错误“App\Jobs\PostServerMsg has been attempted too many times or run too long.”通常意味着队列处理器尝试执行任务的次数超过了允许的最大重试次数,或者单个任务运行的时间超过了设定的超时时间。

    在 Laravel 中,队列任务的重试次数和超时时间可以在配置文件 config/queue.php 中进行设置。具体来说,你可以检查或修改以下配置项:

    1. 重试次数:在队列连接配置中,你可以找到 retry_after 参数,它定义了在任务失败后等待多少秒再次尝试。此外,还有 max_attempts 参数,用于指定任务最多可以尝试多少次。例如:

      'database' => [
          'driver' => 'database',
          'table' => 'jobs',
          'retry_after' => 60,
          'block_for' => null,
          'max_attempts' => 3, // 这里可以调整最大尝试次数
      ],
      
    2. 超时时间:在同一个配置文件中,timeout 参数定义了任务运行的最大时间(以秒为单位)。如果任务运行时间超过这个值,将被终止并可能被视为失败。

      'default' => env('QUEUE_CONNECTION', 'sync'),
      'connections' => [
          'sync' => [
              'driver' => 'sync',
              'timeout' => 60, // 这里可以调整超时时间
          ],
          // 更多连接配置...
      ],
      

    回到你的代码,有几个点需要注意:

    • handle() 方法中,你使用 exit() 来结束脚本。这通常不是一个好习惯,因为 Laravel 的队列工作器期望任务返回结果,而不是简单地终止脚本。你应该改为使用 return 语句。
    • 你捕获异常并立即退出,没有给队列工作器机会重新尝试任务。考虑移除 exit() 并让异常自然传播,这样队列系统可以根据配置自动重试任务。
    • 确保你的 https_curl() 函数正确处理了 HTTP 请求,并且在请求失败时返回了一个可识别的错误响应,以便于 post_msg() 函数能够正确处理异常。

    下面是一个修改后的 handle() 方法示例,使用了 throw 而不是 exit(),并且更优雅地处理了异常:

    public function handle()
    {
        try {
            $base = new BaseController();
            $res = $base->post_msg($this->info);
            if (empty($res)) {
                throw new \Exception("Empty response received.");
            }
            $res = json_decode($res, true);
            if ($res['errcode'] !== 0) {
                throw new \Exception("WeChat API returned an error: {$res['errmsg']}");
            }
            return $res['errmsg']; // 返回成功信息
        } catch (\Exception $e) {
            throw $e; // 让异常向上抛出,允许队列工作器重试
        }
    }
    

    同时,检查你的 post_msg() 函数确保它正确处理了所有可能的错误场景,包括但不限于网络请求失败、API 调用错误等。确保异常被捕获并适当地向外抛出,这样队列系统才能根据配置自动重试任务。

    如果问题仍然存在,进一步的调试可能涉及查看具体的错误信息,检查网络请求的详细情况,以及确认微信 API 的调用是否始终成功。使用 Laravel 的日志记录功能可以帮助你收集更多关于失败任务的信息。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 6月25日
  • 已采纳回答 6月17日
  • 创建了问题 6月13日