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
相关产品推荐
相关产品推荐

