2016-07-08 6 views
2

Wie kann ich herausfinden, ob ein Actor mit einer bestimmten ActorId existiert?Azure Service Fabric: Wie finde ich heraus, ob ein Actor bereits existiert?

Der ActorProxy dient nur zum Erstellen eines Actors. Wenn eine nicht vorhandene ID bereitgestellt wird und der Actor nicht vorhanden ist, wird ein neuer Actor erstellt.

Der Standard ActorService kann alle Actors abrufen, aber das ist soweit, wie ich sehen kann.

+0

Ich bin neugierig - warum brauchen Sie das? –

+0

Wenn ein Actor eine Rechnung ist und die Rechnung gelöscht wurde und ein alter Link zum Abrufen der Rechnung verwendet wird, wird die Rechnung neu erstellt. Aber es wird leer sein. Oder schaue ich Schauspieler in die falsche Richtung? – Martin

+1

Da Schauspieler automatisch Müll gesammelt werden, ist es nicht schlimm, den Schauspieler wieder erschaffen zu lassen. Microsoft behauptet, dass Sie Millionen von Actor-Instanzen haben können. Außerdem würde ich Daten nicht löschen - es ist besser, die Rechnung mit einem gelöschten Status zu markieren. –

Antwort

4

Derzeit gibt es keine einfache Möglichkeit, dies zu tun. Akteure sollen die Lebensdauer der Instanz eines Gegenstandes weg abstrahieren. Ruf einfach eines an, wenn du es brauchst, und es wird da sein. Ich bin mir also nicht sicher, ob das wirklich nötig ist.

Das heißt, Sie könnten eine andere Service-Methode erstellen, um alle Akteure auf der Serverseite zu durchlaufen, statt die gesamte Liste auf den Client zu ziehen, aber wenn Sie Millionen von Actor-Instanzen haben, wird es nicht sehr effizient sein .

Alternativ können Sie einen Markierungsstatus während der Initialisierung Ihres Actors speichern und den State-Provider danach abfragen - auf Kosten des Hinzufügens von mehr Status- und Replikations-Overhead zu Ihrem Actor.

Erstellen Sie zunächst eine Service-Schnittstelle:

public interface IActorServiceEx : IService 
{ 
    Task<bool> ActorExists(ActorId actorId, CancellationToken cancellationToken = default(CancellationToken)); 
} 

Dann einen benutzerdefinierten Schauspieler Dienst erstellen, die diese Schnittstelle implementiert:

internal class CustomActorService : ActorService, IActorServiceEx 
{ 
    public CustomActorService(StatefulServiceContext context, ActorTypeInformation actorTypeInfo, Func<ActorBase> actorFactory = null, IActorStateProvider stateProvider = null, ActorServiceSettings settings = null) 
     : base(context, actorTypeInfo, actorFactory, stateProvider, settings) 
    { 
    } 

    public async Task<bool> ActorExists(ActorId actorId, CancellationToken cancellationToken) 
    { 
     const int batchSize = 1000; 
     ContinuationToken token = null; 
     do 
     { 
      var actors = await StateProvider.GetActorsAsync(batchSize, token, cancellationToken); 
      if (actors.Items.Contains(actorId)) 
      { 
       return true; 
      } 
      token = actors.ContinuationToken; 
     } while (token != null); 
     return false; 
    } 
} 

Oder die alternative Version mit dem Marker:

internal class Actor1 : Actor, IActor1 
{ 
    protected override async Task OnActivateAsync() 
    { 
     await StateManager.TryAddStateAsync("Activated", true); 
    } 
} 

internal class CustomActorService : ActorService, IActorServiceEx 
{ 
    ... 

    public Task<bool> ActorExists(ActorId actorId, CancellationToken cancellationToken) 
    { 
     return StateProvider.ContainsStateAsync(actorId, "Activated", cancellationToken); 
    } 
} 

Schließlich, verwenden Sie es bei der Registrierung Ihres Schauspielers, zB:

ActorRuntime.RegisterActorAsync<Actor1>((context, actorType) => 
    new CustomActorService(context, actorType, 
    () => new Actor1())).GetAwaiter().GetResult(); 

Und diesen neuen Service-Methode aufzurufen:

var actorService = ActorServiceProxy.Create<IActorServiceEx>(serviceUri, actorId); 

var exists = await actorService.ActorExists(actorId); 
+0

Dies funktioniert nicht, wenn 'ActorId.CreateRandom()' verwendet wird. Sie erhalten einen Verweis auf eine zufällige Partition und der IActorStateProvider sieht nur die Aktoren in dieser Partition. Ich aktualisierte die Antwort, so dass es die gleiche Actor-ID sowohl zum Erstellen des IActorServiceEx-Proxys als auch zum Überprüfen, ob es existiert, verwendet. –

+0

Ich glaube, das wird immer die "Aktiviert" immer die ganze Zeit wahr – alltej