محاولة إعادة إنشاء قناة دردشة محذوفة بنفس الاسم (لا تزال) تفشل

متابعةً للنقاش من محاولة إعادة إنشاء قناة دردشة محذوفة بنفس الاسم تفشل:

يبدو أن هذه المشكلة التي تم الإبلاغ عنها في الموضوع المرتبط لا تزال قائمة بالنسبة لي. أنا على أحدث إصدار وقمت بسحب التغييرات وإعادة بناء المشغل بالأمس.

عند محاولة تسمية قناة دردشة جديدة بنفس اسم أي قناة دردشة مستخدمة سابقًا، يحدث خطأ 500 في وحدة تحكم JavaScript.

في سجلات أخطاء Discourse، أحصل على:

فشل في معالجة الاستثناء في تطبيق معالجة الاستثناءات : ActiveRecord::RecordNotUnique : PG::UniqueViolation: خطأ: قيمة المفتاح المكررة تنتهك القيد الفريد "index_chat_channels_on_slug"
التفاصيل: المفتاح (slug)=(sec-fhir) موجود بالفعل.

في وحدة تحكم Rails، يمكنني رؤية أن ChatChannels المحذوفة قد اختفت، لكنني أشك في أن الاسم المستعار (slug) المحذوف لا يزال موجودًا في فهرس أو في تبعية أخرى لقاعدة البيانات ولم يتم حذفه.

هذا الحل البديل لا يعمل بالنسبة لي، عند محاولة إعادة تسمية “foo2” إلى “foo” أحصل على نفس خطأ 500، بسبب فشل قيد التفرد على الاسم المستعار.

لست متأكدًا من كيفية حذف الأسماء المستعارة (المفهرسة؟) لقنوات الدردشة المحذوفة بأمان، لكنني على استعداد للمحاولة.


من المحتمل أن يكون هذا مرتبطًا بهذه المشكلة التي تؤثر أيضًا على الأسماء المستعارة، ولكنها لا تبدو نفس المشكلة: Attempt to recreate deleted chat channel with same name fails

إعجابَين (2)

لقد اختبرت ما يلي الآن ولم أواجه أي مشكلة:

  1. إنشاء قناة بالاسم “whiskers” والاسم المختصر “whiskers”
  2. حذف القناة
  3. إنشاء قناة بالاسم “whiskers” والاسم المختصر “whiskers”

لقد نجح ذلك.

عند حذف القناة (الخطوة 2)، يتغير الاسم المختصر تلقائيًا إلى شيء فريد. ولكن نظرًا لأنك حذفت قناتك قبل تقديم هذا التغيير، فقد لا يزال الاسم المختصر القديم موجودًا.

من المحتمل أن تتمكن من تحديث الاسم المختصر يدويًا للقناة المحذوفة عبر وحدة تحكم rails، لكنني لست متأكدًا من الصيغة الصحيحة. سأسأل.

لاحظ أيضًا أنه يمكن الآن تعديل الأسماء المختصرة للقنوات بشكل مستقل عن اسم القناة، لذلك كحل بديل، يمكنك أيضًا إنشاء قناة بالاسم المطلوب اليوم واختيار اسم مختصر مختلف لا يتعارض.

إعجابَين (2)

هذا غير متوقع على الإطلاق.

نحن لا نحذف القنوات، بل نحذفها بشكل ناعم فقط. لذلك يجب أن تظل هنا مع ملء العمود deleted_at.

إذا قمت بتشغيل هذا في وحدة التحكم الخاصة بك، فهل تحصل على أي نتائج؟

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

أؤكد أن هذا الاختبار يعمل أيضًا بالنسبة لي على نسختي، وهي محدثة بالكامل.

أعتقد أن المشكلة هي أن هناك اسمًا مستعارًا عالقًا في مكان ما في قاعدة البيانات كان يجب حذفه، ولكنه لم يُحذف، ربما كان هناك خطأ في إصدار سابق تم إصلاحه الآن. تم تمكين الدردشة على هذه النسخة لمدة 17 يومًا فقط، لذا فإن أي خطأ يجب أن يكون نشطًا في هذا الإطار الزمني.

إعجاب واحد (1)

لا يمكنني تكرار هذا بأي شكل من الأشكال. بعد إجراء نسخة احتياطية لقاعدة البيانات، ربما يمكنك تجربة هذه الأوامر في وحدة تحكم 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);")

لقد تحققت وهذا متوقع بالفعل، حيث نستبعد السجلات التي تحتوي على deleted_at مملوءة حتى مع 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

ستحتاج إلى القيام بذلك بدلاً من ذلك (بإضافة 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”، ونفس الاسم للـ slug) يظهر الخطأ التالي في السجلات (لا يحدث شيء في الواجهة الأمامية).

لا تظهر أي قنوات “مغلقة”.

ربما كانت لدي قناة عامة في الماضي - وربما حذفتها (هل هي افتراضية؟)

لا يمكنني إعادة إنتاج المشكلة باستخدام slug عشوائي آخر (إنشاء > حذف > إنشاء يعمل بشكل جيد).

فشل في معالجة الاستثناء في تطبيق الوسيط الاستثنائي : ActiveRecord::RecordNotUnique : PG::UniqueViolation: خطأ: مفتاح مكرر ينتهك قيد المفتاح الفريد "index_chat_channels_on_slug"
التفاصيل: المفتاح (slug)=(general) موجود بالفعل.

لقد قمت بنقل منشورك إلى هنا للحفاظ على تجميع التقارير معًا. :+1:

هل سيكون الحل البديل أعلاه مناسبًا في حالتك أيضًا؟

الحل البديل في OP، لا، لم ينجح.

لم يبدو أن هذا يعمل بالنسبة لي أيضًا.

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

الحل البديل لمشكلة المنشور الأصلي موجود في هذا المنشور:

إعجابَين (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) ✗

أنا الآن قادر على إنشاء قناة جديدة بالـ slug المطلوب.

هل هذه هي الطريقة الصحيحة (أو إحدى الطرق الصحيحة)؟

إعجابَين (2)

الحل البديل الذي فشل أعلاه يرجع إلى بعض تعريفات النطاقات التي قدمناها قبل أسابيع. ChatChannel هو الآن Chat::Channel

إعجاب واحد (1)

كنت أتوقع شيئًا كهذا ولكني لم أتمكن من العثور عليه. هل آمل أن يكون تغيير قاعدة البيانات الخاص بي حلاً بديلاً جيدًا أيضًا؟ حتى الآن لا توجد مشاكل.

إعجابَين (2)