一段时间不活动后将 Grain 状态保存到外部服务

Ser*_*kin 1 .net orleans

我们使用 Orleans Grain 作为会话,用事件填充会话,并希望在会话过期后(20 分钟不活动后)将会话保存到外部服务。最初我们打算使用 GrainCollectionOptions.CollectionAge 来保存停用时的会话,但在不同的来源中发现依赖 OnDeactivateAsync 并不安全,因为它可能并不总是被调用,特别是在筒仓崩溃或硬关闭期间。

有人可以建议针对此类用例的推荐方法吗?

这是我们的 Grain 代码:

public class SessionGrain : Grain, ISessionGrain
{
    private readonly IPersistentState<Session> _persistentState;

    public SessionGrain([PersistentState("sessionsState", "sessionsStorage")] IPersistentState<Session> persistentState)
    {
        _persistentState = persistentState;
    }

    public Task CompleteAsync()
    {
        DeactivateOnIdle();
        return Task.CompletedTask;
    }

    public async Task<Session> TrackEventAsync(Event @event)
    {
        _persistentState.State.Events.Add(@event);

        await _persistentState.WriteStateAsync();

        return _persistentState.State;
    }

    public override async Task OnActivateAsync()
    {
        if (_persistentState.State == null)
        {
            _persistentState.State = new Session();
        }

        await base.OnActivateAsync();
    }

    public override async Task OnDeactivateAsync()
    {
        // TODO: SAVE TO EXTERNAL SERVICE HERE???

        await _persistentState.ClearStateAsync();

        await base.OnDeactivateAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

Reu*_*ond 6

如果持久状态至关重要并且无法重建,那么您必须在返回给调用者之前立即保存它,以便调用者可以在发生故障时重试。如果发生故障(例如电源故障,但还有许多其他类型的事件会导致相同的行为),任何未持久保存的数据都将丢失。

如果发生故障时丢失数据是可以接受的,那么您有几个选择:

  • OnDeactivateAsync期间保存状态;或者
  • 使用计时器(例如,via this.RegisterTimer(...))在一段空闲时间后保存状态

  • 好的,原来的问题说你“想要在会话过期后将会话保存到外部服务”。如果你想确保外部服务清理状态,那么你有几个选择: * 使用grain提醒(可靠的计时器)在一段时间后唤醒grain并确保其状态被删除 * 扫描你的存储并删除过时的状态 * 使用存储中的 TTL 功能(例如,CosmosDB 提供此功能)来自动删除不必要的状态 (3认同)