Как я могу обеспечить стабильность зерна Орлеана?
В эрланге вы можете передать начальное состояние актеру при его порождении. Таким образом, вам не нужно иметь дело с сообщениями инициализации, которые снова переводят актера в исходное состояние, или с сообщениями, требующими сообщения инициализации, до этого. В Орлеане, учитывая, что зерна всегда существуют, вы не можете использовать конструкторы. Есть ли способ передать начальное состояние в зерна, избегая, таким образом, любого метода init, который нарушает согласованность, вызывая необходимость его вызова перед любым другим методом?
Когда я говорю "вернуть актера в его начальное состояние", я имею в виду, в контексте Орлеана, дважды вызывать метод init для конкретной активации зерна. Это как перезаписать состояние. Может быть, вам нужен этот король сообщений, который сбрасывает состояние, но если вам это не нужно, это ловушка, потенциальный источник ошибок.
Я ищу какой-то конструктор, что-то вроде spawn(module, function, [initial state])
из эрланга Моей первой попыткой было найти любую перегрузку GetGrain со следующей подписью: GrainFactory.GetGrain<IGrain>(id, initialState);
2 ответа
Как подсказывает @svick, OnActivateAsync
это лучший подход для загрузки исходного состояния для зерна.
public class ExampleGrain : Orleans.Grain, IExampleGrain
{
public override Task OnActivateAsync()
{
// set initial state for grain
return base.OnActivateAsync();
}
...
Этот метод будет вызываться каждый раз, когда зерно инициализируется (а не только в первый раз). Вы можете использовать встроенную в Орлеан инфраструктуру постоянства для записи того, было ли зерно создано ранее (возможно, с использованием логического свойства в вашем классе состояний), т.е.
public class ExampleGrainState : GrainState
{
public bool Initialised { get; set; }
}
[StorageProvider(ProviderName = "Storage")]
public class QuadKeyGrain : Orleans.Grain<ExampleGrainState>, IExampleGrain
{
public override async Task OnActivateAsync()
{
if (!this.State.Initialised)
{
// do initialisation
this.State.Initialised = true;
await this.WriteStateAsync();
}
await base.OnActivateAsync();
}
Смотрите этот учебник для получения дополнительной информации о постоянстве:
http://dotnet.github.io/orleans/Tutorials/Declarative-Persistence.html
Я только начинаю работать с Орлеаном, и, хотя это выглядит очень многообещающим, эта проблема начального состояния - это то, что я также изо всех сил пытаюсь понять.
С помощью POCO, в котором поведение изменяется с помощью параметров, можно настроить модификаторы доступа для соответствующих свойств / полей так, чтобы они могли быть установлены только конструктором. Таким образом, гарантируется, что экземпляр будет готов к использованию сразу после создания, и его поведение не может быть изменено позже. Но в Орлеане, похоже, нет никакого способа получить такие же гарантии. Кажется, мне нужно вызвать GetGrain, чтобы получить ссылку на зерно, затем вызвать для него какой-то метод инициализации, а затем использовать его. Но это означает, что я должен быть очень осторожен, чтобы гарантировать, что метод инициализации вызывается ровно один раз и только перед первым использованием. Кажется хрупким.
Существует предположение, что зерно данного типа + ключ всегда "существовало", по крайней мере, потенциально, и GetGrain используется просто для "поиска" зерна из ключевого пространства. Тем не менее, когда я вызываю GetGrain с использованием Guid.NewGuid в качестве ключа, становится ясно, что я не ожидаю, что такое зерно когда-либо существовало раньше; Я создаю зерно, а не просто нахожу его. Мне кажется, что в этот момент у меня должна быть возможность безопасно инициализировать его.
Тот факт, что это невозможно, заставляет меня подозревать, что мне что-то не хватает в том, как Орлеан должен использоваться на практике. Предполагается, что идентичность зерна полностью определяет его поведение? Если нет, то как люди обычно справляются с параметризованным поведением?
Зерна в Орлеане всегда существуют, поэтому вы с вашим подходом собираетесь [условно] переинициализировать зерно каждый раз, когда оно активируется. Это действительно то, что вы хотите сделать?
Что ж, если вам действительно нужно инициализировать конкретное зерно в определенное состояние, то вы можете использовать его ключ (строковый ключ или строковую часть ключа) для передачи некоторого json. Просто помните, что ключ имеет некоторые ограничения по размеру.