Rake:rebake falha com erros: PG::ConnectionBad: PQsocket

Migrei um fórum com 200.000 posts para um novo servidor. O site ativo foi colocado em modo somente leitura para que não houvesse tempo de inatividade.

Restaurei o backup em um subdomínio diferente para que os usuários não vissem as telas de instalação ou quaisquer problemas que pudessem ocorrer durante a restauração – algo como dev.example.com.

Assim que a restauração foi concluída, apontei o DNS para o novo servidor e alterei o domínio no arquivo app.yml para o normal forum.example.com.

Então, todos os emoticons nos posts base estavam apontando para o servidor dev.example.com, então executei rake:rebake.

Ele processa cerca de 1.000-2.000 posts antes de travar com erros sobre a conexão com o banco de dados.

Aqui estão alguns trechos:

/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/cli.rb:34:in `dispatch'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/cli.rb:28:in `start'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/exe/bundle:45:in `block in <top (required)>'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/friendly_errors.rb:117:in `with_friendly_errors'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/exe/bundle:33:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'
     1999 / 200968 (  1.0%)
Failed to rebake (topic_id: 78730, post_id: 210607)
PG::ConnectionBad: PQsocket() can't get socket descriptor
/var/www/discourse/lib/tasks/posts.rake:108:in `rebake_posts_all_sites'
/var/www/discourse/lib/tasks/posts.rake:7:in `block in <main>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'

Caused by:
PG::ConnectionBad: PQsocket() can't get socket descriptor

No momento, estou carregando as imagens redirecionando o domínio dev.example.com para o domínio forum.example.com, mas é apenas uma solução temporária.

Alguém sabe como superar esse erro para que eu possa refazer todos os posts? Isso está criando muita carga no banco de dados?

Primeiro, veja Mudar o nome de domínio ou renomear seu Discourse (embora outra solução seja fazer backup e depois restaurar com o novo nome de host).

Minha suposição é que você está ficando sem conexões com o banco de dados, mas esse não é o erro que eu esperaria.

Esta é uma instalação padrão ou você está usando algum outro servidor PG?

Obrigado pelos links. É uma instalação Docker padrão em um droplet DigitalOcean (“Premium AMD”, 4 GB de RAM, 2 vCPUs).

Segui as instruções no link que você mencionou. Encontrei alguns URLs incorretos nas configurações, então os corrigi e reconstruí o fórum novamente para garantir.

Em seguida, executei este tipo de comando:

discourse remap dev.example.com forum.example.com

Esse comando falhou com este tipo de erro:

Error: ERROR:  duplicate key value violates unique constraint "unique_post_links"
DETAIL:  Key (topic_id, post_id, url)=(78821, 207117, https://forum.example.com/t/the-slug/78946/7) already exists.

Então, eu temporariamente deletei um post que linkava para o URL mencionado (https://forum.example.com/t/the-slug/78946/7), executei o comando novamente, e ele funcionou sem falhar.

Depois, executei rake posts:rebake novamente.

Falhou em alguns posts como este, mas continuou (reconstruí o HTML para esses posts manualmente):

Rebaking post markdown for 'default'
     2273 / 200996 (  1.1%)
Failed to rebake (topic_id: 66586, post_id: 210353)
JavaScript was terminated (either by timeout or explicitly)

Finalmente, ele falhou pouco antes de atingir 11.000 posts com erros como este:

/usr/local/bin/bundle:25:in `<main>'
    10996 / 200996 (  5.5%)
Failed to rebake (topic_id: 76678, post_id: 200988)
PG::ConnectionBad: PQsocket() can't get socket descriptor
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.4.1/lib/active_record/connection_adapters/postgresql_adapter.rb:768:in `block (2 levels) in exec_no_cache'

O servidor inteiro parece ter ficado offline porque fui alertado pelo Uptime Robot que o site estava fora do ar.

Você acha que o servidor não é potente o suficiente para executar esse comando? :thinking:

Ele está rodando com mais de 80% de RAM normalmente, e atinge 100% enquanto o comando está em execução. Talvez tenha ficado sem memória.

Se você tiver um disco local, poderá adicionar swap, o que evitaria a exaustão da memória (independentemente de essa ser ou não a causa do problema aqui). O que free informa? Você vê oom ou memory na saída de dmesg?

No momento, ele diz:

              total        used        free      shared  buff/cache   available
Mem:           3.8Gi       2.1Gi       160Mi       1.0Gi       1.6Gi       488Mi
Swap:             0B          0B          0B

Eu não vejo oom, mas a palavra memory aparece em alguns lugares sobre reservar e liberar memória.

O servidor foi criado com 4GB de RAM, então o Discourse não criou automaticamente um arquivo de swap. Você acha que vale a pena adicionar?

Se você tiver espaço em disco, certamente vale a pena adicionar cerca de 2G de swap.

A outra coisa a fazer é monitorar o uso enquanto seu trabalho grande estiver em execução. Eu usaria vmstat 5 5 e talvez registrar em um arquivo. Você espera não ver valores grandes nas colunas si ou so, e não ver a coluna swpd chegar perto do tamanho do seu swap.

Talvez veja esta postagem:

(Parece possível que o sistema de banco de dados esteja ficando sem algum recurso, mas não sei nada sobre isso.)

Obrigado, tentarei essas coisas ainda hoje. Tenho 50 GB livres no momento.

Adicionei um swapfile de 2GB, e isso parece ter resolvido. A reconstrução está apenas 20% concluída, mas não houve um único erro ainda, e o uso de RAM está um pouco abaixo de 100%.

Obrigado a ambos pela ajuda.

Parece bom! Só para constar

  • você poderia adicionar mais swap, mesmo enquanto a tarefa está em execução, se vmstat ou free (ou top) mostrarem que o swap está se esgotando.
  • se você for cuidadoso, provavelmente poderia fazer um upgrade temporário reversível para uma instância com mais RAM, o que custará um pouco de dinheiro, mas só precisará ficar em vigor por algumas horas. É importante não mudar para uma instância com disco maior, pois isso não é reversível. (Mais RAM deve permitir que as coisas funcionem na velocidade máxima, enquanto RAM modesta e muito swap podem ter uma penalidade de desempenho, e a tarefa levará mais tempo para ser concluída.)

Pensei nisso, mas teria que desligar o servidor, e os usuários já tiveram um período irritante de “somente leitura” e tempo de inatividade quando mudei de servidor. :sweat:

Não consegui terminar ontem à noite porque tive que ir dormir, mas já está funcionando novamente. 30% até agora sem erros.

Fique de olho nas coisas com o vmstat ou similar - esse é um trabalho de execução tão longa que você não vai querer ter que reiniciá-lo. Eu provavelmente adicionaria mais 2G de swap, para garantir.

Obrigado, verifiquei com vmstat ocasionalmente. Eu o iniciei em uma sessão tmux para que pudesse desanexar e fechar meu laptop por um tempo. Provavelmente levou de 8 a 9 horas para executar o comando, mas tudo foi concluído sem erros.