Сохранить состояние зерна для внешней службы после некоторого периода бездействия - PullRequest
0 голосов
/ 09 апреля 2020

мы используем Orleans Grain в качестве сеанса, заполняем сеанс событиями и хотим сохранить сеанс во внешней службе после его истечения (после 20 минут бездействия). Первоначально мы собирались использовать GrainCollectionOptions.CollectionAge для сохранения сеанса при деактивации, но обнаружили, что в разных источниках небезопасно полагаться на OnDeactivateAsyn c, потому что он не всегда может быть вызван, особенно во время аварийного останова или жесткого отключения.

Кто-нибудь может предложить рекомендуемый подход для такого варианта использования?

Вот наш код зерна:

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();
    }
}

1 Ответ

3 голосов
/ 09 апреля 2020

Если постоянное состояние является жизненно важным и не может быть восстановлено, необходимо немедленно сохранить его, прежде чем вернуться к вызывающему, чтобы вызывающий мог повторить попытку в случае сбоя. Любые данные, которые не были сохранены, будут потеряны в случае сбоя (например, сбоя питания, но есть много других видов событий, которые приводят к тому же поведению).

Если допустимо потерять данные в случае сбоя, то у вас есть несколько вариантов:

  • Сохранить состояние во время OnDeactivateAsync; или
  • Сохранить состояние после некоторого простоя с помощью таймера (например, через this.RegisterTimer(...))
...