Единственный официальный способ проверить, был ли актер активирован в каком-либо Сервисном разделе ранее, - это запрос ActorServiceProxy
, как описано здесь :
IActorService actorServiceProxy = ActorServiceProxy.Create(
new Uri("fabric:/MyApp/MyService"), partitionKey);
ContinuationToken continuationToken = null;
do
{
PagedResult<ActorInformation> page = await actorServiceProxy.GetActorsAsync(continuationToken, cancellationToken);
var actor = page.Items.FirstOrDefault(x => x.ActorId == idToFind);
continuationToken = page.ContinuationToken;
}
while (continuationToken != null);
По своей природе актеры SF являются виртуальными, что означает, что они всегда существуют, даже если вы не активировали ранее, поэтому сделать эту проверку немного сложнее.
Как вы сказали, опрашивать всех актеров нецелесообразно, поэтому вы можете попробовать и другие обходные пути:
Храните идентификаторы в надежном словаре в другом месте, каждый раз, когда активируется актер, вы инициируете событие и вставляете идентификаторы ActorID в словарь, если его еще нет.
- Вы можете использовать
OnActivateAsync()
событие актера, чтобы уведомить о его создании, или
- Вы можете использовать пользовательскую фабрику акторов в ActorService для регистрации активации актера
- Вы можете сохранить словарь в другом актере или другом StatefulService
Создать в акторе свойство, которое устанавливается самим актером при его активации.
-
OnActivateAsync()
проверяет, было ли установлено это свойство до
- Если еще не установлено, вы устанавливаете новое значение и сохраняете в переменной (непостоянное значение), чтобы сказать, что актер новый
- Всякий раз, когда вы взаимодействуете с актером, вы устанавливаете это, чтобы указать, что он больше не нов.
- При следующей активации свойство уже будет установлено, и ничего не должно происходить.
Создайте собственный IActorStateProvider, чтобы сделать то же самое, что упомянуто в варианте 2, вместо того, чтобы обрабатывать его в актере, он будет обрабатывать уровень под ним. Честно говоря, я думаю, что это немного поработало, было бы удобно, если бы вы делали то же самое для многих типов актеров, варианты 1 и 2 были бы намного проще.
Делать как Питер Бонс Рекомендуется, хранить ActorID вне ActorService, как в БД, Я бы предложил этот вариант, только если вы должны проверить это снаружи кластера .
.
Следующие фрагменты могут помочь вам, если вы хотите управлять этими событиями вне субъекта.
private static void Main()
{
try
{
ActorRuntime.RegisterActorAsync<NetCoreActorService>(
(context, actorType) => new ActorService(context, actorType,
new Func<ActorService, ActorId, ActorBase>((actorService, actorId) =>
{
RegisterActor(actorId);//The custom method to register the actor if new
return (ActorBase)Activator.CreateInstance(actorType.ImplementationType, actorService, actorId);
})
)).GetAwaiter().GetResult();
Thread.Sleep(Timeout.Infinite);
}
catch (Exception e)
{
ActorEventSource.Current.ActorHostInitializationFailed(e.ToString());
throw;
}
}
private static void RegisterActor(ActorId actorId)
{
//Here you will put the logic to register elsewhere the actor creation
}