Časovače a připomenutí objektu Actor
Aktéři si můžou naplánovat pravidelnou práci tím, že si zaregistrují časovače nebo připomenutí. Tento článek ukazuje, jak používat časovače a připomenutí a vysvětluje rozdíly mezi nimi.
Časovače objektu actor
Časovače objektu actor poskytují jednoduchou obálku kolem časovače .NET nebo Java, aby metody zpětného volání respektovaly záruky souběžnosti založené na turnu, které poskytuje modul runtime Actors.
Aktéři můžou použít RegisterTimer
metody (C#) nebo registerTimer
(Java) a UnregisterTimer
(C#) nebo unregisterTimer
(Java) v základní třídě k registraci a zrušení registrace časovačů. Následující příklad ukazuje použití rozhraní API časovače. Rozhraní API jsou velmi podobná časovači .NET nebo časovači Java. V tomto příkladu při splnění časovače modul runtime Actors zavolá metodu MoveObject
(C#) nebo moveObject
(Java). Metoda zaručuje dodržování souběžnosti na základě. To znamená, že nebudou probíhat žádné jiné metody objektu actor ani časovač nebo zpětná volání připomenutí, dokud tento zpětný hovor nedokončí provádění.
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;});
});
}
}
Další období časovače se spustí po dokončení provádění zpětného volání. To znamená, že časovač se zastaví, když se zpětné volání spouští a spustí se po dokončení zpětného volání.
Modul runtime Actors ukládá změny provedené správcem stavu objektu actor po dokončení zpětného volání. Pokud dojde k chybě při ukládání stavu, objekt actor bude deaktivován a bude aktivována nová instance.
Na rozdíl od připomenutí nelze časovače aktualizovat. Pokud RegisterTimer
se znovu zavolá, zaregistruje se nový časovač.
Všechny časovače se zastaví, když je objekt actor deaktivován jako součást uvolňování paměti. Po tom nejsou vyvolány žádné zpětná volání časovače. Modul runtime Actors také nezachovává žádné informace o časovači, které byly spuštěny před deaktivací. Je na objektu actor, aby zaregistroval všechny časovače, které potřebuje, když se v budoucnu znovu aktivuje. Další informace najdete v části o uvolňování paměti objektu actor.
Připomenutí objektu actor
Připomenutí jsou mechanismus pro aktivaci trvalých zpětných volání na objektu actor v určených časech. Jejich funkce jsou podobné časovačům. Na rozdíl od časovačů se ale připomenutí aktivují za všech okolností, dokud objekt actor explicitně neodregistruje nebo se objekt actor explicitně neodstraní. Konkrétně se připomenutí aktivují napříč deaktivací objektu actor a převzetím služeb při selhání, protože modul runtime Actors zachovává informace o připomenutích objektu actor pomocí zprostředkovatele stavu objektu actor. Na rozdíl od časovačů je možné existující připomenutí aktualizovat opětovným voláním metody registrace (RegisterReminderAsync
) pomocí stejného reminderName.
Poznámka:
Spolehlivost připomenutí je vázána na záruky spolehlivosti stavu poskytované poskytovatelem stavu objektu actor. To znamená, že pro aktéry, jejichž stálost stavu je nastavena na Žádné, připomenutí se po převzetí služeb při selhání neaktivují.
Pokud chcete zaregistrovat připomenutí, objekt actor volá metodu RegisterReminderAsync
uvedenou v základní třídě, jak je znázorněno v následujícím příkladu:
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
}
V tomto příkladu "Pay cell phone bill"
je název připomenutí. Jedná se o řetězec, který objekt actor používá k jednoznačné identifikaci připomenutí. BitConverter.GetBytes(amountInDollars)
(C#) je kontext přidružený k připomenutí. Předá se zpět objektu actor jako argument zpětnému volání připomenutí, tj. IRemindable.ReceiveReminderAsync
(C#) nebo Remindable.receiveReminderAsync
(Java).
Aktéři, kteří používají připomenutí, musí implementovat IRemindable
rozhraní, jak je znázorněno v následujícím příkladu.
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);
}
Když se aktivuje připomenutí, modul runtime Reliable Actors vyvolá metodu ReceiveReminderAsync
(C#) nebo receiveReminderAsync
(Java) na objektu Actor. Objekt actor může zaregistrovat více připomenutí a ReceiveReminderAsync
při aktivaci některého z těchto připomenutí se vyvolá metoda (C#) nebo receiveReminderAsync
(Java). Objekt actor může použít název připomenutí, který se předá ReceiveReminderAsync
metodě (C#) nebo receiveReminderAsync
(Java), aby zjistil, které připomenutí se aktivovalo.
Modul runtime Actors uloží stav objektu actor při ReceiveReminderAsync
dokončení volání (C#) nebo receiveReminderAsync
(Java). Pokud dojde k chybě při ukládání stavu, objekt actor bude deaktivován a bude aktivována nová instance.
Pokud chcete zrušit registraci připomenutí, objekt actor volá metodu UnregisterReminderAsync
(C#) nebo unregisterReminderAsync
(Java), jak je znázorněno v následujících příkladech.
IActorReminder reminder = GetReminder("Pay cell phone bill");
Task reminderUnregistration = await UnregisterReminderAsync(reminder);
ActorReminder reminder = getReminder("Pay cell phone bill");
CompletableFuture reminderUnregistration = unregisterReminderAsync(reminder);
Jak je znázorněno výše, UnregisterReminderAsync
metoda (C#) nebo unregisterReminderAsync
(Java) přijímá IActorReminder
rozhraní (C#) nebo ActorReminder
(Java). Základní třída objektu actor podporuje metodu GetReminder
(C#) nebo getReminder
(Java), kterou lze použít k načtení IActorReminder
rozhraní (C#) nebo ActorReminder
(Java) předáním názvu připomenutí. To je praktické, protože objekt actor nemusí uchovávat IActorReminder
rozhraní (C#) nebo ActorReminder
(Java), které bylo vráceno z RegisterReminder
volání metody (C#) nebo registerReminder
(Java).
Další kroky
Seznamte se s událostmi Reliable Actor a opětovnou relací: