أريد أن أخبرك كيف قمنا بتنظيم تحديث بيانات الخلفية أثناء طلب خدمة REST.
المهمة كالتالي: يخزن النظام بيانات المستخدم. تعمل الخدمة بمعزل وليس لديها وصول مباشر إلى قواعد البيانات مع هذه البيانات. لكي تعمل الخدمة ، من الضروري أن يكون لديك أسماء المستخدمين الأول والأخير في قاعدة بياناتها الداخلية. يمكن الحصول عليها من هوية المستخدم الحالي في وقت الطلب. مطلوب لإضافة أو تحديث الأسماء أثناء كل طلب. ينصح بتنفيذ هذا في مؤشر ترابط منفصل حتى لا يؤثر هذا العمل على وقت تنفيذ الطلب الرئيسي.
تحسين المهمة
في قاعدة بيانات الخدمة ، نقوم بتخزين أسماء وألقاب المستخدمين. يحتاج العملاء إليهم للحصول على معلومات حول من قام بإنشاء أو تعديل المورد.
هذه البيانات ليست مهمة من الناحية النظامية: إذا لم تكن هناك سجلات ضرورية في قاعدة البيانات ، فلن يحدث شيء سيء. لذلك ، لا نريد تسجيل أعمالنا الخلفية في ASP باستخدام QueueBackgroundWorkItem ، من أجل تعقيد التحميل الزائد لمجال التطبيق.
من المستحسن حل المشكلة بالبساطة الممكنة.
بالنسبة لأولئك الذين يرغبون في معرفة المزيد حول مهام الخلفية في ASP.NET ، أنصحك بقراءة
مقال جيد حول هذا الموضوع.
الحل
لدينا فئة DbRefresher التي تضيف أو تغير بيانات المستخدم في طريقة RefreshAsync.
تستخدم وحدات التحكم الخاصة بنا سمة التفويض. أضف سليلنا إلى هذه الفئة وتجاوز طريقة OnAuthorization:
public override void OnAuthorization(HttpActionContext actionContext) { base.OnAuthorization(actionContext); if (IsAuthorized(actionContext)) DbRefresher.RefreshAsync(actionContext.RequestContext.Principal) .ContinueWith(t => { LogFactory.For<AuthorizeAndRefreshUserAttribute>() .ErrorException("Error occured", t.Exception); }, TaskContinuationOptions.OnlyOnFaulted); }
DbRefresher.RefreshAsync هي طريقة غير متزامنة تقوم بإرجاع كائن مهمة يستمر في التنفيذ في مؤشر ترابط آخر. يتم إنهاء أسلوب OnAuthorize على الفور دون انتظار إكمال المهمة. في حالة حدوث عطل ، ستتم إضافة رسالة خطأ إلى السجل.
هذا كل شيء: كل ما تبقى هو استبدال السمة Authorise في وحدات التحكم باسم السمة الجديدة. تقوم السمة الجديدة بإرجاع التحكم فور التحقق من حقوق المستخدم الحالي ، وبعد ذلك تبدأ وحدة التحكم في عملها. سيتم تحديث قاعدة البيانات بالتوازي مع إعداد استجابة وحدة التحكم.
اختبار
يساعد الاختبار الذي يقوم بتشغيل عدة طلبات خدمة متزامنة في تحديد المشكلات المحتملة:
[TestMethod] public void ConcurrentTest() { const int threadCount = 10; var tasks = new Task[threadCount]; for (int i = 0; i < threadCount; i++) {
المشاكل
إذا كان مطلوبًا لتشغيل بعض أساليب عمل وحدة التحكم أن تحتوي قاعدة البيانات بوضوح على بيانات المستخدم الحالي ، فإن هذا النهج غير مناسب. يجب عليك استخدام مكالمة صريحة إلى DbRefresher.RefreshAsync في نص الأسلوب.
قد تكون هناك مشاكل عند إضافة مستخدم جديد إلى قاعدة البيانات مع العديد من الطلبات المتزامنة. إذا تم إجراء محاولة لإضافة مستخدم إلى جدول به مفتاح موجود ، فيجب عليك الاستثناء من انتهاك انتهاك المفتاح الأساسي والتوقف عن العمل. ثم سيتم تنفيذ كل العمل على تحديث بيانات المستخدم بواسطة مؤشر ترابط واحد فقط.
الخاتمة
يعمل هذا النهج بنجاح في إحدى خدماتنا في Konfermit منذ أكثر من عام.
يبدو لي بسيط وأنيق. سيكون من المثير للاهتمام معرفة رأي المجتمع.