#71: Started adding sub-result control

This commit is contained in:
frikky
2020-06-20 11:08:06 +02:00
parent 4a6595e56a
commit 8f40fa01e9
6 changed files with 114 additions and 48 deletions
+2 -2
View File
@@ -328,7 +328,7 @@ class AppBase:
print("BEFORE VARIABLES!") print("BEFORE VARIABLES!")
if len(baseresult) == 0: if len(baseresult) == 0:
try: try:
print("WF Variables: %s" % execution_data["workflow"]["workflow_variables"]) #print("WF Variables: %s" % execution_data["workflow"]["workflow_variables"])
for variable in execution_data["workflow"]["workflow_variables"]: for variable in execution_data["workflow"]["workflow_variables"]:
variablename = variable["name"].replace(" ", "_", -1).lower() variablename = variable["name"].replace(" ", "_", -1).lower()
@@ -345,7 +345,7 @@ class AppBase:
print("BEFORE EXECUTION VAR") print("BEFORE EXECUTION VAR")
if len(baseresult) == 0: if len(baseresult) == 0:
try: try:
print("Execution Variables: %s" % execution_data["execution_variables"]) #print("Execution Variables: %s" % execution_data["execution_variables"])
for variable in execution_data["execution_variables"]: for variable in execution_data["execution_variables"]:
variablename = variable["name"].replace(" ", "_", -1).lower() variablename = variable["name"].replace(" ", "_", -1).lower()
if variablename.lower() == actionname_lower: if variablename.lower() == actionname_lower:
+104 -40
View File
@@ -250,21 +250,24 @@ type Schedule struct {
} }
type Workflow struct { type Workflow struct {
Actions []Action `json:"actions" datastore:"actions,noindex"` Actions []Action `json:"actions" datastore:"actions,noindex"`
Branches []Branch `json:"branches" datastore:"branches,noindex"` Branches []Branch `json:"branches" datastore:"branches,noindex"`
Triggers []Trigger `json:"triggers" datastore:"triggers,noindex"` Triggers []Trigger `json:"triggers" datastore:"triggers,noindex"`
Schedules []Schedule `json:"schedules" datastore:"schedules,noindex"` Schedules []Schedule `json:"schedules" datastore:"schedules,noindex"`
Errors []string `json:"errors,omitempty" datastore:"errors"` Configuration struct {
Tags []string `json:"tags,omitempty" datastore:"tags"` ExitOnError bool `json:"exit_on_error" datastore:"exit_on_error"`
ID string `json:"id" datastore:"id"` } `json:"configuration,omitempty" datastore:"configuration"`
IsValid bool `json:"is_valid" datastore:"is_valid"` Errors []string `json:"errors,omitempty" datastore:"errors"`
Name string `json:"name" datastore:"name"` Tags []string `json:"tags,omitempty" datastore:"tags"`
Description string `json:"description" datastore:"description"` ID string `json:"id" datastore:"id"`
Start string `json:"start" datastore:"start"` IsValid bool `json:"is_valid" datastore:"is_valid"`
Owner string `json:"owner" datastore:"owner"` Name string `json:"name" datastore:"name"`
Sharing string `json:"sharing" datastore:"sharing"` Description string `json:"description" datastore:"description"`
Org []Org `json:"org,omitempty" datastore:"org"` Start string `json:"start" datastore:"start"`
ExecutingOrg Org `json:"execution_org,omitempty" datastore:"execution_org"` Owner string `json:"owner" datastore:"owner"`
Sharing string `json:"sharing" datastore:"sharing"`
Org []Org `json:"org,omitempty" datastore:"org"`
ExecutingOrg Org `json:"execution_org,omitempty" datastore:"execution_org"`
WorkflowVariables []struct { WorkflowVariables []struct {
Description string `json:"description" datastore:"description"` Description string `json:"description" datastore:"description"`
ID string `json:"id" datastore:"id"` ID string `json:"id" datastore:"id"`
@@ -276,7 +279,7 @@ type Workflow struct {
ID string `json:"id" datastore:"id"` ID string `json:"id" datastore:"id"`
Name string `json:"name" datastore:"name"` Name string `json:"name" datastore:"name"`
Value string `json:"value" datastore:"value"` Value string `json:"value" datastore:"value"`
} `json:"execution_variables,omitempty" datastore:"execution_variables,omitempty"` } `json:"execution_variables,omitempty" datastore:"execution_variables"`
} }
type ActionResult struct { type ActionResult struct {
@@ -675,6 +678,24 @@ func handleGetStreamResults(resp http.ResponseWriter, request *http.Request) {
} }
// Finds the child nodes of a node in execution and returns them
// Used if e.g. a node in a branch is exited, and all children have to be stopped
func findChildNodes(workflowExecution WorkflowExecution, nodeId string) []string {
log.Printf("\nNODE TO FIX: %s\n\n", nodeId)
allChildren := []string{nodeId}
// 1. Find children of this specific node
// 2. Find the children of those nodes etc.
for _, branch := range workflowExecution.Workflow.Branches {
if branch.SourceID == nodeId {
log.Printf("Children: %s", branch.DestinationID)
allChildren = append(allChildren, branch.DestinationID)
}
}
return allChildren
}
func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) { func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
cors := handleCors(resp, request) cors := handleCors(resp, request)
if cors { if cors {
@@ -732,20 +753,65 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
// FIXME - remove comment // FIXME - remove comment
if workflowExecution.Status == "ABORTED" || workflowExecution.Status == "FAILURE" { if workflowExecution.Status == "ABORTED" || workflowExecution.Status == "FAILURE" {
log.Printf("Workflowexecution is already aborted. No further action can be taken") if workflowExecution.Workflow.Configuration.ExitOnError {
resp.WriteHeader(401) log.Printf("Workflowexecution already has status %s. No further action can be taken", workflowExecution.Status)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Workflowexecution is aborted because of %s with result %s and status %s"}`, workflowExecution.LastNode, workflowExecution.Result, workflowExecution.Status))) resp.WriteHeader(401)
return resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Workflowexecution is aborted because of %s with result %s and status %s"}`, workflowExecution.LastNode, workflowExecution.Result, workflowExecution.Status)))
return
} else {
log.Printf("Continuing even though it's aborted.")
}
} }
if actionResult.Status == "ABORTED" || actionResult.Status == "FAILURE" { if actionResult.Status == "ABORTED" || actionResult.Status == "FAILURE" {
log.Printf("Actionresult is %s. Should set workflowExecution and exit all running functions", actionResult.Status) log.Printf("Actionresult is %s. Should set workflowExecution and exit all running functions", actionResult.Status)
workflowExecution.Status = actionResult.Status
workflowExecution.LastNode = actionResult.Action.ID newResults := []ActionResult{}
childNodes := []string{}
if workflowExecution.Workflow.Configuration.ExitOnError {
workflowExecution.Status = actionResult.Status
workflowExecution.LastNode = actionResult.Action.ID
// Find underlying nodes and add them
} else {
// Finds childnodes to set them to SKIPPED
childNodes = findChildNodes(*workflowExecution, actionResult.Action.ID)
for _, nodeId := range childNodes {
if nodeId == actionResult.Action.ID {
continue
}
// 1. Find the action itself
// 2. Create an actionresult
curAction := Action{ID: ""}
for _, action := range workflowExecution.Workflow.Actions {
if action.ID == nodeId {
curAction = action
break
}
}
if len(curAction.ID) == 0 {
log.Printf("Couldn't find subnode %s", nodeId)
continue
}
newResult := ActionResult{
Action: curAction,
ExecutionId: actionResult.ExecutionId,
Authorization: actionResult.Authorization,
Result: "Skipped because of previous node",
StartedAt: 0,
CompletedAt: 0,
Status: "SKIPPED",
}
newResults = append(newResults, newResult)
increaseStatisticsField(ctx, "workflow_execution_actions_skipped", workflowExecution.Workflow.ID, 1)
}
}
// Cleans up aborted, and always gives a result // Cleans up aborted, and always gives a result
lastResult := "" lastResult := ""
newResults := []ActionResult{}
// type ActionResult struct { // type ActionResult struct {
for _, result := range workflowExecution.Results { for _, result := range workflowExecution.Results {
if result.Status == "EXECUTING" { if result.Status == "EXECUTING" {
@@ -776,21 +842,6 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
} }
} }
// This means it should continue I think :)
if actionResult.Status == "SKIPPED" {
// How the fuck do I do this tho
// Parse _all_ children of the skipped and add them to "finished"
//
log.Printf("Find out how to handle skipped items, as there might be more branches to continue anyway")
// FIXME - simulate that every subnode is skipped
// Check worker, as it contains this code
// Children of children of children...
// Recurse, woo
//for _, item := range children {
//}
}
// FIXME rebuild to be like this or something // FIXME rebuild to be like this or something
// workflowExecution/ExecutionId/Nodes/NodeId // workflowExecution/ExecutionId/Nodes/NodeId
// Find the appropriate action // Find the appropriate action
@@ -840,19 +891,31 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
} }
} }
log.Printf("LENGTH: %d - %d", len(workflowExecution.Results), len(workflowExecution.Workflow.Actions))
//log.Printf("Checking results %d vs %d", len(workflowExecution.Results), len(workflowExecution.Workflow.Actions)+extraInputs) //log.Printf("Checking results %d vs %d", len(workflowExecution.Results), len(workflowExecution.Workflow.Actions)+extraInputs)
if len(workflowExecution.Results) == len(workflowExecution.Workflow.Actions)+extraInputs { if len(workflowExecution.Results) == len(workflowExecution.Workflow.Actions)+extraInputs {
finished := true finished := true
lastResult := "" lastResult := ""
// Doesn't have to be SUCCESS and FINISHED everywhere anymore.
skippedNodes := false
for _, result := range workflowExecution.Results { for _, result := range workflowExecution.Results {
if result.Status != "SUCCESS" && result.Status != "FINISHED" { if result.Status == "EXECUTING" {
finished = false finished = false
break break
} }
if result.Status == "SKIPPED" {
skippedNodes = true
}
lastResult = result.Result lastResult = result.Result
} }
// FIXME: Handle skip nodes - change status?
_ = skippedNodes
if finished { if finished {
log.Printf("Execution of %s finished.", workflowExecution.ExecutionId) log.Printf("Execution of %s finished.", workflowExecution.ExecutionId)
//log.Println("Might be finished based on length of results and everything being SUCCESS or FINISHED - VERIFY THIS. Setting status to finished.") //log.Println("Might be finished based on length of results and everything being SUCCESS or FINISHED - VERIFY THIS. Setting status to finished.")
@@ -1070,6 +1133,7 @@ func setNewWorkflow(resp http.ResponseWriter, request *http.Request) {
workflow.Actions = newActions workflow.Actions = newActions
workflow.IsValid = true workflow.IsValid = true
workflow.Configuration.ExitOnError = true
workflowjson, err := json.Marshal(workflow) workflowjson, err := json.Marshal(workflow)
if err != nil { if err != nil {
@@ -1431,7 +1495,7 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) {
"0ca8887e-b4af-4e3e-887c-87e9d3bc3d3e", "0ca8887e-b4af-4e3e-887c-87e9d3bc3d3e",
} }
log.Printf("%s Action execution var: %s", action.Label, action.ExecutionVariable.Name) //log.Printf("%s Action execution var: %s", action.Label, action.ExecutionVariable.Name)
builtin := false builtin := false
for _, id := range reservedApps { for _, id := range reservedApps {
+2 -2
View File
@@ -1,7 +1,7 @@
version: '3' version: '3'
services: services:
frontend: frontend:
#build: ./frontend build: ./frontend
image: frikky/shuffle:frontend image: frikky/shuffle:frontend
container_name: shuffle-frontend container_name: shuffle-frontend
hostname: shuffle-frontend hostname: shuffle-frontend
@@ -14,7 +14,7 @@ services:
depends_on: depends_on:
- backend - backend
backend: backend:
#build: ./backend build: ./backend
image: frikky/shuffle:backend image: frikky/shuffle:backend
container_name: shuffle-backend container_name: shuffle-backend
hostname: ${BACKEND_HOSTNAME} hostname: ${BACKEND_HOSTNAME}
+1 -1
View File
@@ -1455,7 +1455,7 @@ const AngularWorkflow = (props) => {
return ( return (
<div style={appViewStyle}> <div style={appViewStyle}>
<div style={variableScrollStyle}> <div style={variableScrollStyle}>
What are <a href="https://shuffler.io/docs/workflows#variables" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>WORKFLOW variables?</a> What are <a href="https://shuffler.io/docs/workflows#workflow_variables" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>WORKFLOW variables?</a>
{workflow.workflow_variables === null ? {workflow.workflow_variables === null ?
null : workflow.workflow_variables.map(variable=> { null : workflow.workflow_variables.map(variable=> {
return ( return (
+3 -1
View File
@@ -39,8 +39,10 @@ import { positions, Provider } from "react-alert";
// Production - backend proxy forwarding in nginx // Production - backend proxy forwarding in nginx
var globalUrl = window.location.origin var globalUrl = window.location.origin
// CORS used for testing purposes. Should only happen with specific port and http
if (window.location.protocol == "http:" && window.location.port === "3000") { if (window.location.protocol == "http:" && window.location.port === "3000") {
globalUrl = "http://192.168.3.6:5001" globalUrl = "http://localhost:5001"
} }
const surfaceColor = "#27292D" const surfaceColor = "#27292D"
+2 -2
View File
@@ -189,10 +189,10 @@ const Docs = (props) => {
} }
function Heading(props) { function Heading(props) {
const element = React.createElement(`h${props.level}`, {style: {marginTop: 25}}, props.children) const element = React.createElement(`h${props.level}`, {style: {marginTop: 40}}, props.children)
return ( return (
<span> <span>
{props.level !== 1 ? <Divider style={{width: "90%", marginTop: 25, backgroundColor: inputColor}} /> : null} {props.level !== 1 ? <Divider style={{width: "90%", marginTop: 40, backgroundColor: inputColor}} /> : null}
{element} {element}
</span> </span>
) )