From 04e8a22a717f4d70ca0966486038e4165463df0d Mon Sep 17 00:00:00 2001 From: frikky Date: Sun, 21 Feb 2021 17:00:23 +0100 Subject: [PATCH] #247: Fixed Worker return and app SDK bug --- backend/app_sdk/app_base.py | 13 +++-- backend/app_sdk/build.sh | 2 +- backend/go-app/walkoff.go | 5 ++ frontend/src/views/Admin.jsx | 1 + frontend/src/views/AngularWorkflow.jsx | 78 +++++++++++++++++--------- functions/onprem/worker/worker.go | 26 ++++++--- 6 files changed, 83 insertions(+), 42 deletions(-) diff --git a/backend/app_sdk/app_base.py b/backend/app_sdk/app_base.py index 8c43637d..56a320c6 100644 --- a/backend/app_sdk/app_base.py +++ b/backend/app_sdk/app_base.py @@ -541,8 +541,9 @@ class AppBase: "status": "EXECUTING" } + # Simple validation of parameters in general try: - print(action["parameters"]) + tmp_parameters = action["parameters"] except KeyError: action["parameters"] = [] except TypeError: @@ -1514,11 +1515,13 @@ class AppBase: if len(json_replacement) > minlength: minlength = len(json_replacement) + + print("PRE new_replacement") # FIXME: Only do this IF they want to loop new_replacement = [] for i in range(len(json_replacement)): - if isinstance(json_replacement[i], dict) or isinstance(json_replacement[i], dict): + if isinstance(json_replacement[i], dict) or isinstance(json_replacement[i], list): tmp_replacer = json.dumps(json_replacement[i]) newvalue = tmpitem.replace(actualitem[0][0], tmp_replacer, 1) else: @@ -1727,7 +1730,7 @@ class AppBase: #print("[INFO] APP_SDK DONE: Starting NORMAL execution of function") print("[INFO] Running normal execution\n") newres = await func(**params) - print("\n[INFO] Returned from execution:", newres) + print("\n[INFO] Returned from execution with datalength!")#, newres) if isinstance(newres, tuple): print("[INFO] Handling return as tuple") # Handles files. @@ -1753,7 +1756,7 @@ class AppBase: result = json.dumps(tmp_result) elif isinstance(newres, str): - print("[INFO] Handling return as string") + print("[INFO] Handling return as string of length %d" % len(newres)) result += newres else: try: @@ -1762,7 +1765,7 @@ class AppBase: result += "Failed autocasting. Can't handle %s type from function. Must be string" % type(newres) print("Can't handle type %s value from function" % (type(newres))) - print("[INFO] POST NEWRES RESULT: ", result) + print("[INFO] POST NEWRES RESULT!")#, result) else: #print("[INFO] APP_SDK DONE: Starting MULTI execution (length: %d) with values %s" % (minlength, multi_parameters)) # 1. Use number of executions based on the arrays being similar diff --git a/backend/app_sdk/build.sh b/backend/app_sdk/build.sh index 96204598..76c9cee3 100644 --- a/backend/app_sdk/build.sh +++ b/backend/app_sdk/build.sh @@ -1,6 +1,6 @@ #!/bin/bash NAME=shuffle-app_sdk -VERSION=0.8.56 +VERSION=0.8.57 docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force docker build . -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index 7fab3fc6..f49cba9c 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -6163,6 +6163,11 @@ func loadSpecificApps(resp http.ResponseWriter, request *http.Request) { return } + cacheKey := fmt.Sprintf("workflowapps-sorted-100") + requestCache.Delete(cacheKey) + cacheKey = fmt.Sprintf("workflowapps-sorted-500") + requestCache.Delete(cacheKey) + resp.WriteHeader(200) resp.Write([]byte(fmt.Sprintf(`{"success": true}`))) } diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index 735814cf..62f926a4 100644 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -1122,6 +1122,7 @@ const Admin = (props) => { Edit authentication for {selectedAuthentication.app.name} ({selectedAuthentication.label}) {selectedAuthentication.fields.map((data, index) => { + console.log("DATA: ", data, selectedAuthentication) return (
{data.key} diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 2fec90dd..eb88c253 100644 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -1966,7 +1966,7 @@ const AngularWorkflow = (props) => { return (
- What are WORKFLOW variables? + What are WORKFLOW variables? {workflow.workflow_variables === null ? null : workflow.workflow_variables.map(variable=> { return ( @@ -2033,7 +2033,7 @@ const AngularWorkflow = (props) => { }}>New workflow variable
- What are EXECUTION variables? + What are EXECUTION variables? {workflow.execution_variables === null || workflow.execution_variables === undefined ? null : workflow.execution_variables.map(variable=> { return ( @@ -2254,9 +2254,9 @@ const AngularWorkflow = (props) => {
{triggers.map((trigger, index) => { var imageline = trigger.large_image.length === 0 ? - + : - + const color = trigger.is_valid ? "green" : "orange" return( @@ -3935,7 +3935,7 @@ const AngularWorkflow = (props) => { - What are actions? + What are actions? {selectedAction.errors !== null && selectedAction.errors.length > 0 ?
Errors: {selectedAction.errors.join("\n")} @@ -3969,11 +3969,13 @@ const AngularWorkflow = (props) => {
Authenticate {selectedApp.name}: + +
: null} @@ -4559,7 +4561,7 @@ const AngularWorkflow = (props) => { }} > - Conditions can't be used for loops [ .# ] Learn more + Conditions can't be used for loops [ .# ] Learn more Condition @@ -4568,6 +4570,7 @@ const AngularWorkflow = (props) => {
+ +
@@ -4811,7 +4815,7 @@ const AngularWorkflow = (props) => {

Branch: Conditions - {selectedEdgeIndex}

- What are conditions? + What are conditions?
@@ -5035,7 +5039,7 @@ const AngularWorkflow = (props) => {

{selectedTrigger.app_name}: {selectedTrigger.status}

- What are email triggers? + What are email triggers?
@@ -5126,7 +5130,7 @@ const AngularWorkflow = (props) => {

{selectedTrigger.app_name}

- What are subflows? + What are subflows?
@@ -5202,7 +5206,7 @@ const AngularWorkflow = (props) => { })} } - {workflow.triggers[selectedTriggerIndex].parameters[0].value.length === 0 ? null : Explore selected workflow} + {workflow.triggers[selectedTriggerIndex].parameters[0].value.length === 0 ? null : Explore selected workflow}
@@ -5329,7 +5333,7 @@ const AngularWorkflow = (props) => {

{selectedTrigger.app_name}: {selectedTrigger.status}

- What are webhooks? + What are webhooks?
@@ -5704,7 +5708,7 @@ const AngularWorkflow = (props) => {

{selectedTrigger.app_name}: {selectedTrigger.status}

- What is the user input trigger? + What is the user input trigger?
@@ -5882,7 +5886,7 @@ const AngularWorkflow = (props) => {

{selectedTrigger.app_name}: {selectedTrigger.status}

- What are schedules? + What are schedules?
@@ -6139,12 +6143,14 @@ const AngularWorkflow = (props) => {
+ +
) @@ -6195,12 +6201,14 @@ const AngularWorkflow = (props) => {
+ +
) @@ -6212,19 +6220,23 @@ const AngularWorkflow = (props) => { const boxSize = 100 const executionButton = executionRunning ? + + : - + + + return( @@ -6247,29 +6259,37 @@ const AngularWorkflow = (props) => { /> - + + + - + + + + + + + {/* */} @@ -6608,6 +6628,7 @@ const AngularWorkflow = (props) => {

Executing Workflow

+ +
{executionData.status !== undefined && executionData.status.length > 0 ? @@ -6627,7 +6649,7 @@ const AngularWorkflow = (props) => { {executionData.execution_source !== undefined && executionData.execution_source !== null && executionData.execution_source.length > 0 && executionData.execution_source !== "default" ?
Source:   {executionData.execution_parent !== null && executionData.execution_parent !== undefined && executionData.execution_parent.length > 0 ? - Parent Workflow + Parent Workflow : executionData.execution_source } @@ -6744,7 +6766,7 @@ const AngularWorkflow = (props) => { {data.action.app_name === "shuffle-subflow" ? {validate.valid && data.action.parameters !== undefined && data.action.parameters !== null ? - See subflow execution + See subflow execution : "TBD: Load subexecution result for" } @@ -6989,7 +7011,7 @@ const AngularWorkflow = (props) => { Execution Variable - Execution Variables are TEMPORARY variables that you can ony be set and used during execution. Learn more here + Execution Variables are TEMPORARY variables that you can ony be set and used during execution. Learn more here setNewVariableName(event.target.value)} color="primary" @@ -7264,7 +7286,7 @@ const AngularWorkflow = (props) => { return (
- What is this?
+ What is this?
These are required fields for authenticating with {selectedApp.name}
Name - what is this used for? diff --git a/functions/onprem/worker/worker.go b/functions/onprem/worker/worker.go index e09ca874..2773c459 100644 --- a/functions/onprem/worker/worker.go +++ b/functions/onprem/worker/worker.go @@ -1235,7 +1235,7 @@ func handleExecutionResult(workflowExecution WorkflowExecution) { // IF NOT VISITED && IN toExecuteOnPrem // SKIP if it's not onprem toRemove := []int{} - log.Printf("\n\nNEXTACTIONS: %#v\n\n", nextActions) + //log.Printf("\n\nNEXTACTIONS: %#v\n\n", nextActions) for index, nextAction := range nextActions { action := getAction(workflowExecution, nextAction, environment) // check visited and onprem @@ -1698,9 +1698,11 @@ func executionInit(workflowExecution WorkflowExecution) error { } } - log.Printf("\n\n\n[INFO] CHILDREN FOUND: %#v", children) - log.Printf("[INFO] PARENTS FOUND: %#v", parents) - log.Printf("[INFO] NEXT ACTIONS: %#v\n\n", nextActions) + /* + log.Printf("\n\n\n[INFO] CHILDREN FOUND: %#v", children) + log.Printf("[INFO] PARENTS FOUND: %#v", parents) + log.Printf("[INFO] NEXT ACTIONS: %#v\n\n", nextActions) + */ log.Printf("[INFO] Actions: %d + Special Triggers: %d", len(workflowExecution.Workflow.Actions), extra) onpremApps := []string{} @@ -2064,7 +2066,10 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) { // return //} + resp.WriteHeader(200) + resp.Write([]byte(fmt.Sprintf(`{"success": true}`))) runWorkflowExecutionTransaction(ctx, 0, workflowExecution.ExecutionId, actionResult, resp) + } func findChildNodes(workflowExecution WorkflowExecution, nodeId string) []string { @@ -2473,15 +2478,20 @@ func runWorkflowExecutionTransaction(ctx context.Context, attempts int64, workfl return } } else { - log.Printf("Skipping setexec with status %s", workflowExecution.Status) + log.Printf("[INFO] Skipping setexec with status %s", workflowExecution.Status) + + // Just in case. Should MAYBE validate finishing another time as well. + // This fixes issues with e.g. Action -> Trigger -> Action. + handleExecutionResult(*workflowExecution) + //validateFinished(workflowExecution) } //if newExecutions && len(nextActions) > 0 { // handleExecutionResult(*workflowExecution) //} - resp.WriteHeader(200) - resp.Write([]byte(fmt.Sprintf(`{"success": true}`))) + //resp.WriteHeader(200) + //resp.Write([]byte(fmt.Sprintf(`{"success": true}`))) } func getWorkflowExecution(ctx context.Context, id string) (*WorkflowExecution, error) { @@ -2532,7 +2542,7 @@ func validateFinished(workflowExecution WorkflowExecution) { } body, err := ioutil.ReadAll(newresp.Body) - log.Printf("BACKEND STATUS: %d", newresp.StatusCode) + log.Printf("[INFO] BACKEND STATUS: %d", newresp.StatusCode) if err != nil { log.Printf("[ERROR] Failed reading body: %s", err) } else {