سؤال

أنا أعمل على نظام التعامل مع عدد من سباق الشروط عند التقديم وظائف في عدد من العمال الآلات.

وسيكون العملاء الاستعلام نظام الوظائف مع status='0' (توضأ) ، ثم في ذرية طريقة تحديث 'أقدم صف مع status='1' (مؤمن) و استرداد معرف هذا الصف (تحديث وظيفة عامل المعلومات مثل الآلة التي تعمل على ذلك.... الخ).

القضية الرئيسية هنا هي أن هناك قد يكون أي عدد من العملاء تحديث في نفس الوقت.الحل هو قفل حوالي 20 الصفوف مع status='0', تحديث أقدم أحد والإفراج عن جميع الأقفال مرة أخرى بعد ذلك.لقد كنت أبحث في TransactionMiddleware ولكن أنا لا أرى كيف أن هذا من شأنه أن يمنع حالة من أقدم واحد يجري تحديثها من تحت لي بعد الاستعلام ذلك.

لقد بحثت في QuerySet.تحديث() الشيء و يبدو واعدا ، ولكن في حالة اثنين من العملاء الحصول على عقد من نفس السجل ، وحالة ببساطة تحديث سيكون لدينا اثنين من العمال يعملون في نفس الوظيفة..أنا حقا في حيرة هنا.

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

كود:النتيجة = وظيفة

class Result(models.Model):
"""
Result: completed- and pending runs

'ToDo': job hasn't been acquired by a client
'Locked': job has been acquired
'Paused'
"""
# relations
run = models.ForeignKey(Run)
input = models.ForeignKey(Input)

PROOF_CHOICES = (
    (1, 'Maybe'),
    (2, 'No'),
    (3, 'Yes'),
    (4, 'Killed'),
    (5, 'Error'),
    (6, 'NA'),
)
proof_status = models.IntegerField(
    choices=PROOF_CHOICES,
    default=6,
    editable=False)

STATUS_CHOICES = (
    (0, 'ToDo'),
    (1, 'Locked'),
    (2, 'Done'),
)
result_status = models.IntegerField(choices=STATUS_CHOICES, editable=False, default=0)

# != 'None' => status = 'Done'
proof_data = models.FileField(upload_to='results/',
    null=True, blank=True)
# part of the proof_data
stderr = models.TextField(editable=False,
    null=True, blank=True)

realtime = models.TimeField(editable=False,
    null=True, blank=True)
usertime = models.TimeField(editable=False,
    null=True, blank=True)
systemtime = models.TimeField(editable=False,
    null=True, blank=True)

# updated when client sets status to locked
start_time = models.DateTimeField(editable=False)

worker = models.ForeignKey('Worker', related_name='solved',
    null=True, blank=True)
هل كانت مفيدة؟

المحلول

لدمج #2705 في Django الخاص بك ، تحتاج إلى تنزيله أولاً:

cd <django-dir>
wget http://code.djangoproject.com/attachment/ticket/2705/for_update_11366_cdestigter.diff?format=raw

ثم ارجع SVN إلى إصدار Django الضروري:

svn update -r11366

ثم ضعه:

patch -p1 for_update_11366_cdestigter.diff

سوف يعلمك بالملفات التي تم تصحيحها بنجاح والتي لم تكن كذلك. في حالة النزاعات غير المحتملة ، يمكنك إصلاحها يدويًا النظر إليها يدويًا http://code.djangoproject.com/attachment/ticket/2705/for_update_11366_cdestigter.diff

لإلغاء الاطلاع على التصحيح ، فقط اكتب

svn revert --recursive . 

نصائح أخرى

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

from threading import Lock

workers_lock = Lock()

def get_work(request):
    workers_lock.acquire()
    try:
        # Imagine this method exists for brevity
        work_item = WorkItem.get_oldest()
        work_item.result_status = 1
        work_item.save()
    finally:
        workers_lock.release()

    return work_item

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

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

طريقة واحدة للحصول على حول تلك العودة الوظائف في مجموعات محددة للعملاء بحيث لا تحصل دائما على نفس القوائم.على سبيل المثال ، تقسمها حسب المنطقة الجغرافية أو حتى مجرد عشوائيا.على سبيل المثال, كل زبون يمكن أن يكون معرف من 0 إلى 9.تأخذ وزارة الدفاع من هوية الوظائف وإرسالها مرة أخرى تلك الوظائف مع نفس تنتهي أرقام إلى العميل.لا تقتصر على مجرد تلك الوظائف على الرغم من أنك لا تريد أن يكون هناك فرص العمل التي لا يمكنك الوصول إليها.هكذا على سبيل المثال إذا كان لديك عملاء من 1 و 2 و 3 و وظيفة 104 ثم لا أحد سوف تكون قادرة على الحصول عليه.لذا عندما لا يوجد ما يكفي من فرص العمل الصحيح تنتهي أرقام الوظائف ستبدأ العودة مع أرقام فقط لملء القائمة.قد تحتاج للعب حولها مع الدقيق خوارزمية هنا ، ولكن نأمل أن هذا يعطيك فكرة.

كيفية قفل الصفوف في قاعدة البيانات الخاصة بك من أجل تحديث و/أو إعادة إرسال الإخطارات سوف تعتمد إلى حد كبير على RDBMS.في MS SQL Server يمكنك لف كل ذلك العمل بشكل جيد في إجراء مخزن طالما تدخل المستخدم ليس بحاجة في وسطها.

آمل أن يساعد هذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top