3
respostas

[Dúvida] Orquestrador de conexões com banco de dados

Olá, tenho um projeto feito com Lumen 10 e estou tentando utilizar o Swoole nele com o pacote 'swooletw/laravel-swoole'. As requisições mais simples estão funcionado e tive um ganho de performance significativo, mas ao fazer requisições que envolvem conexões com múltiplos bancos de dados acabo tendo problemas, pois a query definida no serviço é executada no banco de dados padrão e não no banco retornado pelo orquestrador gerando assim erro SQL.

O orquestrador é a classe pai das models e é no construtor dele que sobrescrevo as configurações de conexão com o banco e reseto a conexão aberta.

Como resolvo isso?

3 respostas

Olá Cristiano! Tudo bem?

Fico feliz em saber que você está experimentando ganhos de performance com o uso do Swoole no seu projeto! Vamos tentar resolver esse problema com as conexões de banco de dados.

O que você descreveu parece estar relacionado à persistência de conexões no contexto de um servidor assíncrono como o Swoole. Quando você utiliza Swoole, as conexões podem ser reutilizadas entre requisições, o que é diferente do comportamento tradicional do PHP, onde cada requisição é isolada.

Aqui estão algumas sugestões para resolver o problema:

  1. Verifique o Orquestrador: Certifique-se de que o orquestrador está configurando corretamente a conexão com o banco de dados antes de cada operação. Isso pode significar que você precisa redefinir a conexão no início de cada requisição ou operação que envolva múltiplos bancos de dados.

  2. Utilize Middleware: Considere implementar um middleware que garanta que a conexão correta seja usada para cada requisição. Este middleware pode ser responsável por definir a conexão com o banco de dados com base nas condições específicas da requisição.

  3. Reset de Conexões: Após cada requisição, especialmente em um contexto de servidor persistente como o Swoole, é importante garantir que as conexões sejam resetadas ou fechadas corretamente para evitar que informações de estado sejam carregadas para a próxima requisição.

  4. Configuração de Ambiente: Verifique se as configurações de ambiente e de conexão estão corretamente definidas para cada banco de dados que você está utilizando. Isso pode incluir variáveis de ambiente que especificam qual banco de dados deve ser usado em diferentes contextos.

  5. Logs e Debugging: Utilize logs para verificar qual banco de dados está sendo conectado em cada requisição. Isso pode ajudar a identificar onde as conexões estão sendo mal configuradas.

Aqui está um exemplo de como você poderia implementar um middleware para gerenciar conexões:

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\DB;

class SetDatabaseConnection
{
    public function handle($request, Closure $next)
    {
        // Defina a lógica para escolher a conexão correta
        $connectionName = $this->getConnectionNameBasedOnRequest($request);

        // Altere a conexão padrão
        config(['database.default' => $connectionName]);

        return $next($request);
    }

    private function getConnectionNameBasedOnRequest($request)
    {
        // Sua lógica para determinar a conexão correta
        return 'nome_da_conexao';
    }
}

Espero que essas dicas ajudem a resolver o problema com as conexões de banco de dados no seu projeto.

Bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

Olá, obrigado pelo retorno!

Eu já havia tentado essa abordagem, mas para o meu caso ela não funciona porque em alguma requisições eu realizo mais de uma operação SQL onde cada operação pode ocorrer em um banco diferente. Se eu definir a conexão com o banco logo no começo da requisição e persistir ela até o final só a primeira operação SQL será executada com sucesso e as outras irão falhar.

Eu já tentei resetar a conexão para trocar de banco uma linha antes da operação SQL, mas não adiantou. O Swoole continuou persistindo a primeira conexão.

Oi, Cristiano!

O problema aqui é a persistência de conexões dentro do contexto do Swoole. Como Swoole mantém conexões abertas entre requisições, simplesmente redefinir a conexão antes de cada operação pode não ser suficiente.

Resolva fazendo o seguinte:

  1. Use conexões explícitas por operação: Em vez de confiar na conexão padrão, defina a conexão diretamente ao executar a query, assim:
DB::connection('nome_da_conexao')->select('sua_query_aqui');
  1. Forçe o reset da conexão no próprio model: Antes de cada operação, resete a conexão explicitamente, evitando que Swoole reutilize a anterior:
DB::purge('nome_da_conexao');
DB::connection('nome_da_conexao')->reconnect();
  1. Utilize DB::disconnect() após cada operação: Isso garante que a conexão não será reaproveitada incorretamente:
DB::disconnect('nome_da_conexao');
  1. Verifique se o orquestrador realmente está sobrescrevendo a conexão antes de cada query. Se ele faz isso no __construct(), tente movê-lo para dentro de um método chamado antes de cada operação.

Veja este ajuste no seu orquestrador:

class Orquestrador
{
    public function setConnectionName($connection)
    {
        DB::purge($connection);
        DB::disconnect($connection);
        DB::setDefaultConnection($connection);
    }

    public function executarQuery($connection, $query)
    {
        $this->setConnectionName($connection);
        return DB::connection($connection)->select($query);
    }
}

Com esse ajuste, antes de cada operação, a conexão correta será configurada e reaproveitamentos indesejados serão evitados.

Fico à disposição.