الوصول إلى حالة "المستخدم الموثوق به" وحفظها وإزالتها
المستخدمين الموثوقين عبارة عن عناصر ذات مؤشر ترابط واحد يمكنها تغليف كل من المنطق والحالة والحفاظ على موثوقية الحالة. كل مثيل مستخدم له مدير حالة خاص به: بنية بيانات تشبه القاموس تخزن بشكل موثوق أزواج المفاتيح/ القيمة. مدير الحالة هو برنامج تضمين حول موفر الحالة. يمكنك استخدامه لتخزين البيانات بغض النظر عن إعداد الاستمرارية المستخدم.
يجب أن تكون مفاتيح مدير الحالة عبارة عن سلاسل. عادة تكون القيم عامة ومن أي نوع، بما في ذلك الأنواع المخصصة. يجب أن تكون القيم المخزنة في مدير الحالة قابلة للتسلسل لعقد البيانات لأنه قد يتم نقلها عبر الشبكة إلى العقد الأخرى أثناء النسخ المتماثل وقد تتم كتابتها على القرص، اعتمادًا على إعداد استمرار حالة المستخدم.
يكشف مدير الحالة عن طرق القاموس الشائعة لإدارة الحالة، على غرار تلك الموجودة في Reliable Dictionary.
لمزيد من المعلومات، راجع أفضل الممارسات في إدارة حالة الجهة المستخدم.
حالة الوصول
يستطيع مدير الحالة الوصول إلى الحالة عن طريق المفتاح. جميع أساليب مدير الحالة غير متزامنة لأنها قد تتطلب إدخال/إخراج القرص عند استمرار حالة المستخدمين. عند الوصول للمرة الأولى، يتم تخزين عناصر الحالة مؤقتا في الذاكرة. تكرار عمليات الوصول و عناصر الوصول مباشرة من الذاكرة والعودة بشكل متزامن دون تكبد إدخال/إخراج القرص أو النفقات العامة لتبديل السياق بشكل غير متزامن. تتم إزالة عنصر حالة من ذاكرة التخزين المؤقت في الحالات التالية:
- يطرح أسلوب المستخدم استثناء غير معالج بعد استرداد عنصر من مدير الحالة.
- يحدث إعادة تنشيط للمستخدم، إما بعد إلغاء تنشيطه أو بعد الفشل.
- حالة صفحات موفر الحالة على القرص. يعتمد هذا السلوك على تنفيذ موفر الحالة. موفر الحالة الافتراضي للإعداد
Persisted
لديه هذا السلوك.
يمكنك استرداد الحالة باستخدام عملية Get قياسية تقوم بطرح KeyNotFoundException
(C #) أو NoSuchElementException
(Java) في حالة عدم وجود إدخال للمفتاح:
[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
public MyActor(ActorService actorService, ActorId actorId)
: base(actorService, actorId)
{
}
public Task<int> GetCountAsync()
{
return this.StateManager.GetStateAsync<int>("MyState");
}
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements MyActor
{
public MyActorImpl(ActorService actorService, ActorId actorId)
{
super(actorService, actorId);
}
public CompletableFuture<Integer> getCountAsync()
{
return this.stateManager().getStateAsync("MyState");
}
}
يمكنك أيضا استرداد الحالة باستخدام أسلوب TryGet الذي لا يطرح إن لم يكن هناك إدخال لمفتاح:
class MyActor : Actor, IMyActor
{
public MyActor(ActorService actorService, ActorId actorId)
: base(actorService, actorId)
{
}
public async Task<int> GetCountAsync()
{
ConditionalValue<int> result = await this.StateManager.TryGetStateAsync<int>("MyState");
if (result.HasValue)
{
return result.Value;
}
return 0;
}
}
class MyActorImpl extends FabricActor implements MyActor
{
public MyActorImpl(ActorService actorService, ActorId actorId)
{
super(actorService, actorId);
}
public CompletableFuture<Integer> getCountAsync()
{
return this.stateManager().<Integer>tryGetStateAsync("MyState").thenApply(result -> {
if (result.hasValue()) {
return result.getValue();
} else {
return 0;
});
}
}
حفظ الحالة
تقوم أساليب استرجاع مدير الحالة بإرجاع مرجع إلى عنصر في الذاكرة المحلية. تعديل هذا العنصر في الذاكرة المحلية وحدها لا يؤدي إلى حفظه بشكل دائم. عندما يتم استرداد عنصر من مدير الحالة وتعديله، يجب إعادة إدخاله في مدير الحالة ليتم حفظه بشكل دائم.
يمكنك إدراج حالة باستخدام مجموعة غير مشروطة، مشابهة لسطر dictionary["key"] = value
:
[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
public MyActor(ActorService actorService, ActorId actorId)
: base(actorService, actorId)
{
}
public Task SetCountAsync(int value)
{
return this.StateManager.SetStateAsync<int>("MyState", value);
}
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements MyActor
{
public MyActorImpl(ActorService actorService, ActorId actorId)
{
super(actorService, actorId);
}
public CompletableFuture setCountAsync(int value)
{
return this.stateManager().setStateAsync("MyState", value);
}
}
يمكنك إضافة حالة باستخدام أسلوب إضافة. تقوم هذه الطريقة بطرح InvalidOperationException
(C #) أو IllegalStateException
(Java) عند محاولة إضافة مفتاح موجود بالفعل.
[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
public MyActor(ActorService actorService, ActorId actorId)
: base(actorService, actorId)
{
}
public Task AddCountAsync(int value)
{
return this.StateManager.AddStateAsync<int>("MyState", value);
}
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements MyActor
{
public MyActorImpl(ActorService actorService, ActorId actorId)
{
super(actorService, actorId);
}
public CompletableFuture addCountAsync(int value)
{
return this.stateManager().addOrUpdateStateAsync("MyState", value, (key, old_value) -> old_value + value);
}
}
يمكنك أيضا إضافة حالة باستخدام طريقة TryAdd. لا تقوم هذه الطريقة بأي طرح عند محاولة إضافة مفتاح موجود بالفعل.
[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
public MyActor(ActorService actorService, ActorId actorId)
: base(actorService, actorId)
{
}
public async Task AddCountAsync(int value)
{
bool result = await this.StateManager.TryAddStateAsync<int>("MyState", value);
if (result)
{
// Added successfully!
}
}
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements MyActor
{
public MyActorImpl(ActorService actorService, ActorId actorId)
{
super(actorService, actorId);
}
public CompletableFuture addCountAsync(int value)
{
return this.stateManager().tryAddStateAsync("MyState", value).thenApply((result)->{
if(result)
{
// Added successfully!
}
});
}
}
في نهاية أسلوب المستخدم، يقوم مدير الحالة تلقائيا بحفظ أي قيم تمت إضافتها أو تعديلها بواسطة عملية إدراج أو تحديث. يمكن أن يتضمن "الحفظ" الاستمرار على القرص والنسخ المتماثل، حسب الإعدادات المستخدمة. القيم التي لا يجرى لها تعديل، لا تستمر ولا تنسخ. في حالة عدم تعديل أي قيم، فإن عملية الحفظ لا تغير شيئ. في حالة فشل الحفظ، يتم تجاهل الحالة المعدلة وإعادة تحميل الحالة الأصلية.
يمكنك أيضا حفظ الحالة يدويا عن طريق استدعاء الأسلوب SaveStateAsync
على قاعدة المستخدم:
async Task IMyActor.SetCountAsync(int count)
{
await this.StateManager.AddOrUpdateStateAsync("count", count, (key, value) => count > value ? count : value);
await this.SaveStateAsync();
}
interface MyActor {
CompletableFuture setCountAsync(int count)
{
this.stateManager().addOrUpdateStateAsync("count", count, (key, value) -> count > value ? count : value).thenApply();
this.stateManager().saveStateAsync().thenApply();
}
}
عملية إزالة الحالة
يمكنك إزالة الحالة نهائيا من مدير حالة المستخدم عن طريق استدعاء أسلوب الإزالة. تقوم هذه الطريقة بطرح KeyNotFoundException
(C#) أو NoSuchElementException
(Java) عند محاولة إزالة مفتاح غير موجود.
[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
public MyActor(ActorService actorService, ActorId actorId)
: base(actorService, actorId)
{
}
public Task RemoveCountAsync()
{
return this.StateManager.RemoveStateAsync("MyState");
}
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements MyActor
{
public MyActorImpl(ActorService actorService, ActorId actorId)
{
super(actorService, actorId);
}
public CompletableFuture removeCountAsync()
{
return this.stateManager().removeStateAsync("MyState");
}
}
يمكنك أيضا إزالة الحالة نهائيا باستخدام طريقة TryRemove. لا يطرح هذا الأسلوب عند محاولة إزالة مفتاح غير موجود.
[StatePersistence(StatePersistence.Persisted)]
class MyActor : Actor, IMyActor
{
public MyActor(ActorService actorService, ActorId actorId)
: base(actorService, actorId)
{
}
public async Task RemoveCountAsync()
{
bool result = await this.StateManager.TryRemoveStateAsync("MyState");
if (result)
{
// State removed!
}
}
}
@StatePersistenceAttribute(statePersistence = StatePersistence.Persisted)
class MyActorImpl extends FabricActor implements MyActor
{
public MyActorImpl(ActorService actorService, ActorId actorId)
{
super(actorService, actorId);
}
public CompletableFuture removeCountAsync()
{
return this.stateManager().tryRemoveStateAsync("MyState").thenApply((result)->{
if(result)
{
// State removed!
}
});
}
}
الخطوات التالية
يجب إجراء تسلسل للحالة المخزنة في الفاعلين الموثوق بهم قبل كتابتها على القرص وتكرارها لتوفير إمكانية عالية. تعرف على المزيد حول إنشاء تسلسل نوع المستخدم.
بعدها، تعرف على المزيد حول تشخيصات المستخدمين ومراقبة الأداء.