如何确保谷物的一致性?

时间:2015-11-25 15:34:15

标签: c# erlang actor orleans

在erlang中,你可以在产生它时将初始状态传递给actor。这样您就不需要处理初始状态的初始状态的init消息或者之前到达消息的消息。在奥尔良,假设谷物总是存在,你不能使用构造函数。有没有办法将初始状态传递给grain,从而避免任何init方法通过在任何其他方法之前调用它来破坏一致性?

当我说"把演员带到它的初始状态"时,我的意思是,在奥尔良语境中,调用特定粒子激活的init方法两次。这就像覆盖国家。也许你需要这个重置状态的消息之王,但如果你不需要它,那就是一个陷阱,一个潜在的错误来源。

我正在寻找某种类型的构造函数,例如来自erlang的spawn(module, function, [initial state])。我的第一次尝试是使用以下签名寻找GetGrain的任何重载:GrainFactory.GetGrain<IGrain>(id, initialState);

3 个答案:

答案 0 :(得分:3)

正如@svick建议的那样,OnActivateAsync是加载谷物初始状态的最佳方法。

 public class ExampleGrain : Orleans.Grain, IExampleGrain
 {

   public override Task OnActivateAsync()
   {
        // set initial state for grain
        return base.OnActivateAsync();
    }

 ...

每次初始化谷物时(而不仅仅是第一次)都会调用此方法。您可以使用Orleans中内置的Persistence基础结构来记录之前是否已创建粒度(可能在您的州类中使用布尔属性),即

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

答案 1 :(得分:0)

奥尔良的谷物一直存在,因此,每次激活谷物时,您都将[有条件地]重新初始化谷物。这真的是您想要做的吗?

好吧,如果您确实需要将特定的Grain初始化为特定的状态,则可以使用其键(字符串键或键的字符串部分)传递一些json。请记住,密钥在大小上有一些限制。

答案 2 :(得分:0)

我刚开始接触奥尔良,虽然看起来非常有前途,但我也一直难以理解这个初始状态问题。

对于通过参数修改行为的POCO,可以设置相关属性/字段的访问修饰符,使其只能由构造函数设置。这样,可以确保实例在构造后即可立即使用,并且实例的行为以后无法更改。但是在奥尔良,似乎没有任何方法可以实现相同的保证。看来我必须调用GetGrain来获取对Grain的引用,然后在其上调用某种初始化方法,然后再使用它。但这意味着我必须非常小心,以确保初始化方法仅在首次使用之前被调用一次。似乎很脆弱。

有一个假设,至少在 中,给定类型+密钥的谷物始终“存在”,并且GetGrain用于简单地从密钥空间中“查找”谷物。但是,当我使用Guid.NewGuid作为键来调用GetGrain时,很明显,我不希望谷物曾经存在过。我正在创造谷物,而不仅仅是找到它。在我看来,那时我应该有机会安全地对其进行初始化。

这是不可能的事实,这使我怀疑我缺少有关应该如何在实践中使用奥尔良的东西。谷物的身份是否应该完全定义其行为?如果没有,人们通常如何处理参数化行为?