// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. namespace Microsoft.Teams.Apps.State; /// /// Holds the conversation-scoped and user-scoped state for the current turn. /// public sealed class TurnStateContainer { private Func? _deleteDelegate; /// /// Gets the conversation-scoped state, shared by all users in the conversation. /// Keyed by Conversation.Id. /// public TurnState ConversationState { get; } /// /// Gets the user-scoped state, private to each user in each conversation. /// Keyed by Conversation.Id + From.Id. /// Returns when the activity has no From field. /// public TurnState? UserState { get; } /// /// Initializes a new instance of the class. /// public TurnStateContainer(TurnState conversationState, TurnState? userState) { ArgumentNullException.ThrowIfNull(conversationState); ConversationState = conversationState; UserState = userState; } /// /// Sets the delegate used to delete state from the backing store. /// Called by the framework after loading state. /// internal void SetDeleteDelegate(Func deleteDelegate) { _deleteDelegate = deleteDelegate; } /// /// Deletes conversation and user state from the backing store. /// The in-memory state remains accessible for the rest of the turn /// but will not be persisted at end-of-turn unless new values are written. /// /// A cancellation token. public async Task DeleteAsync(CancellationToken cancellationToken = default) { if (_deleteDelegate is null) { throw new InvalidOperationException( "State deletion is not available. Call UseState() during service registration."); } await _deleteDelegate(cancellationToken).ConfigureAwait(false); // Clear dirty flags so end-of-turn save doesn't re-persist the deleted state. ConversationState.IsDirty = false; if (UserState is not null) { UserState.IsDirty = false; } } }