Как передать данные в OnActivateAsync() для инициализации моего актера с состоянием?
Я создаю надежного, с государственным обслуживанием актера.
Вопрос:
Есть ли способ передать данные инициализации при создании прокси актера (ActorProxy.Create()
)? В основном эквивалент конструктора для моего актера.
Текущие мысли:
Я могу добиться этого, следуя вызову создания прокси с помощью вызова метода субъекта, отвечающего за инициализацию состояния.
Например
//Danger, the following calls are not atomic
ITokenManager tokenActor = ActorProxy.Create<IMyActor>(actorId, "AppName");
//Something could happen here and leave my actor in an unknown state
await tokenActor.InitializeAsync(desiredInitialState);
Моя забота о таком подходе:
- Эта операция не является атомарной. Это может оставить моего актера в противоречивом состоянии
- Этот метод инициализации теперь доступен на протяжении всей жизни актера, что нежелательно.
3 ответа
Пару мыслей для вас здесь. Например, данные, необходимые для инициализации, действительно недоступны самому актеру во время OnActivateAsync
? Обычно, если я полагаюсь на получение некоторых начальных данных в состоянии моего актера, я бы так и сделал.
protected override Task OnActivateAsync()
{
if (State == null)
{
var initialState = await externalSource.GetSomeState();
// simplified here but map the values properly onto the actual actor state
this.State = initialState;
return base.OnActivateAsync();
}
}
Другая мысль заключается в том, что если вы действительно не можете заставить актера извлекать данные во время его собственной активации, вам очень легко создать логическое свойство, которое является частью состояния актера, указывающее, имеет ли другая активация, о которой вы говорите, когда-либо происходило.
public Task InitializeAsync(State someState)
{
if (State.IsActivated)
{
// log out here that someone is attempting to reactivate when they shouldn't
return Task.CompletedTask;
}
State = someState;
State.IsActivated = true;
return Task.CompletedTask;
}
Таким образом, хотя технически метод будет доступен для вызова в течение всего срока действия субъекта, у вас есть однопотоковая гарантия, что он действительно будет делать что-то только при первом вызове.
Кажется, что лучший подход для атомарной инициализации - это сохранить данные инициализации в каком-то внешнем хранилище, а во время OnActivateAsync() использовать эти данные из этого хранилища.
Создание прокси не эквивалентно конструктору. В Service Fabric клиент не должен знать, был ли уже создан субъект, и жизненный цикл управляется средой выполнения.
Таким образом, сам актер должен инициализироваться до некоторого состояния по умолчанию. Задача реализации актера - предотвращать другие вызовы перед вызовами инициализации и предотвращать множественную инициализацию, если это необходимо. Поскольку актеры всегда являются однопоточными, это может быть легко достигнуто с помощью чего-то вроде логических флагов.