Поделиться через


Надёжные акторы: повторный вход

Среда выполнения Reliable Actors по умолчанию позволяет повторно выполнять логический вызов на основе контекста. Это позволяет субъектам повторно применяться, если они находятся в той же цепочке контекста вызова. Например, субъект A отправляет сообщение субъекту B, который отправляет сообщение субъекту C. В рамках обработки сообщений, если субъект C вызывает субъект A, сообщение повторно перенаправится, поэтому оно будет разрешено. Все другие сообщения, которые являются частью другого контекста вызова, будут заблокированы для субъекта A, пока не завершится обработка.

Существует два варианта повторного входа актора, определённые в перечислении ActorReentrancyMode:

  • LogicalCallContext (поведение по умолчанию)
  • Disallowed — отключает повторный вход
public enum ActorReentrancyMode
{
    LogicalCallContext = 1,
    Disallowed = 2
}
public enum ActorReentrancyMode
{
    LogicalCallContext(1),
    Disallowed(2)
}

Реентрабельность можно настроить в ActorService параметрах во время регистрации. Этот параметр применяется ко всем экземплярам актёров, созданным в актёрском сервисе.

В следующем примере показана служба акторов, которая задает для режима повторного входа значение ActorReentrancyMode.Disallowed. В этом случае, если субъект отправляет повторное сообщение другому субъекту, создается исключение типа FabricException .

static class Program
{
    static void Main()
    {
        try
        {
            ActorRuntime.RegisterActorAsync<Actor1>(
                (context, actorType) => new ActorService(
                    context,
                    actorType, () => new Actor1(),
                    settings: new ActorServiceSettings()
                    {
                        ActorConcurrencySettings = new ActorConcurrencySettings()
                        {
                            ReentrancyMode = ActorReentrancyMode.Disallowed
                        }
                    }))
                .GetAwaiter().GetResult();

            Thread.Sleep(Timeout.Infinite);
        }
        catch (Exception e)
        {
            ActorEventSource.Current.ActorHostInitializationFailed(e.ToString());
            throw;
        }
    }
}
static class Program
{
    static void Main()
    {
        try
        {
            ActorConcurrencySettings actorConcurrencySettings = new ActorConcurrencySettings();
            actorConcurrencySettings.setReentrancyMode(ActorReentrancyMode.Disallowed);

            ActorServiceSettings actorServiceSettings = new ActorServiceSettings();
            actorServiceSettings.setActorConcurrencySettings(actorConcurrencySettings);

            ActorRuntime.registerActorAsync(
                Actor1.getClass(),
                (context, actorType) -> new FabricActorService(
                    context,
                    actorType, () -> new Actor1(),
                    null,
                    stateProvider,
                    actorServiceSettings, timeout);

            Thread.sleep(Long.MAX_VALUE);
        }
        catch (Exception e)
        {
            throw e;
        }
    }
}

Дальнейшие действия