Tentative de recréation du canal de discussion supprimé avec le même nom (toujours) échoue

Continuant la discussion de Tentative de recréer un canal de chat supprimé avec le même nom échoue :

Ce bug a été signalé dans le fil de discussion lié mais semble toujours persister pour moi. Je suis sur la dernière version, j’ai fait un git pull et reconstruit le lanceur hier.

Lorsque j’essaie de nommer un nouveau canal de chat avec un nom de canal de chat précédemment utilisé, il y a une erreur 500 dans la console JS.

Dans les journaux d’erreurs de Discourse, j’obtiens :

Failed to handle exception in exception app middleware : ActiveRecord::RecordNotUnique : PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_chat_channels_on_slug"
DETAIL:  Key (slug)=(sec-fhir) already exists.

Dans la console Rails, je peux voir que les ChatChannels supprimés ont disparu, mais je soupçonne que quelque part le slug supprimé reste dans un index ou dans une autre dépendance de la base de données et n’a pas été supprimé.

Cette solution de contournement ne fonctionne pas pour moi, lorsque j’essaie de renommer “foo2” en “foo”, j’obtiens la même erreur 500, en raison de la contrainte d’unicité échouée sur le slug.

Je ne suis pas sûr de la manière de supprimer en toute sécurité les slugs (indexés ?) des ChatChannels supprimés, mais je serais prêt à essayer.


Possiblement lié : ce problème qui affecte également les slugs, mais il ne semble pas s’agir du même problème : Attempt to recreate deleted chat channel with same name fails

2 « J'aime »

Je viens de tester ce qui suit et je n’ai eu aucun problème :

  1. Créer un canal nommé « whiskers » avec le slug « whiskers »
  2. Supprimer le canal
  3. Créer un canal nommé « whiskers » avec le slug « whiskers »

Cela a fonctionné.

Lorsque le canal est supprimé (étape 2), le slug est automatiquement modifié pour quelque chose d’unique. Mais comme vous avez supprimé votre canal avant l’introduction de cette modification, l’ancien slug pourrait encore traîner.

Vous pouvez probablement mettre à jour manuellement le slug du canal supprimé via la console Rails, mais je ne suis pas sûr de la bonne formule. Je vais me renseigner.

Notez également que les slugs de canal peuvent désormais être modifiés indépendamment du nom du canal, donc comme solution de contournement, vous pourriez également créer aujourd’hui un canal avec le nom souhaité et choisir un slug différent qui ne pose pas de conflit.

2 « J'aime »

C’est très inattendu.

Nous ne supprimons pas les canaux, nous les supprimons uniquement de manière logique. Ils devraient donc toujours être là avec la colonne deleted_at remplie.

Si vous exécutez ceci dans votre console, vous n’obtenez aucun résultat ?

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

Je peux confirmer que ce test fonctionne également pour moi sur mon instance, qui est entièrement à jour.

Je pense que le problème est qu’il y a quelque part dans la base de données un slug qui traîne et qui aurait dû être supprimé, mais qui ne l’a pas été. Il y a peut-être eu un bug dans une version précédente qui est maintenant corrigé. Le chat n’est activé sur cette instance que depuis 17 jours, donc tout bug aurait dû être actif dans ce laps de temps.

1 « J'aime »

Impossible de reproduire cela de quelque manière que ce soit. Après avoir effectué une sauvegarde de la base de données, vous pourrez peut-être essayer ceci dans la console Rails. Cela semble surprenant cependant.

[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);")

J’ai vérifié et c’est en fait ce à quoi il fallait s’attendre, car nous excluons les enregistrements avec deleted_at rempli même avec 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

Vous devrez faire ceci à la place (en ajoutant 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>

Donc, pour nettoyer l’ancien slug de canal supprimé, faites quelque chose comme ceci :

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

Peut-être avons-nous besoin d’une migration pour corriger cela @mcwumbly et @j.jaffeux ?

2 « J'aime »

Ah oui, c’est vrai, j’avais oublié le with_deleted dans ce cas :+1:

Je suggère que nous laissions votre réponse ici pour l’instant. Cela devrait être un cas rare : supprimé avant la correction + volonté de recréer avec le même nom.

4 « J'aime »

Merci pour ce qui précède. Je ne connaissais pas with_deleted mais cela m’a permis de voir les instances supprimées et de renommer leurs slugs comme dans votre extrait.

Je peux confirmer que cela est corrigé. Je suis d’accord avec @j.jaffeux sur le fait que cela n’affecte probablement pas beaucoup d’utilisateurs, donc je dirais qu’il suffit qu’une correction dans la console Rails soit présente dans le fil de discussion.

3 « J'aime »

Excellent, content de savoir que cela a résolu votre problème Marcus. Je ferme ce sujet maintenant.

2 « J'aime »

Lorsque j’essaie de créer un nouveau canal (nommé « general », même chose pour le slug), l’erreur suivante s’affiche dans les logs (rien ne se passe côté frontend).

Aucun canal « Fermé » n’est affiché.

J’ai peut-être eu un canal general par le passé - et l’ai probablement supprimé (est-ce par défaut ?)

Impossible de reproduire avec un autre slug aléatoire (créer > supprimer > recréer fonctionne très bien).

Failed to handle exception in exception app middleware : ActiveRecord::RecordNotUnique : PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_chat_channels_on_slug"
DETAIL:  Key (slug)=(general) already exists.

J’ai déplacé votre publication ici pour que les rapports restent groupés. :+1:

La solution de contournement ci-dessus conviendrait-elle également dans votre cas ?

La solution de contournement dans le message initial, non, n’a pas fonctionné.

Ceci ne semble pas non plus avoir fonctionné pour moi.

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

La solution de contournement pour le problème des OPs se trouve dans ce message :

2 « J'aime »

J’ai essayé ceux-ci, c’est ce dont parlait mon bloc de code partagé.

Je n’ai pas réussi à exécuter ces commandes dans rails.

Peut-être que je fais quelque chose de mal ici ?

EDIT : pour être clair, la solution de contournement suggérée génère la même erreur lors de la recherche du canal

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

Bien, j’ai réussi à résoudre le problème (du moins, je le pense).

Pour moi, cela a été un peu compliqué de tout comprendre, alors je vais partager les étapes complètes.

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

Donc, dans votre console Rails, cela ressemblera à ceci :

[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) ✗

Je suis maintenant capable de créer un nouveau canal avec le slug souhaité.

Est-ce la bonne façon (ou une bonne façon) de faire ?

2 « J'aime »

La solution de contournement ci-dessus échoue en raison d’un espace de noms que nous avons introduit il y a quelques semaines. ChatChannel est maintenant Chat::Channel.

1 « J'aime »

Je m’attendais à quelque chose comme ça mais je n’ai pas pu le trouver. J’espère que mon changement de base de données est également une bonne solution de contournement ? Jusqu’à présent, aucun problème.

2 « J'aime »