Tentativa de recriar canal de chat excluído com o mesmo nome (ainda) falha

Continuando a discussão de Falha ao recriar canal de chat excluído com o mesmo nome:

Este bug foi relatado no tópico vinculado, mas parece persistir para mim. Estou na versão mais recente, fiz um git pull e reconstruí o launcher ontem.

Ao tentar nomear um novo canal de chat com qualquer nome de canal de chat usado anteriormente, ocorre um erro 500 no console JS.

Nos logs de erro do Discourse, recebo:

Falha ao tratar exceção no middleware de exceção: ActiveRecord::RecordNotUnique : PG::UniqueViolation: ERROR:  violação de chave duplicada viola a restrição de chave única "index_chat_channels_on_slug"
DETALHE:  A chave (slug)=(sec-fhir) já existe.

No console do Rails, posso ver que os ChatChannels excluídos desapareceram, mas suspeito que em algum lugar o slug excluído permaneça em um índice ou em alguma outra dependência do banco de dados e não tenha sido excluído.

Esta solução alternativa não funciona para mim, ao tentar renomear “foo2” para “foo”, recebo o mesmo erro 500, devido à falha na restrição de exclusividade do slug.

Não tenho certeza de como excluir com segurança os slugs (indexados?) de ChatChannels excluídos, mas estaria disposto a tentar.


Possivelmente relacionado: este problema que também afeta slugs, mas não parece ser o mesmo problema: Attempt to recreate deleted chat channel with same name fails

2 curtidas

Acabei de testar o seguinte agora e não tive problemas:

  1. Crie um canal com o nome “whiskers” e o slug “whiskers”
  2. Exclua o canal
  3. Crie um canal com o nome “whiskers” e o slug “whiskers”

Isso funcionou.

Quando o canal é excluído (etapa 2), o slug é alterado automaticamente para algo exclusivo. Mas como você excluiu seu canal antes que essa alteração fosse introduzida, o slug antigo pode ainda estar por aí.

Você provavelmente pode atualizar manualmente o slug do canal excluído através do console do Rails, mas não tenho certeza de qual é a instrução correta. Vou perguntar.

Observe também que os slugs de canal agora podem ser editados independentemente do nome do canal, portanto, como solução alternativa, você também pode criar um canal com o nome desejado hoje e escolher um slug diferente que não entre em conflito.

2 curtidas

Isso é super inesperado.

Nós não excluímos canais, apenas os excluímos logicamente. Portanto, eles ainda deveriam estar aqui com a coluna deleted_at preenchida.

Se você executar isso no seu console, não obterá resultados?

ChatChannel.find_by(slug: "sec-fhir")
[1] pry(main)> ChatChannel.find_by(slug: "sec-fhir")
=> nil

Posso confirmar que este teste também funciona para mim na minha instância, que está totalmente atualizada.

Acho que o problema é que em algum lugar no banco de dados existe algum slug “pendurado” que deveria ter sido excluído, mas não foi, talvez tenha havido um bug em uma versão anterior que agora foi corrigido. O Chat só foi ativado nesta instância há 17 dias, então qualquer bug teria que ter estado ativo nesse período.

1 curtida

Não consigo reproduzir isso de forma alguma. Depois de fazer um backup do banco de dados, talvez você possa tentar o seguinte no console do Rails. Parece surpreendente, no entanto.

[1] pry(main)> DB.exec("DROP INDEX IF EXISTS index_chat_channels_on_slug;")
[2] pry(main)> DB.exec("CREATE UNIQUE INDEX index_chat_channels_on_slug ON chat_channels(slug);")

Verifiquei e isso é esperado, pois excluímos registros com deleted_at preenchido, mesmo com find_by:

ChatChannel.find_by(slug: "sec-fhir")
  ChatChannel Load (0.4ms)  SELECT "chat_channels".* FROM "chat_channels" WHERE "chat_channels"."deleted_at" IS NULL AND "chat_channels"."slug" = 'sec-fhir' LIMIT 1
=> nil

Você precisará fazer isso em vez disso (adicionando with_deleted):

ChatChannel.with_deleted.find_by(slug: "sec-fhir")
  ChatChannel Load (0.3ms)  SELECT "chat_channels".* FROM "chat_channels" WHERE "chat_channels"."slug" = 'sec-fhir' LIMIT 1
=> #<CategoryChannel:0x00007fc9bfb4abf0
 id: 124,
 chatable_id: 19,
 deleted_at: Wed, 15 Feb 2023 01:19:20.982181000 UTC +00:00,
 deleted_by_id: nil,
 featured_in_category_id: nil,
 delete_after_seconds: nil,
 chatable_type: "Category",
 created_at: Fri, 13 Jan 2023 01:46:43.730329000 UTC +00:00,
 updated_at: Wed, 15 Feb 2023 01:19:56.427647000 UTC +00:00,
 name: "test channel",
 description: "",
 status: "archived",
 user_count: 1,
 last_message_sent_at: Fri, 13 Jan 2023 01:46:51.130903000 UTC +00:00,
 auto_join_users: false,
 user_count_stale: false,
 slug: "sec-fhir",
 type: "CategoryChannel",
 allow_channel_wide_mentions: true,
 messages_count: 0,
 threading_enabled: false>

Portanto, para limpar o antigo slug do canal excluído, faça algo como isto:

channel = ChatChannel.with_deleted.find_by(slug: "sec-fhir")
channel.update!(slug: "#{channel.deleted_at.strftime("%Y%m%d-%H%M")}-#{channel.slug}-deleted")

Talvez precisemos de uma migração para corrigir isso, @mcwumbly e @j.jaffeux?

2 curtidas

Ah sim, esqueci do with_deleted neste caso :+1:

Sugiro que deixemos sua resposta aqui por enquanto. Deve ser um caso raro: excluído antes da correção + quer recriar com o mesmo nome.

4 curtidas

Obrigado pelo acima. Eu não sabia sobre with_deleted, mas isso me permitiu ver as instâncias excluídas e renomear seus slugs de acordo com seu snippet.

Posso confirmar que isso foi corrigido. Concordaria com @j.jaffeux que isso provavelmente não está afetando muitos usuários, então eu diria que é o suficiente que uma correção no console Rails esteja aqui no tópico.

3 curtidas

Excelente, bom saber que resolveu para você, Marcus. Encerrando este tópico agora.

2 curtidas

Ao tentar criar um novo canal (nomeado “geral”, o mesmo para o slug), o seguinte erro aparece nos logs (nada está acontecendo no frontend).

Nenhum canal “Fechado” é exibido.

Eu posso ter tido um canal geral no passado - e provavelmente o deletei (é o padrão?)

Não consigo reproduzir com outro slug aleatório (criar > deletar > criar funciona perfeitamente).

Falha ao lidar com a exceção no middleware de exceção: ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERRO:  violação de chave duplicada viola a restrição de chave exclusiva "index_chat_channels_on_slug"
DETALHE:  A chave (slug)=(general) já existe.

Eu transferi sua postagem para cá para manter os relatórios agrupados. :+1:

A solução alternativa acima seria adequada no seu caso também?

A solução alternativa em OP, não, não funcionou.

Isso também não pareceu funcionar para mim.

[1] pry(main)> ChatChannel.find_by(slug: "general")
NameError: uninitialized constant ChatChannel
from (pry):1:in `__pry__'

A solução alternativa para o problema do OP está neste post:

2 curtidas

Eu tentei estes, é sobre isso que era o meu bloco de código compartilhado.

Falhei em executar esses comandos no rails.

Talvez eu esteja fazendo algo errado aqui?

EDIT: para ser claro, a solução alternativa sugerida gera o mesmo erro ao procurar o canal

[7] pry(main)> ChatChannel.with_deleted.find_by(slug: "general")
NameError: uninitialized constant ChatChannel
from (pry):7:in `__pry__'
2 curtidas

Tudo bem, consegui resolver o problema (pelo menos, acho que sim).

Para mim, foi um pouco complicado descobrir tudo isso, então vou compartilhar os passos completos.

cd /var/discourse & ./launcher enter app
rails c
DB.exec("UPDATE chat_channels SET slug = 'new' WHERE slug = 'old';")

Então, no seu console do Rails, isso ficará assim:

[1] pry(main)> DB.exec("UPDATE chat_channels SET slug = 'new' WHERE slug = 'old';")
=> 1
[2] pry(main)> exit
root@discourse-app:~# exit
logout
➜ discourse git:(main) ✗

Agora sou capaz de criar um novo canal com o slug desejado.

Este é o caminho (ou um dos caminhos) correto?

2 curtidas

A solução alternativa que falhou acima deve-se a algum namespace que introduzimos há semanas. ChatChannel agora é Chat::Channel

1 curtida

Eu estava esperando algo assim, mas não consegui encontrar. Espero que minha alteração no banco de dados seja uma boa solução alternativa também? Até agora, sem problemas.

2 curtidas