You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel队列任务handle方法数据无法插入数据库求助

Laravel队列任务数据无法持久化到数据库问题排查

问题描述

Laravel项目中创建了一个队列任务,负责调用外部API并将响应数据写入数据库。目前任务其他逻辑(API调用、日志输出)正常执行,但数据始终无法持久化到数据库,无任何报错信息。

任务代码

public function __construct($dados, WgClient $model)
{
    $this->dados = $dados;
    $this->model = $model;        
}

public function handle()
{
    try {
        $dataWG = [
            'tipo' => 'interface',
            'data' => $this->data
        ];
        
        $response = Http::post('http://my.api.ip.address:port/login', [  
            'username' => '*',
            'password' => '*',
        ]);


        if (!isset($response->json()['access_token'])) 
                throw new Exception("Erro na autenticação");

        $token = $response->json()['access_token'];

        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . $token,
        ])->post('http://my.api.ip.address:port/criar', $dataWG);

        $response = json_decode($response, true);

        $this->model->name = $response['name'];
        $this->model->network = $response['network'];
        $this->model->public_key = $response['public_key'];
        $this->model->private_key = $response['private_key'];
        $this->model->port = $response['port'];
        $this->model->company = 13;
        $this->model->save();

    } catch (\Throwable $th) {
        throw $th;
    }
}

任务调用方式

$data = $request->all();
$model = new WgClient;
CreateWgInterfaceJob::dispatch($data, $model);

队列配置

queue.php中的Redis配置

'redis' => [
    'driver' => 'redis',
    'connection' => 'default',
    'queue' => env('REDIS_QUEUE', 'default'),
    'retry_after' => 90,
    'block_for' => null,
    'after_commit' => false,
],

horizon.php中的Supervisor配置

'defaults' => [
    'supervisor-1' => [
        'connection' => 'redis',
        'queue' => ['default'],
        'balance' => 'simple',
        'autoScalingStrategy' => 'time',
        'maxProcesses' => 1,
        'maxTime' => 0,
        'maxJobs' => 0,
        'memory' => 128,
        'tries' => 1,
        'timeout' => 60,
        'nice' => 0,
    ],
],

Docker Compose配置

version: '3'

services:
  db:
    container_name: 'mysql_accessmanager'
    image: mysql
    restart: always
    ports:
      - 3306:3306
    env_file:
      - ./config/db.env
    volumes:
      - ./config/CreateDBs.sql:/docker-entrypoint-initdb.d/1.sql
      - ./db:/var/lib/mysql
    networks:
      - netaccessmanager

  accessmanager:
    container_name: 'accessmanager'
    image: docker.io/bitnami/laravel:9
    restart: always
    ports:
      - 4727:8000
    env_file:
      - ./config/laravel.env  
    environment:
      - DB_DATABASE=db_accessmanager
    volumes:
      - ./laravel/accessmanager:/app
    depends_on:
      - db
    networks:
      - netaccessmanager
  
  fila_accessmanager:
    container_name: 'fila_accessmanager'
    image: docker.io/bitnami/laravel:9
    restart: always
    env_file:
      - ./config/laravel.env  
    environment:
      - DB_DATABASE=db_accessmanager
    volumes:
      - ./laravel/accessmanager:/app
    entrypoint: ["bash", "-c", "php artisan horizon"]
    depends_on:
      - accessmanager
    networks:
      - netaccessmanager

  agenda_accessmanager:
    container_name: 'agenda_accessmanager'
    image: docker.io/bitnami/laravel:9
    restart: always
    env_file:
      - ./config/laravel.env  
    environment:
      - DB_DATABASE=db_accessmanager
    volumes:
      - /mnt/efs-data/docker/accessmanager/laravel/accessmanager:/app
    entrypoint: ["bash", "-c", "php artisan schedule:work"]
    depends_on:
      - accessmanager
    networks:
      - netaccessmanager

  phpmyadmin:
    container_name: 'phpmyadmin_accessmanager'
    image: phpmyadmin/phpmyadmin:latest
    restart: always
    env_file:
      - ./config/phpmyadmin.env
    ports:
      - "1004:80"
    networks:
      - netaccessmanager

  redis:
    container_name: 'redis_accessmanager'
    image: redis
    restart: always
    ports:
      - 6379:6379
    volumes:
      - ./redis:/data
    networks:
      - netaccessmanager

networks:
    netaccessmanager:

已尝试的方案

  • 在handle方法中添加Log::info(),运行queue:work后日志正常输出,确认任务已执行
  • 尝试过Stack Overflow上的相关解决方案
  • 测试过开启/关闭SerializesModels特性,结果一致

问题分析与解决方案

1. 模型实例序列化异常

队列任务会序列化传入的模型实例,在队列进程反序列化时,可能丢失数据库连接上下文或实例状态,导致save()静默失败。

解决方法:不在构造函数中传入模型实例,改为在handle方法内部创建新实例:

// 修改任务构造函数
public function __construct($dados)
{
    $this->dados = $dados;
}

// 修改handle方法
public function handle()
{
    // ... 原有API调用逻辑 ...
    
    // 内部创建模型实例
    $model = new WgClient();
    $model->name = $response['name'];
    $model->network = $response['network'];
    $model->public_key = $response['public_key'];
    $model->private_key = $response['private_key'];
    $model->port = $response['port'];
    $model->company = 13;
    $model->save();
}

同时更新任务调用代码:

$data = $request->all();
CreateWgInterfaceJob::dispatch($data);

2. 模型验证或填充规则问题

如果$response中的数据不符合模型的验证规则,或者模型未设置$fillable允许批量赋值,save()会返回false但不抛出异常。

解决方法:

  • 确保模型的$fillable包含所有要赋值的字段:
class WgClient extends Model
{
    protected $fillable = ['name', 'network', 'public_key', 'private_key', 'port', 'company'];
}
  • 添加保存结果判断,输出错误日志:
if (!$model->save()) {
    Log::error('WgClient保存失败', $model->getErrors()->toArray());
    throw new Exception('无法保存WgClient数据');
}

3. 队列进程数据库连接问题

Docker环境中,队列容器可能存在数据库连接异常(如网络不通、权限不足),但未抛出异常导致静默失败。

解决方法:

  • 进入队列容器执行php artisan tinker,手动创建并保存WgClient实例,验证连接是否正常
  • 检查laravel.env中的数据库主机配置,确保使用容器名db而非localhost或127.0.0.1
  • 确认数据库用户拥有从队列容器所在网络访问数据库的权限

4. 队列事务提交时机问题

当前队列配置after_commit为false,如果任务在事务中被分发,可能会在事务提交前执行,导致数据无法持久化。

解决方法:

  • 修改队列配置中的after_commit为true:
'redis' => [
    // ... 其他配置 ...
    'after_commit' => true,
],
  • 或在分发任务时指定afterCommit():
CreateWgInterfaceJob::dispatch($data)->afterCommit();

内容的提问来源于stack exchange,提问作者Moisés S. Oliveira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 23:39:50