* Added missing summaries
This commit is contained in:
@@ -4,6 +4,10 @@ using Telegrator.Core.States;
|
||||
|
||||
namespace Telegrator.States;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a Redis-based implementation of the <see cref="IStateStorage"/> interface.
|
||||
/// Serializes state objects to JSON format before storing them in the Redis database.
|
||||
/// </summary>
|
||||
public class RedisStateStorage(IConnectionMultiplexer redis) : IStateStorage
|
||||
{
|
||||
private readonly IDatabase _db = redis.GetDatabase();
|
||||
@@ -30,6 +34,6 @@ public class RedisStateStorage(IConnectionMultiplexer redis) : IStateStorage
|
||||
/// <inheritdoc/>
|
||||
public async Task DeleteAsync(string key, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
await _db.KeyDeleteAsync(key);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -6,14 +6,25 @@ using Telegrator.Filters;
|
||||
|
||||
namespace Telegrator.Annotations;
|
||||
|
||||
/// <summary>
|
||||
/// Attribute for filtering updates where resolved state matches target value.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="value"></param>
|
||||
public class StateAttribute<TKey, TValue>(TValue? value) : UpdateFilterAttribute<Update>(new StateKeyFilter<TKey, TValue>(value))
|
||||
where TKey : IStateKeyResolver, new()
|
||||
where TValue : IEquatable<TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// The targetting state value.
|
||||
/// </summary>
|
||||
public TValue? Value => value;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override UpdateType[] AllowedTypes => Update.AllTypes;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Update? GetFilterringTarget(Update update)
|
||||
{
|
||||
return update;
|
||||
|
||||
@@ -1,9 +1,44 @@
|
||||
namespace Telegrator.Core.States;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a contract for a state machine that manages transitions and retrieves states for specific updates.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The type of the state. Must implement <see cref="IEquatable{T}"/>.</typeparam>
|
||||
public interface IStateMachine<TState> where TState : IEquatable<TState>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the current state associated with the specified update key.
|
||||
/// </summary>
|
||||
/// <param name="storage">The storage mechanism used to persist the state.</param>
|
||||
/// <param name="updateKey">The unique key identifying the current update context (e.g., chat and user ID).</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains the current state, or the default value if no state is found.</returns>
|
||||
Task<TState?> Current(IStateStorage storage, string updateKey, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Advances the state machine to the next state in the sequence.
|
||||
/// </summary>
|
||||
/// <param name="storage">The storage mechanism used to persist the state.</param>
|
||||
/// <param name="updateKey">The unique key identifying the current update context.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A task that represents the asynchronous transition operation.</returns>
|
||||
Task Advance(IStateStorage storage, string updateKey, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Moves the state machine backward to the previous state in the sequence.
|
||||
/// </summary>
|
||||
/// <param name="storage">The storage mechanism used to persist the state.</param>
|
||||
/// <param name="updateKey">The unique key identifying the current update context.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A task that represents the asynchronous transition operation.</returns>
|
||||
Task Retreat(IStateStorage storage, string updateKey, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the state machine to its initial or default state.
|
||||
/// </summary>
|
||||
/// <param name="storage">The storage mechanism used to persist the state.</param>
|
||||
/// <param name="updateKey">The unique key identifying the current update context.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A task that represents the asynchronous reset operation.</returns>
|
||||
Task Reset(IStateStorage storage, string updateKey, CancellationToken cancellationToken = default);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,34 @@
|
||||
namespace Telegrator.Core.States;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a contract for an asynchronous state storage mechanism.
|
||||
/// </summary>
|
||||
public interface IStateStorage
|
||||
{
|
||||
/// <summary>
|
||||
/// Saves or updates a state value associated with the specified key.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the state object.</typeparam>
|
||||
/// <param name="key">The unique identifier for the state.</param>
|
||||
/// <param name="state">The state object to store.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A task that represents the asynchronous save operation.</returns>
|
||||
Task SetAsync<T>(string key, T state, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a state value associated with the specified key.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the state object to retrieve.</typeparam>
|
||||
/// <param name="key">The unique identifier for the state.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A task that represents the asynchronous retrieve operation. The task result contains the state object if found; otherwise, the default value of <typeparamref name="T"/>.</returns>
|
||||
Task<T?> GetAsync<T>(string key, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the state value associated with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique identifier for the state to remove.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <returns>A task that represents the asynchronous delete operation.</returns>
|
||||
Task DeleteAsync(string key, CancellationToken cancellationToken = default);
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,7 @@ namespace Telegrator.Handlers
|
||||
/// <param name="extraData"></param>
|
||||
/// <param name="filters"></param>
|
||||
/// <param name="awaitingProvider"></param>
|
||||
/// <param name="stateStorage"></param>
|
||||
public HandlerContainer(TUpdate actualUpdate, Update handlingUpdate, ITelegramBotClient client, Dictionary<string, object> extraData, CompletedFiltersList filters, IAwaitingProvider awaitingProvider, IStateStorage stateStorage)
|
||||
{
|
||||
ActualUpdate = actualUpdate;
|
||||
|
||||
@@ -3,10 +3,14 @@ using Telegrator.Core.States;
|
||||
|
||||
namespace Telegrator.States;
|
||||
|
||||
/// <summary>
|
||||
/// Defines default in-memory state storage
|
||||
/// </summary>
|
||||
public class DefaultStateStorage : IStateStorage
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, object> storage = [];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task DeleteAsync(string key, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (key is null)
|
||||
@@ -18,6 +22,7 @@ public class DefaultStateStorage : IStateStorage
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<T?> GetAsync<T>(string key, CancellationToken ccancellationTokent = default)
|
||||
{
|
||||
if (key is null)
|
||||
@@ -29,6 +34,7 @@ public class DefaultStateStorage : IStateStorage
|
||||
return Task.FromResult(default(T));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task SetAsync<T>(string key, T state, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (key is null)
|
||||
|
||||
@@ -3,6 +3,7 @@ using Telegrator.Core.States;
|
||||
|
||||
namespace Telegrator.States;
|
||||
|
||||
/// <inheritdoc cref="IStateMachine{TState}"/>
|
||||
public class StateMachine<TMachine, TState>(IStateStorage stateStorage, Update handlingUpdate)
|
||||
where TMachine : IStateMachine<TState>, new()
|
||||
where TState : IEquatable<TState>
|
||||
@@ -11,8 +12,12 @@ public class StateMachine<TMachine, TState>(IStateStorage stateStorage, Update h
|
||||
private readonly Update _handlingUpdate = handlingUpdate;
|
||||
private readonly IStateMachine<TState> _stateMachine = new TMachine();
|
||||
|
||||
/// <summary>
|
||||
/// Chosen key resolver
|
||||
/// </summary>
|
||||
public IStateKeyResolver? KeyResolver;
|
||||
|
||||
/// <inheritdoc cref="IStateMachine{TState}.Advance(IStateStorage, string, CancellationToken)"/>
|
||||
public async Task Advance(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (KeyResolver is null)
|
||||
@@ -25,6 +30,7 @@ public class StateMachine<TMachine, TState>(IStateStorage stateStorage, Update h
|
||||
await _stateMachine.Advance(_stateStorage, key, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStateMachine{TState}.Current(IStateStorage, string, CancellationToken)"/>
|
||||
public async Task<TState?> Current(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (KeyResolver is null)
|
||||
@@ -37,6 +43,7 @@ public class StateMachine<TMachine, TState>(IStateStorage stateStorage, Update h
|
||||
return await _stateMachine.Current(_stateStorage, key, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStateMachine{TState}.Reset(IStateStorage, string, CancellationToken)"/>
|
||||
public async Task Reset(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (KeyResolver is null)
|
||||
@@ -49,6 +56,7 @@ public class StateMachine<TMachine, TState>(IStateStorage stateStorage, Update h
|
||||
await _stateMachine.Reset(_stateStorage, key, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStateMachine{TState}.Retreat(IStateStorage, string, CancellationToken)"/>
|
||||
public async Task Retreat(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (KeyResolver is null)
|
||||
|
||||
@@ -284,30 +284,74 @@ namespace Telegrator
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for <see cref="IStateStorage"/> to easily initialize state machines.
|
||||
/// </summary>
|
||||
public static class StateStorageExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a state machine using the default <see cref="EnumStateMachine{TState}"/> for the specified update.
|
||||
/// </summary>
|
||||
/// <typeparam name="TState">The enum type representing the state.</typeparam>
|
||||
/// <param name="stateStorage">The storage mechanism used to persist the state.</param>
|
||||
/// <param name="handlingUpdate">The update context to resolve the state key from.</param>
|
||||
/// <returns>A new instance of <see cref="StateMachine{TMachine, TState}"/>.</returns>
|
||||
public static StateMachine<EnumStateMachine<TState>, TState> GetStateMachine<TState>(this IStateStorage stateStorage, Update handlingUpdate)
|
||||
where TState : struct, Enum, IEquatable<TState>
|
||||
=> new StateMachine<EnumStateMachine<TState>, TState>(stateStorage, handlingUpdate);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a specific custom state machine for the specified update.
|
||||
/// </summary>
|
||||
/// <typeparam name="TMachine">The type of the state machine logic implementation.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <param name="stateStorage">The storage mechanism used to persist the state.</param>
|
||||
/// <param name="handlingUpdate">The update context to resolve the state key from.</param>
|
||||
/// <returns>A new instance of <see cref="StateMachine{TMachine, TState}"/>.</returns>
|
||||
public static StateMachine<TMachine, TState> GetStateMachine<TMachine, TState>(this IStateStorage stateStorage, Update handlingUpdate)
|
||||
where TMachine : IStateMachine<TState>, new()
|
||||
where TState : IEquatable<TState>
|
||||
=> new StateMachine<TMachine, TState>(stateStorage, handlingUpdate);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a state machine and explicitly configures it to resolve keys by the chat ID.
|
||||
/// </summary>
|
||||
/// <typeparam name="TMachine">The type of the state machine logic implementation.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <param name="stateStorage">The storage mechanism used to persist the state.</param>
|
||||
/// <param name="handlingUpdate">The update context to resolve the state key from.</param>
|
||||
/// <returns>A configured instance of <see cref="StateMachine{TMachine, TState}"/>.</returns>
|
||||
public static StateMachine<TMachine, TState> ByChatId<TMachine, TState>(this IStateStorage stateStorage, Update handlingUpdate)
|
||||
where TMachine : IStateMachine<TState>, new()
|
||||
where TState : IEquatable<TState>
|
||||
=> new StateMachine<TMachine, TState>(stateStorage, handlingUpdate).ByChatId();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a state machine and explicitly configures it to resolve keys by the sender (user) ID.
|
||||
/// </summary>
|
||||
/// <typeparam name="TMachine">The type of the state machine logic implementation.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <param name="stateStorage">The storage mechanism used to persist the state.</param>
|
||||
/// <param name="handlingUpdate">The update context to resolve the state key from.</param>
|
||||
/// <returns>A configured instance of <see cref="StateMachine{TMachine, TState}"/>.</returns>
|
||||
public static StateMachine<TMachine, TState> BySenderId<TMachine, TState>(this IStateStorage stateStorage, Update handlingUpdate)
|
||||
where TMachine : IStateMachine<TState>, new()
|
||||
where TState : IEquatable<TState>
|
||||
=> new StateMachine<TMachine, TState>(stateStorage, handlingUpdate).BySenderId();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides fluent extension methods for configuring <see cref="StateMachine{TMachine, TState}"/> instances.
|
||||
/// </summary>
|
||||
public static class StateMachineExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures the state machine to use a <see cref="ChatIdResolver"/> for state key resolution.
|
||||
/// </summary>
|
||||
/// <typeparam name="TMachine">The type of the state machine logic implementation.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <param name="stateMachine">The state machine instance to configure.</param>
|
||||
/// <returns>The same state machine instance for method chaining.</returns>
|
||||
public static StateMachine<TMachine, TState> ByChatId<TMachine, TState>(this StateMachine<TMachine, TState> stateMachine)
|
||||
where TMachine : IStateMachine<TState>, new()
|
||||
where TState : IEquatable<TState>
|
||||
@@ -316,6 +360,13 @@ namespace Telegrator
|
||||
return stateMachine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures the state machine to use a <see cref="SenderIdResolver"/> for state key resolution.
|
||||
/// </summary>
|
||||
/// <typeparam name="TMachine">The type of the state machine logic implementation.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <param name="stateMachine">The state machine instance to configure.</param>
|
||||
/// <returns>The same state machine instance for method chaining.</returns>
|
||||
public static StateMachine<TMachine, TState> BySenderId<TMachine, TState>(this StateMachine<TMachine, TState> stateMachine)
|
||||
where TMachine : IStateMachine<TState>, new()
|
||||
where TState : IEquatable<TState>
|
||||
|
||||
Reference in New Issue
Block a user