Ejemplo n.º 1
0
 public StateMachine CreateInstance(StateMachineContext context, ITransitionDispatcher dispatcher)
 {
     context.Name = this.Name;
     context.State ??= this.InitialState;
     context.Ttl = this.Ttl;
     return(StateMachine.Create(context, dispatcher, this.configuration));
 }
Ejemplo n.º 2
0
        private async Task <bool> HandleGetTriggersRequest(
            HttpContext httpContext,
            IStateMachineContextStorage contextStorage,
            IEnumerable <IStatemachineDefinition> definitions,
            ITransitionDispatcher dispatcher)
        {
            var segments = this.routeMatcher.Match(this.options.RoutePrefix + "/{name}/{id}/triggers", httpContext.Request.Path);

            if (segments?.ContainsKey("name") == true && segments?.ContainsKey("id") == true)
            {
                this.logger.LogInformation($"statemachine: get triggers (name={segments["name"]}, id={segments["id"]})");
                var definition = definitions.Safe()
                                 .FirstOrDefault(d => d.Name.Equals(segments["name"] as string, StringComparison.OrdinalIgnoreCase));
                if (definition == null)
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    var details = new ProblemDetails()
                    {
                        Title    = "state machine definition not found",
                        Status   = (int)HttpStatusCode.BadRequest,
                        Instance = $"{this.options.RoutePrefix}/{segments["name"]}/{segments["id"]}",
                    };

                    httpContext.Response.ContentType = "application/json";
                    await httpContext.Response.WriteAsync(JsonConvert.SerializeObject(details, JsonSerializerSettings.Create()), Encoding.UTF8).ConfigureAwait(false);

                    return(true);
                }

                var context = contextStorage.FindById(segments["id"] as string);
                if (context == null)
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    return(true);
                }

                if (!context.Name.Equals(segments["name"] as string, StringComparison.OrdinalIgnoreCase))
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    return(true);
                }

                var instance = definition.CreateInstance(context, dispatcher);

                httpContext.Response.StatusCode  = (int)HttpStatusCode.OK;
                httpContext.Response.ContentType = "application/json";
                httpContext.Response.Headers.Add("Location", $"{this.options.RoutePrefix}/{segments["name"]}/{context.Id}");
                await httpContext.Response.WriteAsync(JsonConvert.SerializeObject(instance.PermittedTriggers, JsonSerializerSettings.Create()), Encoding.UTF8).ConfigureAwait(false);

                return(true);
            }

            return(false);
        }
Ejemplo n.º 3
0
        private async Task <bool> HandleCreateNewRequest(
            HttpContext httpContext,
            IStateMachineContextStorage contextStorage,
            IStateMachineContentStorage contentStorage,
            IEnumerable <IStatemachineDefinition> definitions,
            ITransitionDispatcher dispatcher)
        {
            var segments = this.routeMatcher.Match(this.options.RoutePrefix + "/{name}", httpContext.Request.Path);

            if (segments?.ContainsKey("name") == true)
            {
                this.logger.LogInformation($"statemachine: create new (name={segments["name"]})");
                var definition = definitions.Safe()
                                 .FirstOrDefault(d => d.Name.Equals(segments["name"] as string, StringComparison.OrdinalIgnoreCase));
                if (definition == null)
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    var details = new ProblemDetails()
                    {
                        Title    = "state machine definition not found",
                        Status   = (int)HttpStatusCode.BadRequest,
                        Instance = $"{this.options.RoutePrefix}/{segments["name"]}",
                    };

                    httpContext.Response.ContentType = "application/json";
                    await httpContext.Response.WriteAsync(JsonConvert.SerializeObject(details, JsonSerializerSettings.Create()), Encoding.UTF8).ConfigureAwait(false);

                    return(true);
                }

                var context = new StateMachineContext()
                {
                    Created = DateTime.UtcNow, Updated = DateTime.UtcNow
                };
                httpContext.Request.Query.ForEach(i => context.Properties.AddOrUpdate(i.Key, i.Value));

                var instance = definition.CreateInstance(context, dispatcher);
                instance.Activate();
                await this.StoreContent(httpContext, "_current", context, contextStorage, contentStorage).ConfigureAwait(false);

                await this.StoreContent(httpContext, context.State, context, contextStorage, contentStorage).ConfigureAwait(false);

                httpContext.Response.StatusCode  = (int)HttpStatusCode.Created;
                httpContext.Response.ContentType = "application/json";
                httpContext.Response.Headers.Add("Location", $"{this.options.RoutePrefix}/{segments["name"]}/{context.Id}");
                await httpContext.Response.WriteAsync(JsonConvert.SerializeObject(context, JsonSerializerSettings.Create()), Encoding.UTF8).ConfigureAwait(false);

                return(true);
            }

            return(false);
        }
Ejemplo n.º 4
0
        public static StateMachine Create(
            StateMachineContext context,
            ITransitionDispatcher dispatcher,
            Action <StateMachine> configuration = null)
        {
            var result = new StateMachine(context.State)
            {
                Context    = context,
                Dispatcher = dispatcher
            };

            configuration?.Invoke(result);
            return(result);
        }
Ejemplo n.º 5
0
        private async Task <bool> HandleFireTriggerRequest(
            HttpContext httpContext,
            IStateMachineContextStorage contextStorage,
            IStateMachineContentStorage contentStorage,
            IEnumerable <IStatemachineDefinition> definitions,
            ITransitionDispatcher dispatcher)
        {
            var segments = this.routeMatcher.Match(this.options.RoutePrefix + "/{name}/{id}/triggers/{trigger}", httpContext.Request.Path);

            if (segments?.ContainsKey("name") == true && segments?.ContainsKey("id") == true && segments?.ContainsKey("trigger") == true)
            {
                this.logger.LogInformation($"statemachine: fire trigger (name={segments["name"]}, id={segments["id"]}, trigger={segments["trigger"]})");

                var definition = definitions.Safe()
                                 .FirstOrDefault(d => d.Name.Equals(segments["name"] as string, StringComparison.OrdinalIgnoreCase));
                if (definition == null)
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    var details = new ProblemDetails()
                    {
                        Title    = "state machine definition not found",
                        Status   = (int)HttpStatusCode.BadRequest,
                        Instance = $"{this.options.RoutePrefix}/{segments["name"]}/{segments["id"]}",
                    };

                    httpContext.Response.ContentType = "application/json";
                    await httpContext.Response.WriteAsync(JsonConvert.SerializeObject(details, JsonSerializerSettings.Create()), Encoding.UTF8).ConfigureAwait(false);

                    return(true);
                }

                var context = contextStorage.FindById(segments["id"] as string);
                if (context == null)
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    return(true);
                }

                if (context.IsExpired())
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    var details = new ProblemDetails()
                    {
                        Title    = "state machine is expired",
                        Status   = (int)HttpStatusCode.BadRequest,
                        Instance = $"{this.options.RoutePrefix}/{context.Name}/{context.Id}",
                    };

                    httpContext.Response.ContentType = "application/json";
                    await httpContext.Response.WriteAsync(JsonConvert.SerializeObject(details, JsonSerializerSettings.Create()), Encoding.UTF8).ConfigureAwait(false);

                    return(true);
                }

                if (!context.Name.Equals(segments["name"] as string, StringComparison.OrdinalIgnoreCase))
                {
                    httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    return(true);
                }

                httpContext.Request.Query.ForEach(i => context.Properties.AddOrUpdate(i.Key, i.Value));
                var instance = definition.CreateInstance(context, dispatcher);
                try
                {
                    await this.StoreContent(httpContext, "_current", context, contextStorage, contentStorage).ConfigureAwait(false);

                    if (await instance.FireAsync(segments["trigger"] as string).ConfigureAwait(false))
                    {
                        await this.StoreContent(httpContext, context.State, context, contextStorage, contentStorage).ConfigureAwait(false);

                        this.logger.LogInformation($"statemachine: trigger successfull (name={segments["name"]}, id={segments["id"]}, trigger={segments["trigger"]})");
                        contextStorage.Save(context);

                        httpContext.Response.StatusCode = (int)HttpStatusCode.OK;
                    }
                    else
                    {
                        this.logger.LogError($"statemachine: trigger invalid (name={segments["name"]}, id={segments["id"]}, trigger={segments["trigger"]})");
                        httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    }
                }
                catch (Exception ex)
                {
                    this.logger.LogCritical(ex, $"statemachine: trigger failed (name={segments["name"]}, id={segments["id"]}, trigger={segments["trigger"]}) {ex.Message}");
                    httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                }
                finally
                {
                    this.logger.LogInformation($"statemachine: permitted triggers={string.Join("|", instance.PermittedTriggers)}");
                    contextStorage.Save(context);
                }

                return(true);
            }

            return(false);
        }