مؤقتات وتذكيرات المستخدم

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

مؤقتات المستخدم

توفر مؤقتات المستخدمين غلافا بسيطا حول مؤقت .NET أو Java للتأكد من أن أساليب رد الاتصال تحترم التزامن القائم على الأدوار التي يوفرها وقت تشغيل المستخدمين.

يمكن للجهات المستخدم استخدام طرق RegisterTimer(C#) أو registerTimer (Java) و UnregisterTimer(C#) أو unregisterTimer(Java) في فئتها الأساسية لتسجيل المؤقتات الخاصة بها وإلغاء تسجيلها. يوضح المثال أدناه استخدام واجهات برمجة تطبيقات المؤقت. واجهات برمجة التطبيقات تشبه إلى حد كبير مؤقت .NET أو مؤقت Java. في هذا المثال، عند استحقاق المؤقت، سيقوم وقت تشغيل المستخدمين باستدعاء الأسلوب MoveObject(C#) أو moveObject(Java). الطريقة مضمونة لاحترام التزامن القائم على الأدوار. وهذا يعني أنه لن تكون هناك طرق أخرى للمستخدمين أو عمليات رد الاتصال بالمؤقت / التذكير قيد التقدم حتى يكتمل تنفيذ رد الاتصال هذا.

class VisualObjectActor : Actor, IVisualObject
{
    private IActorTimer _updateTimer;

    public VisualObjectActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    protected override Task OnActivateAsync()
    {
        ...

        _updateTimer = RegisterTimer(
            MoveObject,                     // Callback method
            null,                           // Parameter to pass to the callback method
            TimeSpan.FromMilliseconds(15),  // Amount of time to delay before the callback is invoked
            TimeSpan.FromMilliseconds(15)); // Time interval between invocations of the callback method

        return base.OnActivateAsync();
    }

    protected override Task OnDeactivateAsync()
    {
        if (_updateTimer != null)
        {
            UnregisterTimer(_updateTimer);
        }

        return base.OnDeactivateAsync();
    }

    private Task MoveObject(object state)
    {
        ...
        return Task.FromResult(true);
    }
}
public class VisualObjectActorImpl extends FabricActor implements VisualObjectActor
{
    private ActorTimer updateTimer;

    public VisualObjectActorImpl(FabricActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    @Override
    protected CompletableFuture onActivateAsync()
    {
        ...

        return this.stateManager()
                .getOrAddStateAsync(
                        stateName,
                        VisualObject.createRandom(
                                this.getId().toString(),
                                new Random(this.getId().toString().hashCode())))
                .thenApply((r) -> {
                    this.registerTimer(
                            (o) -> this.moveObject(o),                        // Callback method
                            "moveObject",
                            null,                                             // Parameter to pass to the callback method
                            Duration.ofMillis(10),                            // Amount of time to delay before the callback is invoked
                            Duration.ofMillis(timerIntervalInMilliSeconds));  // Time interval between invocations of the callback method
                    return null;
                });
    }

    @Override
    protected CompletableFuture onDeactivateAsync()
    {
        if (updateTimer != null)
        {
            unregisterTimer(updateTimer);
        }

        return super.onDeactivateAsync();
    }

    private CompletableFuture moveObject(Object state)
    {
        ...
        return this.stateManager().getStateAsync(this.stateName).thenCompose(v -> {
            VisualObject v1 = (VisualObject)v;
            v1.move();
            return (CompletableFuture<?>)this.stateManager().setStateAsync(stateName, v1).
                    thenApply(r -> {
                      ...
                      return null;});
        });
    }
}

تبدأ الفترة التالية من المؤقت بعد اكتمال عملية معاودة الاتصال للتنفيذ. هذا يعني أنه يتم إيقاف المؤقت أثناء تنفيذ معاودة الاتصال ويتم تشغيله عند انتهاء رد الاتصال.

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

على عكس التذكيرات، لا يمكن تحديث المؤقتات. إذا تم استدعاء RegisterTimer مرة أخرى، سيتم تسجيل مؤقت جديد.

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

تذكير المستخدم

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

ملاحظة

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

لتسجيل تذكير، يقوم أحد المستخدمين باستدعاء RegisterReminderAsync الطريقة المتوفرة في الفئة الأساسية، كما هو موضح في المثال التالي:

protected override async Task OnActivateAsync()
{
    string reminderName = "Pay cell phone bill";
    int amountInDollars = 100;

    IActorReminder reminderRegistration = await this.RegisterReminderAsync(
        reminderName,
        BitConverter.GetBytes(amountInDollars),
        TimeSpan.FromDays(3),    //The amount of time to delay before firing the reminder
        TimeSpan.FromDays(1));    //The time interval between firing of reminders
}
@Override
protected CompletableFuture onActivateAsync()
{
    String reminderName = "Pay cell phone bill";
    int amountInDollars = 100;

    ActorReminder reminderRegistration = this.registerReminderAsync(
            reminderName,
            state,
            dueTime,    //The amount of time to delay before firing the reminder
            period);    //The time interval between firing of reminders
}

في هذا المثال، "Pay cell phone bill" هو اسم التذكير. هذه سلسلة يستخدمها المستخدم لتحديد تذكير بشكل فريد. BitConverter.GetBytes(amountInDollars)(C#) هو السياق المرتبط بالتذكير. سيتم تمريرها مرة أخرى إلى المستخدم كحجة لمعاودة الاتصال بالتذكير، أي IRemindable.ReceiveReminderAsync(C#) أو Remindable.receiveReminderAsync(Java).

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

public class ToDoListActor : Actor, IToDoListActor, IRemindable
{
    public ToDoListActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task ReceiveReminderAsync(string reminderName, byte[] context, TimeSpan dueTime, TimeSpan period)
    {
        if (reminderName.Equals("Pay cell phone bill"))
        {
            int amountToPay = BitConverter.ToInt32(context, 0);
            System.Console.WriteLine("Please pay your cell phone bill of ${0}!", amountToPay);
        }
        return Task.FromResult(true);
    }
}
public class ToDoListActorImpl extends FabricActor implements ToDoListActor, Remindable
{
    public ToDoListActor(FabricActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture receiveReminderAsync(String reminderName, byte[] context, Duration dueTime, Duration period)
    {
        if (reminderName.equals("Pay cell phone bill"))
        {
            int amountToPay = ByteBuffer.wrap(context).getInt();
            System.out.println("Please pay your cell phone bill of " + amountToPay);
        }
        return CompletableFuture.completedFuture(true);
    }

عند تشغيل تذكير، سيستدعي ReceiveReminderAsyncوقت التشغيل الموثوق للمستخدمين طريقة (C#) أو receiveReminderAsync(Java) على المستخدم. يمكن للمستخدم ReceiveReminderAsyncتسجيل تذكيرات متعددة، ويتم استدعاء طريقة (C#) أو receiveReminderAsync(Java) عند تشغيل أي من هذه التذكيرات. يمكن للمستخدم استخدام اسم التذكير الذي تم تمريره إلى ReceiveReminderAsyncطريقة (C#) أو receiveReminderAsync(Java) لمعرفة التذكير الذي تم تشغيله.

يوفر وقت تشغيل المستخدمين حالة المستخدم عند ReceiveReminderAsyncانتهاء مكالمة (C#) أو receiveReminderAsync(Java). في حالة حدوث خطأ في حفظ الحالة، سيتم إلغاء تنشيط كائن المستخدم هذا وسيتم تنشيط مثيل جديد.

لإلغاء تسجيل تذكير، يستدعي UnregisterReminderAsyncأحد المستخدمين طريقة (C#) أو unregisterReminderAsync(Java)، كما هو موضح في الأمثلة أدناه.

IActorReminder reminder = GetReminder("Pay cell phone bill");
Task reminderUnregistration = await UnregisterReminderAsync(reminder);
ActorReminder reminder = getReminder("Pay cell phone bill");
CompletableFuture reminderUnregistration = unregisterReminderAsync(reminder);

كما هو موضح أعلاه، UnregisterReminderAsyncتقبل unregisterReminderAsyncطريقة (C#) أو (Java) واجهة (C#) أو IActorReminderActorReminder(Java). تدعم الفئة الأساسية للمستخدم طريقة GetReminder(C#) أو (Java) التي يمكن استخدامها لاسترداد getReminderواجهة (C#) أو IActorReminderActorReminder(Java) عن طريق المرور باسم التذكير. هذا مناسب لأن المستخدم لا يحتاج إلى الاستمرار في IActorReminderواجهة (C#) أو (Java) التي تم إرجاعها من استدعاء طريقة ActorReminder(C#) أو RegisterReminderregisterReminder(Java).

الخطوات التالية

تعرف على أحداث المستخدم الموثوق به وإعادة القبول: