private static void AttemptCleanup(Database db, Execution execution, WorkflowObj workflow, List <History> decisions) { if (ExState.Create(execution.ExecutionState.State) == ExState.Cleanup) { StopWorkflow(execution, decisions); return; } try { var cleanupStartTask = workflow.Tasks.SingleOrDefault(t => t.ActivityName == "cleanup"); if (cleanupStartTask == null) { StopWorkflow(execution, decisions); return; } var cleanupTaskId = cleanupStartTask.Outflows.Single(o => o.Name == "Out").Target; var cleanupTask = workflow.Tasks.Single(t => t.TaskId == cleanupTaskId); decisions.Add(new WorkflowCleanupStartedEvent()); CreateTaskScheduledEvent(db, execution, cleanupTask, decisions); } catch (Exception ex) { log.Error("Exception thrown from cleanup", ex); StopWorkflow(execution, decisions); } }
public C Create(Context data) { ExState exState = ContextToExState(data); InState inState = ContextToInState(data); return(new C(inState, exState)); }
// Large footprint public void Op(ExState anExState) { // Uses both intrinsic and // extrinsic state }
public bool ExUpdate(float ctime, float bp, ref bool[] button, ref bool[] released, ref MarkManager.EffectType check, bool auto, ref int soundtype, MarkManager.EvaluateEffectHandler effectcallback) { bool ret = false; lasttime = ctime; //base.Update(ctime, bp, ref button, ref check, auto, ref soundtype); if (!auto) { if (exstate == ExState.waitingpress) { if (button[(int)ButtonType]) { int a = evaluate(this.time, ctime - adjustgaptime); if (a > 1) { button[(int)ButtonType] = false; } switch (a) { // if more than safe,ok case 5: check = MarkManager.EffectType.Cool; exstate = ExState.pressok; break; case 4: check = MarkManager.EffectType.Fine; exstate = ExState.pressok; break; case 3: check = MarkManager.EffectType.Safe; state = State.safe; exstate = ExState.released; ret = true; break; case 2: check = MarkManager.EffectType.Sad; state = State.sad; exstate = ExState.released; ret = true; break; case 1: check = MarkManager.EffectType.Worst; state = State.worst; exstate = ExState.released; ret = true; break; case 0: break; } if (a != 0) { hidden = false; pos1 = new Vector2[40]; pos2 = new Vector2[40]; iVerticesCount = 0; } if (AC && (check == MarkManager.EffectType.Cool || check == MarkManager.EffectType.Fine)) { state = State.cool; effectcallback.Invoke(MarkManager.EffectType.Cool, Position); hidden = true; } } } else if (exstate == ExState.pressok) { if (AC) { if (released[(int)ButtonType]) { check = MarkManager.EffectType.PressReleased; ret = true; } else { check = MarkManager.EffectType.Pressing; } } else { if (released[(int)ButtonType]) { released[(int)ButtonType] = false; int a = evaluate(this.endtime, ctime - adjustgaptime); switch (a) { // final evaluate case 5: check = MarkManager.EffectType.Cool; state = State.cool; effectcallback.Invoke(MarkManager.EffectType.Cool, Position); exstate = ExState.released; ret = true; break; case 4: check = MarkManager.EffectType.Fine; state = State.fine; effectcallback.Invoke(MarkManager.EffectType.Fine, Position); exstate = ExState.released; ret = true; break; case 3: check = MarkManager.EffectType.Safe; state = State.safe; effectcallback.Invoke(MarkManager.EffectType.Safe, Position); exstate = ExState.released; ret = true; break; case 2: check = MarkManager.EffectType.Sad; state = State.sad; effectcallback.Invoke(MarkManager.EffectType.Sad, Position); exstate = ExState.released; ret = true; break; case 1: check = MarkManager.EffectType.Worst; state = State.worst; exstate = ExState.released; ret = true; break; case 0: check = MarkManager.EffectType.Worst; state = State.worst; exstate = ExState.released; ret = true; break; } if (state >= State.cool && state <= State.sad) { //離したとき用の音 soundtype = (int)ButtonType; } } } } if (exstate == ExState.waitingpress) { if (ctime - this.time >= eval[3]) { check = MarkManager.EffectType.Worst; ret = true; } } else if (exstate == ExState.pressok) { if (!AC) { if (ctime - this.endtime >= eval[3]) { check = MarkManager.EffectType.Worst; ret = true; } } } } else { //when auto if (exstate == ExState.waitingpress) { if (ctime - this.time >= -autowidth) { check = MarkManager.EffectType.Cool; exstate = ExState.pressok; soundtype = (int)ButtonType; if (AC) { state = State.cool; effectcallback.Invoke(MarkManager.EffectType.Cool, Position); hidden = true; } else { hidden = false; } pos1 = new Vector2[40]; pos2 = new Vector2[40]; iVerticesCount = 0; } } else if (exstate == ExState.pressok) { if (AC) { check = MarkManager.EffectType.Pressing; } else { if (ctime - this.endtime >= -autowidth) { check = MarkManager.EffectType.Cool; exstate = ExState.released; soundtype = (int)ButtonType + 10; state = State.cool; effectcallback.Invoke(MarkManager.EffectType.Cool, Position); hidden = false; ret = true; } } } } if (state < State.cool) { float scale = (float)bp / defaultbpm; if (hidden) { if (this.time - ctime <= 2 / scale) { if (dState == DisplayState.Normal || dState == DisplayState.Hidden) { effectcallback.Invoke(MarkManager.EffectType.Appear, Position); hidden = false; } } if (this.time - ctime <= 0.5f / scale) { if (dState == DisplayState.Sudden) { effectcallback.Invoke(MarkManager.EffectType.Appear, Position); hidden = false; } } if (this.time - ctime <= 0.25f / scale) { if (dState == DisplayState.Hidden && exstate == ExState.waitingpress) { effectcallback.Invoke(MarkManager.EffectType.Appear, Position); hidden = true; } } if (this.endtime - ctime <= 0.25f / scale) { if (dState == DisplayState.Hidden) { effectcallback.Invoke(MarkManager.EffectType.Appear, Position); hidden = true; } } } if (state == State.appearing && !hidden) { float sx = mark.Scale.X + 0.05f; mark.Scale = new Vector2(sx, sx); outcircle.Scale = new Vector2(sx, sx); outjiku.Scale = new Vector2(sx, sx); hold.Scale = new Vector2(sx, sx); if (mark.Scale.X > 1.2f) { mark.Scale = new Vector2(1, 1); outcircle.Scale = new Vector2(1, 1); outjiku.Scale = new Vector2(1, 1); hold.Scale = new Vector2(1, 1); state = State.moving; } } CaliculateColorPosition(ctime, bp); jiku.Rotation = -1 * (float)Math.PI * (this.time - ctime) * scale; if (jiku.Rotation >= 0) { jiku.Rotation = 0; } outjiku.Rotation = -2 * (float)Math.PI * (this.time - ctime) / length; } mark.Update(); markc.Update(); jiku.Update(); outcircle.Update(); outjiku.Update(); hold.Update(); return(ret); }
public C(InState inState, ExState exState) { TheInState = inState; TheExState = exState; }
/// <summary> /// Change the current execution state /// POSTed json object: /// {"command": cmd} /// where cmd is a string and one of /// "run", "pause", "cancel" or "stop". /// </summary> public ExecutionStateModule() { log = LogManager.GetLogger(typeof(ExecutionStateModule)); History history = null; Post["/executionstate/{executionid}"] = parameters => { ExState newState; string command; using (var reader = new StreamReader(Request.Body)) { var json = reader.ReadToEnd(); JObject obj; try { obj = JObject.Parse(json); } catch { var response = new Response(); response.StatusCode = HttpStatusCode.BadRequest; response.ReasonPhrase = "Invalid JSON"; return(response); } command = ((string)obj.SelectToken("$.state")).ToLower(); switch (command) { case "run": history = new WorkflowExecutionResumedEvent { }; newState = ExState.Running; break; case "pause": history = new WorkflowExecutionPausedEvent { }; newState = ExState.Paused; break; case "cancel": history = new WorkflowExecutionCancelledEvent { }; newState = ExState.Running; break; case "stop": history = new WorkflowStoppedEvent { }; newState = ExState.Stopped; break; default: return(new Response().WithStatusCode(HttpStatusCode.BadRequest)); } } Guid executionId; if (!Guid.TryParse(parameters.executionid, out executionId)) { return(new Response().WithStatusCode(HttpStatusCode.BadRequest)); } using (var db = new Database()) { var execution = db.Executions.SingleOrDefault(e => e.ExecutionId == executionId); var executionState = db.ExecutionStates.SingleOrDefault(st => st.ExecutionId == executionId); if (execution == null || executionState == null) { return new Response { StatusCode = HttpStatusCode.NotFound } } ; var state = ExState.Create(executionState.State); // Do not change terminal states and ignore if newState is the current state if (state == ExState.Stopped || // Cannot change STOPPED state (state == ExState.Cleanup && newState != ExState.Stopped) || // Can only go to STOPPED from CLEANUP (state == newState && command != "cancel")) // No state change and not cancelling { return(((Response)state.Json).WithContentType("application/json")); } Database.InsertHistory(execution, history); if (state == newState) { return(((Response)newState.Json).WithContentType("application/json")); } // Now update the execution state and retry upon failure executionState.State = newState; int i; for (i = 0; i < DB_RETRIES; i++) { try { db.SubmitChanges(); } catch (ChangeConflictException) { // Surely there can be, at most, only one conflict on the executionState foreach (var conflict in db.ChangeConflicts.Where(c => c.Object == executionState)) { // Conflict must be the state value var mc = conflict.MemberConflicts.Single(); // Should never happen if (mc.Member.Name != "State") { log.Error($"ExecutionState update conflict member name is {mc.Member.Name}"); throw new ApplicationException($"ExecutionState update conflict member name is {mc.Member.Name}"); } var dbState = ExState.Create((string)mc.DatabaseValue); // The desired state was set elsewhere, so leave it if (dbState == newState) { break; } if (dbState == ExState.Stopped) { // Do not overwrite STOPPED state // (but do overwrite newState with the value from the database so that the correct // current state is reported back to the client) newState = dbState; break; } // Presumably the state went from PAUSED to RUNNING or vice versa, try again conflict.Resolve(RefreshMode.KeepCurrentValues); } } } if (i == DB_RETRIES) { log.Info($"Too many retries to set state of execution {executionId} to {newState}"); // return the current (and original) state var originalState = ExState.Create(db.ExecutionStates.GetOriginalEntityState(executionState).State); return(((Response)originalState.Json).WithContentType("application/json")); } return(((Response)newState.Json).WithContentType("application/json")); } }; } }
/// <summary> /// Process task completion by scheduling the next task or completing the workflow /// </summary> /// <param name="db"></param> /// <param name="workflow"></param> /// <param name="execution"></param> /// <param name="history"></param> /// <param name="decisions"></param> private static void ProcessActivityTaskCompletedEvent(Database db, WorkflowObj workflow, Execution execution, History history, List <History> decisions) { // There should(!) be no contention for the data modified in this process var evt = ActivityTaskCompletedEvent.Create(history); var se = ActivityTaskScheduledEvent.Create(db.GetHistoryEvent(execution.ExecutionId, evt.SchedulingEventId)); var completedTask = workflow.Tasks.Single(t => t.TaskId == se.TaskId); // Default task outflow var outflow = "Out"; // Update variables if (evt.Result != null) { // Update the variables if there are any normal results (not prefixed with "$") if (evt.Result.Properties().Any(p => !p.Name.StartsWith("$"))) { var variables = db.Variables.Where(v => v.Execution == execution).ToArray(); foreach (var o in completedTask.Outputs.Where(o => o.Value.Var != null)) { // If the activity has not returned a value for an output then we don't update the mapped variable // In general it is probably best if activities return values for all outputs to avoid confusion JToken value; if (evt.Result.TryGetValue(o.Key, out value)) { variables.Single(v => v.Name == o.Value.Var).Json = value.ToString(Formatting.None); } } } // Get the correct outflow JToken outflowToken; if (evt.Result.TryGetValue("$outflow", out outflowToken)) { if (outflowToken.Type == JTokenType.String) { outflow = (string)outflowToken; } else { throw new ApplicationException("Task outflow identifier must be a string"); } } } var nextTaskId = completedTask.Outflows.Single(o => o.Name == outflow).Target; var nextTask = workflow.Tasks.Single(t => t.TaskId == nextTaskId); // A task with no outflows is an end if (nextTask.Outflows.Length == 0) { Console.WriteLine($"Execution state = {execution.ExecutionState.State}"); if (ExState.Create(execution.ExecutionState.State) != ExState.Cleanup) { CreateWorkflowCompletedEvent(execution, decisions); } AttemptCleanup(db, execution, workflow, decisions); } else { CreateTaskScheduledEvent(db, execution, nextTask, decisions); } }