예제 #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));
 }
예제 #2
0
 public void Save(StateMachineContext entity)
 {
     using (var db = new LiteDatabase(this.connectionString))
     {
         db.GetCollection <StateMachineContext>().Upsert(entity);
     }
 }
예제 #3
0
        private async Task StoreContent(HttpContext httpContext, string key, StateMachineContext context, IStateMachineContextStorage contextStorage, IStateMachineContentStorage contentStorage)
        {
            var contentLength = httpContext.Request.ContentLength ?? 0;

            if (httpContext.Request.Body != null && contentLength > 0)
            {
                httpContext.Request.EnableBuffering(); // allow multiple reads
                httpContext.Request.Body.Position = 0;
                try
                {
                    using (var stream = new MemoryStream())
                    {
                        await httpContext.Request.Body.CopyToAsync(stream).ConfigureAwait(false);

                        this.logger.LogInformation($"statemachine: store content (name={context.Name}, id={context.Id}, key={key}, size={stream.Length}, type={httpContext.Request.ContentType})");
                        contentStorage.Save(context, $"{key}", stream, httpContext.Request.ContentType);
                        context.AddContent(key, httpContext.Request.ContentType, stream.Length);
                    }
                }
                catch (Exception ex)
                {
                    this.logger.LogWarning(ex, $"save content failed: {ex.Message}");
                }

                httpContext.Request.Body.Position = 0;
            }

            contextStorage.Save(context);
        }
예제 #4
0
        public Stream Load(StateMachineContext context, string key, Stream stream)
        {
            using var db = new LiteDatabase(this.connectionString);
            if (db.FileStorage.Exists($"{context.Id}/{key}"))
            {
                var fileInfo = db.FileStorage.Download($"{context.Id}/{key}", stream);
            }

            return(stream);
        }
예제 #5
0
        public void Save(StateMachineContext context, string key, Stream stream, string contentType)
        {
            using (var db = new LiteDatabase(this.connectionString))
            {
                if (db.FileStorage.Exists($"{context.Id}/{key}"))
                {
                    db.FileStorage.Delete($"{context.Id}/{key}");
                }

                db.FileStorage.Upload($"{context.Id}/{key}", key, stream);
            }
        }
예제 #6
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);
        }
예제 #7
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);
        }