-
Notifications
You must be signed in to change notification settings - Fork 2
States, stages and other state machine stuff
Concept is simple. When you need to receive some specific input from user (text message, etc) you put him on stage, and next his update object will be processed not by common defined pipeline but with this specific stage handler. So at this handler you should check what you receive, compare with what you expected and either change his stage or not. Each stage also can have few steps. For example you need from user 3 messages with Last name, email and date of birth. You can handle it with same stage but different steps. So on 1st step you expect Last name, on 2nd email and so on.
So how to describe them in code?
[State(Stage = "input_something")]
public class InputState<TContext> : BasicState, IUpdateHandler<TContext> where TContext : IUpdateContext
{
public async Task HandleAsync(TContext context, UpdateDelegate<TContext> next, CancellationToken cancellationToken)
{
throw new System.NotImplementedException();
}
public InputState(TContext state) : base(state)
{ }
}
-
add attribute [State(Stage = "input here beginning of the stage name")] that string is used in runtime to find the needed handler. so, for example if you have stage with "start" users update will enter this handler when their stage value has start starting start_sadkqlje but he won`t enter if his stage is star
-
inherit BasicState, IUpdateHandler where TContext : IUpdateContext
abstract class BasicState allows you to override 2 methods:
public virtual async Task Enter()
{ }
public virtual async Task Exit()
{
State.UserState.Stage = "default";
State.UserState.Step = 0;
}
In future updates you will be able to resolve stages from context object and call this methods. For example entering the stage usually would happen with some message like "Please, enter your email". And if this stage may be entered with more then one other handler it is useful to keep some code there (avoid code duplicates) Same idea with Exit, but in addition you should specify where this user goes. In default implementation it returns to default.
Now, when you have some understanding of what that is and how it can be used lets talk about how it really works. For it to work we need some database where we will store all users stages, steps and data that he provided. At this moment there is 2 implemented providers to handle default stage data:
- MongoDB
- EF Core 1st needs existing MongoDB (example in console project) 2nd needs some EntityFramework database (example with SQLite is web app)
They handle only default fields. If you need any other fields - you need to make new Middleware and handle on your own.
PS: yeah, state, stage, a lot of misnaming in code, I really should fix it....