2

我的要求是启动一个长时间运行的过程来标记所有过期的产品。这在每晚凌晨 1:00 运行。客户可能正在访问网站上的某些产品,因此他们在作业运行时有实例。其他人在持久媒体中,还没有实例,因为客户没有访问它们。

我应该在哪里连接逻辑以从持久媒体读取演员的最新状态并创建一个全新的演员?我应该在Prestart覆盖方法中调用吗?如果是这样,我如何告诉ProductActor正在创建一个新的 Actor。

或者我应该向像LoadMeFromAzureTable这样的ProductActor发送消息,该消息将在创建 Actor 后从持久媒体加载状态?

4

1 回答 1

3

根据您的需要,有不同的方法可以做到这一点,而不是只有一个“正确”的答案。

您可以使用Persistent Actor在启动时自动从持久存储中恢复状态(或在崩溃的情况下进行恢复)。或者,如果您不想使用该模块(截至 2015 年 7 月仍处于测试阶段),您可以自己使用以下两种方法之一:

1) 您可以在 中加载您的状态PreStart,但如果您可以通过数据库客户端使操作异步并使用PipeTo模式将结果逐步发送回您自己,我只会这样做。但是,如果您需要在开始工作之前将所有状态都保存在内存中,那么您需要...

2)使用行为切换制作一个有限状态机。从门控状态开始,向自己发送一条消息以加载数据,并存储所有进入的内容。然后切换到接收状态并在状态加载完成后取消存储所有消息。这是我更喜欢的方法。

示例(只是用 a 模拟数据库负载Task):

public class ProductActor : ReceiveActor, IWithUnboundedStash
{
    public IStash Stash { get; set; }

    public ProductActor()
    {
        // begin in gated state
        BecomeLoading();
    }

    private void BecomeLoading()
    {
        Become(Loading);
        LoadInitialState();
    }

    private void Loading()
    {
        Receive<DoneLoading>(done =>
        {
            BecomeReady();
        });

        // stash any messages that come in until we're done loading
        ReceiveAny(o =>
        {
            Stash.Stash();
        });
    }

    private void LoadInitialState()
    {
        // load your state here async & send back to self via PipeTo
        Task.Run(() =>
        {
            // database loading task here
            return new Object();
        }).ContinueWith(tr =>
        {
            // do whatever (e.g. error handling)
            return new DoneLoading();
        }).PipeTo(Self);
    }

    private void BecomeReady()
    {
        Become(Ready);
        // our state is ready! put all those stashed messages back in the mailbox
        Stash.UnstashAll();
    }

    private void Ready()
    {
        // handle those unstashed + new messages...

        ReceiveAny(o =>
        {
            // do whatever you need to do...
        });
    }
}

/// <summary>
/// Marker interface.
/// </summary>
public class DoneLoading {}
于 2015-07-24T22:18:44.257 回答