同じ名前で削除されたチャットチャンネルを再作成しようとすると(まだ)失敗します

Attempt to recreate deleted chat channel with same name fails の議論を続けます。

リンク先のスレッドで報告されたこのバグは、私の場合、まだ残っているようです。最新版を使用しており、昨日 git pull とランチャーの再構築を行いました。

以前使用したチャットチャンネル名と同じ名前で新しいチャットチャンネルを作成しようとすると、JSコンソールに500エラーが表示されます。

Discourseのエラーログには次のように表示されます。

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.

Railsコンソールでは、削除されたChatChannelsは消えていることがわかりますが、削除されたスラッグがインデックスまたは他のDB依存関係のどこかに残っており、削除されていないのではないかと疑っています。

この回避策は私には機能しません。「foo2」を「foo」にリネームしようとすると、スラッグの一意性制約の失敗により、同じ500エラーが発生します。

削除されたChatChannelsの(インデックス化された?)スラッグを安全に削除する方法はわかりませんが、試してみたいと思います。


おそらく関連:スラッグにも影響するこの問題ですが、同じ問題ではないようです:Attempt to recreate deleted chat channel with same name fails

「いいね!」 2

以下をテストしたところ、問題ありませんでした。

  1. 「whiskers」という名前と「whiskers」というスラッグでチャンネルを作成します。
  2. チャンネルを削除します。
  3. 「whiskers」という名前と「whiskers」というスラッグでチャンネルを作成します。

これはうまくいきました。

チャンネルが削除されると(ステップ2)、スラッグは自動的に一意なものに変更されます。しかし、その変更が導入される前にチャンネルを削除したため、古いスラッグがまだ残っている可能性があります。

おそらく、レールコンソール経由で削除されたチャンネルのスラッグを手動で更新できると思いますが、正しい呪文が何であるかはわかりません。誰かに聞いてみます。

また、チャンネルのスラッグは、チャンネル名とは別に編集できるようになりました。回避策として、今日、希望の名前のチャンネルを作成し、競合しない別のスラッグを選択することもできます。

「いいね!」 2

これは全く予期していませんでした。

チャンネルは削除せず、ソフトデリートのみを行っています。そのため、deleted_atカラムが埋められた状態で、まだここにあるはずです。

コンソールでこれを実行しても結果は得られませんか?

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

私も、完全に最新の状態に更新されている私のインスタンスで、このテストが機能することを確認できます。

問題は、DBのどこかに削除されるべきスラッグが残っていて、削除されなかったことだと思います。おそらく、以前のバージョンにバグがあり、それが修正されたのでしょう。このインスタンスでチャットが有効になったのは17日前なので、バグがあったとしてもその期間に有効だったはずです。

「いいね!」 1

どうしても再現できません。DBのバックアップ後、Railsコンソールで以下を試してみてください。驚くべきことです。

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

確認したところ、これは実際には想定通りの動作です。find_by を使用しても deleted_at が設定されているレコードは除外されるためです。

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

代わりに、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>

したがって、古い削除されたチャンネルのスラッグをクリアするには、次のようなことを行う必要があります。

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

これらの修正のためにマイグレーションが必要でしょうか? @mcwumbly@j.jaffeux

「いいね!」 2

はい、このケースでは with_deleted を忘れていました :+1:

ここでは、この回答をそのままにしておくことをお勧めします。まれなケースでしょうが、修正前に削除され、同じ名前で再作成したい場合です。

「いいね!」 4

上記、ありがとうございます。with_deleted については知りませんでしたが、これにより削除されたインスタンスを確認し、スニペットに従ってスラッグの名前を変更することができました。

これが修正されたことを確認できます。@j.jaffeux と同様に、これは多くのユーザーに影響する可能性は低いと思いますので、スレッドに Rails コンソールでの修正があれば十分だと思います。

「いいね!」 3

解決してよかったです。これでこのトピックを終了します。

「いいね!」 2

新しいチャンネル(名前とスラッグを「general」に設定)を作成しようとすると、ログに以下のエラーが表示されます(フロントエンドでは何も起こりません)。

「Closed」チャンネルは表示されていません。

過去に general チャンネルがあり、おそらく削除した可能性があります(デフォルトですか?)。

別のランダムなスラッグでは再現できません(作成 > 削除 > 再作成は問題なく動作します)。

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.

投稿をこちらに移動しました。レポートをまとめておくためです。:+1:

上記回避策は、お客様の場合にも適していますでしょうか?

OP の回避策は機能しませんでした。

これも私には機能しないようです。

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

OPの問題に対する回避策は、こちらの投稿にあります。

「いいね!」 2

これらを試しましたが、共有したコードブロックはそれについてのものです。

これらのコマンドをrailsで実行できませんでした。

もしかしたら、ここで何か間違っているのかもしれませんか?

編集:明確にするために、提案された回避策は、チャンネルを検索するときに同じエラーを返します。

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

問題は解決しました(少なくとも、そう思っています)。

私にとっては、これをすべて理解するのが大変だったので、完全な手順を共有します。

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

だから、あなたのRailsコンソールでは、これは次のようになります。

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

これで、目的のスラッグを持つ新しいチャネルを作成できるようになりました。

これは正しい方法(またはその一つ)でしょうか?

「いいね!」 2

上記で失敗している回避策は、数週間前に導入した名前空間が原因です。ChatChannel は Chat::Channel になりました。

「いいね!」 1

そのようなものを期待していましたが、見つけることができませんでした。私のDB変更も良い回避策であることを願っていますか?今のところ問題はありません。

「いいね!」 2