告诉 Laravel 在 X 秒后停止尝试连接

问题描述

我有一个使用两个数据库连接的 Laravel 应用。

一个总是可以访问的(并且是我环境中的认配置)。

一个是远程的,可能无法访问(这是它的预期行为)。

只能通过按钮访问第二个数据库。我希望只有在可以访问数据库时才启用此按钮。

为此,我使用了一个简单的 Livewire 组件来检查 DB::('second_db')->getPdo();

这是我的组件

// blade
<button wire:init="loaddisabled" class="..." {{ $this->disabled ? 'disabled' : '' }}>
    Access DB
</button>

// Component class
public $disabled = true;

function loaddisabled()
{
   try {
       DB::connection('second_db')->getPdo();
   } catch (PDOException $e) {
       $this->disabled = true;
   }
   $this->disabled = false;
}

public function render()
{
   return view('livewire.my-component');
}

使用 Tinker 时,我在几秒钟后尝试了 DB::connection('second_db')->getPdo();(在我看来很多),我得到了 PDOException with message 'sqlSTATE[HY000] [335544721] Unable to complete network request to host "...",因为数据库处于离线状态(这是我所期望的)但是当我尝试它时网页包含我的 livewire 组件,我从 504 Gateway time-out

得到了一个 Nginx

我什至尝试用 catch(Exception $e) 捕捉任何异常,但同样的事情发生了

我深入挖掘后发现这是认的 valet-linux 配置造成的。

当我寻找解决方案时,每个人都建议增加超时时间,但我不想要!

我想告诉我的程序做什么:

  1. 尝试 X 秒(比如 5 秒或更短)以获取 pdo
  2. 如果有效,很好,给我真实的
  3. 如果没有,就抛出 PDOException(或者任何更适合这种情况的异常)
  4. 让我处理 catch 块中的异常

基本上,我希望我的应用程序在触发 Nginx 错误之前“决定停止”,因为我知道一个事实,如果它需要那么长时间,那就是我的数据库无法访问,这就是我寻找。

解决方法

您可以进行并行处理。尝试使用 Laravel 队列并将结果传递给 Notification 实例,该实例将通过您的按钮元素反映出来。可能需要 3-5 秒左右。

您也可以采用异步方式。 spatie/async 包可以帮助您并行运行代码,因此您可以连接到数据库并同时跟踪时间。如果时间过去了,你总是可以抛出异常。

使用 spatie/async,您的代码看起来更像这样:

$pool
->add(function () {
    // Attempt your database connection
})
->then(function ($output) {
    // when successful,update livewire component
})
->catch(function ($exception) {
    // if you have a custom timeout exception,here's the best place
})
->timeout(function () {
    // or you let the package handle the timeout,perform your timeout action here 
});

在此处了解更多信息:https://github.com/spatie/async#asynchronous-and-parallel-php

如果您想要更多的本机控制,它可能会引导您进行一些严肃的 PHP 代码操作,我建议您从这里开始:https://www.php.net/manual/en/function.set-time-limit.php#115057