/polls/voters.json يعيد مستخدمين مكررين عبر طلبات مرقمة صفحات

عند استدعاء نقطة النهاية /polls/voters.json، باستخدام التقسيم إلى صفحات، وجدنا أن الاستدعاء الأول يُرجع 25 مستخدمًا كما هو متوقع، ولكن الصفحة الثانية تُرجع 26 مستخدمًا، تم إرجاع أحدهم في الاستدعاء الأول. هذا ثابت كلما كان هناك أكثر من 25 مستخدمًا.

المشكلة هنا في إضافة الاستطلاع لـ discourse:
https://github.com/discourse/poll/blob/main/plugins/poll/lib/poll.rb#L223

يتم حساب الإزاحة بافتراض أن استعلامات PostgreSQL حصرية مع حد للصف باستخدام BETWEEN، عندما تكون شاملة.

الاستعلام الأول يُرجع بالفعل 25، لأن الصفوف المحسوبة تبدأ بالفعل من 1، وليس 0.

إصلاحي المقترح بسيط مثل:

   params = {
      offset: offset + 1,
      offset_plus_limit: offset + limit,
      option_digest: opts[:option_id].presence,
    }

أو، قد يكون الحل الأكثر أناقة هو استخدام LIMIT و OFFSET في PostgreSQL

    params = {
      limit: limit,
      offset: offset,
      option_digest: opts[:option_id].presence,
    }
          WHERE pv.poll_id IN (:poll_ids)
                /* where */
        ) v
        ORDER BY digest, CASE WHEN rank = 'Abstain' THEN 1 ELSE CAST(rank AS integer) END, username
        LIMIT :limit OFFSET :offset
      SQL
إعجابَين (2)

ملاحظة جيدة، سأضع علامة pr-welcome هنا في حال أراد أي شخص محاولة إصلاح هذا.

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

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

شكراً على الرد السريع!
سأحاول إعداد بيئة، لم أكن أرغب في تقديم طلب سحب (PR) دون اختبار. أي شخص يشعر بالحرية في أن يسبقني. أنا لست مطور روبي على الإطلاق. أنا أيضًا لا أعرف شيئًا عن تغيير المواصفات أو الاختبارات.

من المضحك أنه في واجهة المستخدم يوجد كود يقوم بتفريغ النتائج في مجموعة لتجاوز هذه المشكلة.

إعجابَين (2)

لكل من يشاهد، لقد قمنا بإصلاح واجهة مستخدم مماثل لبرنامج اليانصيب الخاص بنا هنا.

تحية طيبة لـ @lukecyca من VHS لتحديد منطقة المشكلة.

هناك أيضًا تقرير متعلق بتحميل المزيد من المصوتين في استطلاعات الرأي من يناير.

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

صيد رائع.

الأمر أكثر إضحاكًا من ذلك. لقد قدمت طلبين كبيرين جدًا لتحديث الواجهة الأمامية وإضافة التصويت الترتيبي.

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

أعترف بأنني اتبعت سابقة الواجهة الأمامية تلك التي تم وضعها في عام 2018 للتصويت الترتيبي دون التفكير حقًا في الأمر :sweat_smile:. (والتي اتبعتموها أيضًا، وإن كان عن علم :laughing:)

من المدهش كيف يمكن للحلول البديلة أن تستمر دون تحديد المشكلة الأساسية.

3 إعجابات

إذًا، فكرت في أن أجرب هذا الأمر كمساهمة أولى لي، ولكن يبدو أنه قد يكون أكثر تعقيدًا مما توقعت. :wink:

لدي مسودة طلب سحب (PR) مفتوحة: FIX: do not return duplicates from /polls/voters.json by clechasseur · Pull Request #1 · clechasseur/discourse · GitHub

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

حاولت أيضًا الحل الأكثر أناقة (الذي كنت سأفضله)، ولكن على الرغم من أنه يمنع الناخبين المكررين، إلا أنه يغير أيضًا الناخب الذي يتم إرجاعه في كل صفحة، بما في ذلك الصفحة الأولى، مما قد يعتبر تغييرًا جذريًا (اعتمادًا على كيفية تعامل الواجهة الأمامية معه - لم ألقِ نظرة بعد).

بالعودة إلى الوراء، أتساءل ما هو المعنى الحقيقي لمعامل limit عند استدعاء نقطة النهاية هذه - فهو لا يحد حقًا من عدد الناخبين الإجماليين الذين تم إرجاعهم، بل يحد فقط من عدد الناخبين الذين تم إرجاعهم لكل خيار من خيارات الاستطلاع. يمكنك رؤية هذا التأثير في الاختبار الذي أضفته للاستطلاع متعدد الخيارات هنا - الصفحة الأولى محدودة بالفعل بناخبين اثنين لكل خيار، ولكن في المجموع، يتم إرجاع ثلاثة ناخبين مختلفين (موزعين عبر الخيارات). التبديل إلى الحل الأنيق (أي استخدام LIMIT :limit OFFSET :offset) يؤدي إلى تطبيق limit على العدد الإجمالي للأصوات وليس الناخبين. لست متأكدًا بنسبة 100٪ ما إذا كان هذا أفضل أو أكثر بديهية.

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

على الهامش، أعتقد أن هناك خطأ آخر في هذا الجزء من الكود. الاستعلام لتحميل الناخبين مرتب حسب الهضم (digest) والرتبة (rank) واسم المستخدم - ولكن عند الترتيب حسب الرتبة، فإنه يستخدم هذا الشرط:

CASE WHEN rank = 'Abstain' THEN 1 ELSE CAST(rank AS integer) END

ومع ذلك، فإن ’Abstain’ يقابل فعليًا الرتبة 0، وليس 1 - يمكن أيضًا إرجاع الرتبة 1 كـ ’1’. هذا يجعل الترتيب غير حتمي عبر الاستعلامات، مما يعني أنه اعتمادًا على عدد الناخبين وقيمة limit المستخدمة، قد يكون من الممكن فعليًا تفويت الناخبين عند إجراء استعلامات مرقمة. في اختباراتي الجديدة، اضطررت إلى فرز الناخبين المرتجعين للتغلب على الطبيعة غير الحتمية. (نظرًا لأنها غير حتمية، أفترض أنه ليس من السهل إعادة إنتاجها في اختبار، ولكن يمكنني محاولة ذلك…)

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

لقد اتبعت الرابط أعلاه لتقرير سابق، والذي يتضمن رابطًا إلى تقرير سابق سابق والذي يتضمن شيئًا يبدو أنه يشير إلى هذا الاحتمال أيضًا:

ومع ذلك، فقد مر وقت طويل جدًا، لذا قد يكون الكود مختلفًا تمامًا في ذلك الوقت. (حاولت العودة بالزمن باستخدام Git ولكن التاريخ توقف في عام 2021، لذا أفترض أن الكود قد انتقل في مرحلة ما.)

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

لقد أنشأت طلب سحب (PR) مع اختباري والإصلاحات التي أقترحها: إصلاح: تجنب إرجاع ناخبين مكررين من نقطة النهاية /polls/voters.json بواسطة clechasseur · طلب سحب #34433 · discourse/discourse

3 إعجابات

شكراً جزيلاً على الإصلاح وصبرك لمراجعتنا.
لقد وافقت ودمجته. :partying_face:

3 إعجابات

تم إغلاق هذا الموضوع تلقائيًا بعد 3 أيام. لم يعد يُسمح بالردود الجديدة.