Fixed execution speed with too many executions
This commit is contained in:
+56
-10
@@ -327,13 +327,36 @@ class AppBase:
|
|||||||
|
|
||||||
print("BEFORE VARIABLES!")
|
print("BEFORE VARIABLES!")
|
||||||
if len(baseresult) == 0:
|
if len(baseresult) == 0:
|
||||||
print("Variables: %s" % execution_data["workflow"]["workflow_variables"])
|
try:
|
||||||
for variable in execution_data["workflow"]["workflow_variables"]:
|
print("WF Variables: %s" % execution_data["workflow"]["workflow_variables"])
|
||||||
variablename = variable["name"].replace(" ", "_", -1).lower()
|
for variable in execution_data["workflow"]["workflow_variables"]:
|
||||||
|
variablename = variable["name"].replace(" ", "_", -1).lower()
|
||||||
|
|
||||||
if variablename.lower() == actionname_lower:
|
if variablename.lower() == actionname_lower:
|
||||||
baseresult = variable["value"]
|
baseresult = variable["value"]
|
||||||
break
|
break
|
||||||
|
except KeyError as e:
|
||||||
|
print("KeyError wf variables: %s" % e)
|
||||||
|
pass
|
||||||
|
except TypeError as e:
|
||||||
|
print("TypeError wf variables: %s" % e)
|
||||||
|
pass
|
||||||
|
|
||||||
|
print("BEFORE EXECUTION VAR")
|
||||||
|
if len(baseresult) == 0:
|
||||||
|
try:
|
||||||
|
print("Execution Variables: %s" % execution_data["execution_variables"])
|
||||||
|
for variable in execution_data["execution_variables"]:
|
||||||
|
variablename = variable["name"].replace(" ", "_", -1).lower()
|
||||||
|
if variablename.lower() == actionname_lower:
|
||||||
|
baseresult = variable["value"]
|
||||||
|
break
|
||||||
|
except KeyError as e:
|
||||||
|
print("KeyError exec variables: %s" % e)
|
||||||
|
pass
|
||||||
|
except TypeError as e:
|
||||||
|
print("TypeError exec variables: %s" % e)
|
||||||
|
pass
|
||||||
|
|
||||||
except KeyError as error:
|
except KeyError as error:
|
||||||
print(f"KeyError in JSON: {error}")
|
print(f"KeyError in JSON: {error}")
|
||||||
@@ -421,10 +444,33 @@ class AppBase:
|
|||||||
|
|
||||||
|
|
||||||
if parameter["variant"] == "WORKFLOW_VARIABLE":
|
if parameter["variant"] == "WORKFLOW_VARIABLE":
|
||||||
for item in fullexecution["workflow"]["workflow_variables"]:
|
print("Handling workflow variable")
|
||||||
if parameter["action_field"] == item["name"]:
|
found = False
|
||||||
parameter["value"] = item["value"]
|
try:
|
||||||
break
|
for item in fullexecution["workflow"]["workflow_variables"]:
|
||||||
|
if parameter["action_field"] == item["name"]:
|
||||||
|
found = True
|
||||||
|
parameter["value"] = item["value"]
|
||||||
|
break
|
||||||
|
except KeyError as e:
|
||||||
|
print("KeyError WF variable 1: %s" % e)
|
||||||
|
pass
|
||||||
|
except TypeError as e:
|
||||||
|
print("TypeError WF variables 1: %s" % e)
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
try:
|
||||||
|
for item in fullexecution["execution_variables"]:
|
||||||
|
if parameter["action_field"] == item["name"]:
|
||||||
|
parameter["value"] = item["value"]
|
||||||
|
break
|
||||||
|
except KeyError as e:
|
||||||
|
print("KeyError WF variable 2: %s" % e)
|
||||||
|
pass
|
||||||
|
except TypeError as e:
|
||||||
|
print("TypeError WF variables 2: %s" % e)
|
||||||
|
pass
|
||||||
|
|
||||||
elif parameter["variant"] == "ACTION_RESULT":
|
elif parameter["variant"] == "ACTION_RESULT":
|
||||||
# FIXME - calculate value based on action_field and $if prominent
|
# FIXME - calculate value based on action_field and $if prominent
|
||||||
|
|||||||
@@ -191,13 +191,14 @@ func buildImageMemory(fs billy.Filesystem, tags []string, dockerfileFolder strin
|
|||||||
)
|
)
|
||||||
//log.Printf("IMAGERESPONSE: %#v", imageBuildResponse.Body)
|
//log.Printf("IMAGERESPONSE: %#v", imageBuildResponse.Body)
|
||||||
|
|
||||||
|
defer imageBuildResponse.Body.Close()
|
||||||
|
_, newerr := io.Copy(os.Stdout, imageBuildResponse.Body)
|
||||||
|
if newerr != nil {
|
||||||
|
log.Printf("Failed reading Docker build STDOUT: %s", newerr)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Read the STDOUT from the build process
|
// Read the STDOUT from the build process
|
||||||
defer imageBuildResponse.Body.Close()
|
|
||||||
_, newerr := io.Copy(os.Stdout, imageBuildResponse.Body)
|
|
||||||
if newerr != nil {
|
|
||||||
log.Printf("Failed reading Docker build STDOUT: %s", newerr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2148,7 +2148,7 @@ func getApikey(ctx context.Context, apikey string) (User, error) {
|
|||||||
var users []User
|
var users []User
|
||||||
_, err := dbclient.GetAll(ctx, q, &users)
|
_, err := dbclient.GetAll(ctx, q, &users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error getting users apikey: %s", err)
|
log.Printf("Error getting users apikey (getapikey): %s", err)
|
||||||
return User{}, err
|
return User{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5969,7 +5969,7 @@ func runInit(ctx context.Context) {
|
|||||||
var users []User
|
var users []User
|
||||||
_, err = dbclient.GetAll(ctx, q, &users)
|
_, err = dbclient.GetAll(ctx, q, &users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error getting users apikey: %s", err)
|
log.Printf("Error getting users apikey (runinit): %s", err)
|
||||||
} else {
|
} else {
|
||||||
if len(users) == 0 {
|
if len(users) == 0 {
|
||||||
log.Printf("No active users found - setting ALL to active")
|
log.Printf("No active users found - setting ALL to active")
|
||||||
@@ -6030,6 +6030,7 @@ func runInit(ctx context.Context) {
|
|||||||
} else {
|
} else {
|
||||||
log.Printf("Setting up %d schedule(s)", len(schedules))
|
log.Printf("Setting up %d schedule(s)", len(schedules))
|
||||||
for _, schedule := range schedules {
|
for _, schedule := range schedules {
|
||||||
|
//log.Printf("Schedule: %#v", schedule)
|
||||||
job := func() {
|
job := func() {
|
||||||
request := &http.Request{
|
request := &http.Request{
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
|
|||||||
+78
-57
@@ -138,8 +138,7 @@ type WorkflowAppAction 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" datastore:"execution_variables"`
|
} `json:"execution_variable" datastore:"execution_variables"`
|
||||||
|
|
||||||
Returns struct {
|
Returns struct {
|
||||||
Description string `json:"description" datastore:"returns" yaml:"description,omitempty"`
|
Description string `json:"description" datastore:"returns" yaml:"description,omitempty"`
|
||||||
ID string `json:"id" datastore:"id" yaml:"id,omitempty"`
|
ID string `json:"id" datastore:"id" yaml:"id,omitempty"`
|
||||||
@@ -149,41 +148,53 @@ type WorkflowAppAction struct {
|
|||||||
|
|
||||||
// FIXME: Generate a callback authentication ID?
|
// FIXME: Generate a callback authentication ID?
|
||||||
type WorkflowExecution struct {
|
type WorkflowExecution struct {
|
||||||
Type string `json:"type" datastore:"type"`
|
Type string `json:"type" datastore:"type"`
|
||||||
Status string `json:"status" datastore:"status"`
|
Status string `json:"status" datastore:"status"`
|
||||||
Start string `json:"start" datastore:"start"`
|
Start string `json:"start" datastore:"start"`
|
||||||
ExecutionArgument string `json:"execution_argument" datastore:"execution_argument"`
|
ExecutionArgument string `json:"execution_argument" datastore:"execution_argument"`
|
||||||
ExecutionId string `json:"execution_id" datastore:"execution_id"`
|
ExecutionId string `json:"execution_id" datastore:"execution_id"`
|
||||||
WorkflowId string `json:"workflow_id" datastore:"workflow_id"`
|
WorkflowId string `json:"workflow_id" datastore:"workflow_id"`
|
||||||
LastNode string `json:"last_node" datastore:"last_node"`
|
LastNode string `json:"last_node" datastore:"last_node"`
|
||||||
Authorization string `json:"authorization" datastore:"authorization"`
|
Authorization string `json:"authorization" datastore:"authorization"`
|
||||||
Result string `json:"result" datastore:"result,noindex"`
|
Result string `json:"result" datastore:"result,noindex"`
|
||||||
StartedAt int64 `json:"started_at" datastore:"started_at"`
|
StartedAt int64 `json:"started_at" datastore:"started_at"`
|
||||||
CompletedAt int64 `json:"completed_at" datastore:"completed_at"`
|
CompletedAt int64 `json:"completed_at" datastore:"completed_at"`
|
||||||
ProjectId string `json:"project_id" datastore:"project_id"`
|
ProjectId string `json:"project_id" datastore:"project_id"`
|
||||||
Locations []string `json:"locations" datastore:"locations"`
|
Locations []string `json:"locations" datastore:"locations"`
|
||||||
Workflow Workflow `json:"workflow" datastore:"workflow,noindex"`
|
Workflow Workflow `json:"workflow" datastore:"workflow,noindex"`
|
||||||
Results []ActionResult `json:"results" datastore:"results,noindex"`
|
Results []ActionResult `json:"results" datastore:"results,noindex"`
|
||||||
|
ExecutionVariables []struct {
|
||||||
|
Description string `json:"description" datastore:"description"`
|
||||||
|
ID string `json:"id" datastore:"id"`
|
||||||
|
Name string `json:"name" datastore:"name"`
|
||||||
|
Value string `json:"value" datastore:"value"`
|
||||||
|
} `json:"execution_variables,omitempty" datastore:"execution_variables,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Added environment for location to execute
|
// Added environment for location to execute
|
||||||
type Action struct {
|
type Action struct {
|
||||||
AppName string `json:"app_name" datastore:"app_name"`
|
AppName string `json:"app_name" datastore:"app_name"`
|
||||||
AppVersion string `json:"app_version" datastore:"app_version"`
|
AppVersion string `json:"app_version" datastore:"app_version"`
|
||||||
AppID string `json:"app_id" datastore:"app_id"`
|
AppID string `json:"app_id" datastore:"app_id"`
|
||||||
Errors []string `json:"errors" datastore:"errors"`
|
Errors []string `json:"errors" datastore:"errors"`
|
||||||
ID string `json:"id" datastore:"id"`
|
ID string `json:"id" datastore:"id"`
|
||||||
IsValid bool `json:"is_valid" datastore:"is_valid"`
|
IsValid bool `json:"is_valid" datastore:"is_valid"`
|
||||||
IsStartNode bool `json:"isStartNode" datastore:"isStartNode"`
|
IsStartNode bool `json:"isStartNode" datastore:"isStartNode"`
|
||||||
Sharing bool `json:"sharing" datastore:"sharing"`
|
Sharing bool `json:"sharing" datastore:"sharing"`
|
||||||
PrivateID string `json:"private_id" datastore:"private_id"`
|
PrivateID string `json:"private_id" datastore:"private_id"`
|
||||||
Label string `json:"label" datastore:"label"`
|
Label string `json:"label" datastore:"label"`
|
||||||
SmallImage string `json:"small_image" datastore:"small_image,noindex" required:false yaml:"small_image"`
|
SmallImage string `json:"small_image" datastore:"small_image,noindex" required:false yaml:"small_image"`
|
||||||
LargeImage string `json:"large_image" datastore:"large_image,noindex" yaml:"large_image" required:false`
|
LargeImage string `json:"large_image" datastore:"large_image,noindex" yaml:"large_image" required:false`
|
||||||
Environment string `json:"environment" datastore:"environment"`
|
Environment string `json:"environment" datastore:"environment"`
|
||||||
Name string `json:"name" datastore:"name"`
|
Name string `json:"name" datastore:"name"`
|
||||||
Parameters []WorkflowAppActionParameter `json:"parameters" datastore: "parameters,noindex"`
|
Parameters []WorkflowAppActionParameter `json:"parameters" datastore: "parameters,noindex"`
|
||||||
Position struct {
|
ExecutionVariable struct {
|
||||||
|
Description string `json:"description" datastore:"description"`
|
||||||
|
ID string `json:"id" datastore:"id"`
|
||||||
|
Name string `json:"name" datastore:"name"`
|
||||||
|
Value string `json:"value" datastore:"value"`
|
||||||
|
} `json:"execution_variable,omitempty" datastore:"execution_variable,omitempty"`
|
||||||
|
Position struct {
|
||||||
X float64 `json:"x" datastore:"x"`
|
X float64 `json:"x" datastore:"x"`
|
||||||
Y float64 `json:"y" datastore:"y"`
|
Y float64 `json:"y" datastore:"y"`
|
||||||
} `json:"position"`
|
} `json:"position"`
|
||||||
@@ -265,7 +276,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" datastore:"execution_variables"`
|
} `json:"execution_variables,omitempty" datastore:"execution_variables,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActionResult struct {
|
type ActionResult struct {
|
||||||
@@ -796,13 +807,20 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if found {
|
if found {
|
||||||
// FIXME - this is broken, but why
|
// If result exists and execution variable exists, update execution value
|
||||||
//if workflowExecution.Results[outerindex].Status == actionResult.Status {
|
//log.Printf("Exec var backend: %s", workflowExecution.Results[outerindex].Action.ExecutionVariable.Name)
|
||||||
// log.Printf("Status of %s is already %s", actionResult.Action.ID, actionResult.Status)
|
actionVarName := workflowExecution.Results[outerindex].Action.ExecutionVariable.Name
|
||||||
// resp.WriteHeader(401)
|
// Finds potential execution arguments
|
||||||
// resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Status of %s is already %s"}`, actionResult.Action.ID, actionResult.Status)))
|
if len(actionVarName) > 0 {
|
||||||
// return
|
log.Printf("EXECUTION VARIABLE LOCAL: %s", actionVarName)
|
||||||
//}
|
for index, execvar := range workflowExecution.ExecutionVariables {
|
||||||
|
if execvar.Name == actionVarName {
|
||||||
|
// Sets the value for the variable
|
||||||
|
workflowExecution.ExecutionVariables[index].Value = actionResult.Result
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Updating %s in %s from %s to %s", actionResult.Action.ID, workflowExecution.ExecutionId, workflowExecution.Results[outerindex].Status, actionResult.Status)
|
log.Printf("Updating %s in %s from %s to %s", actionResult.Action.ID, workflowExecution.ExecutionId, workflowExecution.Results[outerindex].Status, actionResult.Status)
|
||||||
workflowExecution.Results[outerindex] = actionResult
|
workflowExecution.Results[outerindex] = actionResult
|
||||||
@@ -1013,6 +1031,7 @@ func setNewWorkflow(resp http.ResponseWriter, request *http.Request) {
|
|||||||
if len(newActions) == 0 {
|
if len(newActions) == 0 {
|
||||||
log.Printf("APPENDING NEW APP FOR NEW WORKFLOW")
|
log.Printf("APPENDING NEW APP FOR NEW WORKFLOW")
|
||||||
|
|
||||||
|
// Adds the Testing app if it's a new workflow
|
||||||
workflowapps, err := getAllWorkflowApps(ctx)
|
workflowapps, err := getAllWorkflowApps(ctx)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
for _, item := range workflowapps {
|
for _, item := range workflowapps {
|
||||||
@@ -1046,7 +1065,7 @@ func setNewWorkflow(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Has actions already?")
|
log.Printf("Has %d actions already", len(newActions))
|
||||||
}
|
}
|
||||||
|
|
||||||
workflow.Actions = newActions
|
workflow.Actions = newActions
|
||||||
@@ -1412,6 +1431,8 @@ 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)
|
||||||
|
|
||||||
builtin := false
|
builtin := false
|
||||||
for _, id := range reservedApps {
|
for _, id := range reservedApps {
|
||||||
if id == action.AppID {
|
if id == action.AppID {
|
||||||
@@ -1935,6 +1956,8 @@ func handleExecution(id string, workflow Workflow, request *http.Request) (Workf
|
|||||||
// Status for the entire workflow.
|
// Status for the entire workflow.
|
||||||
workflowExecution.Status = "EXECUTING"
|
workflowExecution.Status = "EXECUTING"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
workflowExecution.ExecutionVariables = workflow.ExecutionVariables
|
||||||
// Local authorization for this single workflow used in workers.
|
// Local authorization for this single workflow used in workers.
|
||||||
|
|
||||||
// FIXME: Used for cloud
|
// FIXME: Used for cloud
|
||||||
@@ -2095,7 +2118,6 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func stopSchedule(resp http.ResponseWriter, request *http.Request) {
|
func stopSchedule(resp http.ResponseWriter, request *http.Request) {
|
||||||
log.Printf("Delete?")
|
|
||||||
cors := handleCors(resp, request)
|
cors := handleCors(resp, request)
|
||||||
if cors {
|
if cors {
|
||||||
return
|
return
|
||||||
@@ -2262,20 +2284,19 @@ func stopScheduleGCP(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
func deleteSchedule(ctx context.Context, id string) error {
|
func deleteSchedule(ctx context.Context, id string) error {
|
||||||
log.Printf("Should stop schedule %s!", id)
|
log.Printf("Should stop schedule %s!", id)
|
||||||
//newscheduler "github.com/carlescere/scheduler"
|
err := DeleteKey(ctx, "schedules", id)
|
||||||
log.Printf("Schedules: %#v", scheduledJobs)
|
if err != nil {
|
||||||
if value, exists := scheduledJobs[id]; exists {
|
log.Printf("Failed to delete schedule: %s", err)
|
||||||
log.Printf("STOP THIS ONE: %s", value)
|
return err
|
||||||
// Looks like this does the trick? Hurr
|
|
||||||
value.Lock()
|
|
||||||
err := DeleteKey(ctx, "schedules", id)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed to delete schedule: %s", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// FIXME - allow it to kind of stop anyway?
|
if value, exists := scheduledJobs[id]; exists {
|
||||||
return errors.New("Can't find the schedule.")
|
log.Printf("STOP THIS ONE: %s", value)
|
||||||
|
// Looks like this does the trick? Hurr
|
||||||
|
value.Lock()
|
||||||
|
} else {
|
||||||
|
// FIXME - allow it to kind of stop anyway?
|
||||||
|
return errors.New("Can't find the schedule.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -2717,7 +2738,7 @@ func deleteUser(resp http.ResponseWriter, request *http.Request) {
|
|||||||
var users []User
|
var users []User
|
||||||
_, err := dbclient.GetAll(ctx, q, &users)
|
_, err := dbclient.GetAll(ctx, q, &users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error getting users apikey: %s", err)
|
log.Printf("Error getting users apikey (deleteuser): %s", err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": "Failed getting users for verification"}`))
|
resp.Write([]byte(`{"success": false, "reason": "Failed getting users for verification"}`))
|
||||||
return
|
return
|
||||||
|
|||||||
+2
-2
@@ -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}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const Admin = (props) => {
|
|||||||
console.log("INPUT: ", data)
|
console.log("INPUT: ", data)
|
||||||
|
|
||||||
// Just use this one?
|
// Just use this one?
|
||||||
const url = globalUrl+'/api/v1/workflows/'+data["workflow_id datastore:"]+"/schedule/"+data.id
|
const url = globalUrl+'/api/v1/workflows/'+data["workflow_id"]+"/schedule/"+data.id
|
||||||
console.log("URL: ", url)
|
console.log("URL: ", url)
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
@@ -54,6 +54,7 @@ const Admin = (props) => {
|
|||||||
})
|
})
|
||||||
.then(response =>
|
.then(response =>
|
||||||
response.json().then(responseJson => {
|
response.json().then(responseJson => {
|
||||||
|
console.log("RESP: ", responseJson)
|
||||||
if (responseJson["success"] === false) {
|
if (responseJson["success"] === false) {
|
||||||
alert.error("Failed stopping schedule")
|
alert.error("Failed stopping schedule")
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+221
-29
@@ -112,6 +112,7 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
const [appAuthentication, setAppAuthentication] = React.useState({});
|
const [appAuthentication, setAppAuthentication] = React.useState({});
|
||||||
const [variablesModalOpen, setVariablesModalOpen] = React.useState(false);
|
const [variablesModalOpen, setVariablesModalOpen] = React.useState(false);
|
||||||
|
const [executionVariablesModalOpen, setExecutionVariablesModalOpen] = React.useState(false);
|
||||||
const [authenticationModalOpen, setAuthenticationModalOpen] = React.useState(false);
|
const [authenticationModalOpen, setAuthenticationModalOpen] = React.useState(false);
|
||||||
const [conditionsModalOpen, setConditionsModalOpen] = React.useState(false);
|
const [conditionsModalOpen, setConditionsModalOpen] = React.useState(false);
|
||||||
const [newVariableName, setNewVariableName] = React.useState("");
|
const [newVariableName, setNewVariableName] = React.useState("");
|
||||||
@@ -791,7 +792,6 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
const onNodeSelect = (event) => {
|
const onNodeSelect = (event) => {
|
||||||
const data = event.target.data()
|
const data = event.target.data()
|
||||||
console.log("NODE: ", data)
|
|
||||||
setLastSaved(false)
|
setLastSaved(false)
|
||||||
//console.log(data)
|
//console.log(data)
|
||||||
|
|
||||||
@@ -1412,22 +1412,6 @@ const AngularWorkflow = (props) => {
|
|||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||||
|
|
||||||
if (workflow.workflow_variables === undefined || workflow.workflow_variables === null || workflow.workflow_variables.length === 0) {
|
|
||||||
return (
|
|
||||||
<div style={appViewStyle}>
|
|
||||||
<div style={appScrollStyle}>
|
|
||||||
<div style={{margin: 10}}>
|
|
||||||
Looks like you don't have any variables yet.
|
|
||||||
<div/>
|
|
||||||
<div style={{width: "100%", margin: "auto"}}>
|
|
||||||
<Button fullWidth style={{margin: "auto", marginTop: "10px", borderRadius: 0}} color="primary" variant="outlined" onClick={() => setVariablesModalOpen(true)}>Make a new workflow variable</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const menuClick = (event) => {
|
const menuClick = (event) => {
|
||||||
setOpen(!open)
|
setOpen(!open)
|
||||||
setAnchorEl(event.currentTarget);
|
setAnchorEl(event.currentTarget);
|
||||||
@@ -1438,8 +1422,13 @@ const AngularWorkflow = (props) => {
|
|||||||
setWorkflow(workflow)
|
setWorkflow(workflow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deleteExecutionVariable = (variableName) => {
|
||||||
|
workflow.execution_variables = workflow.execution_variables.filter(data => data.name !== variableName)
|
||||||
|
setWorkflow(workflow)
|
||||||
|
}
|
||||||
|
|
||||||
const variableScrollStyle = {
|
const variableScrollStyle = {
|
||||||
marginTop: "10px",
|
margin: 15,
|
||||||
overflow: "scroll",
|
overflow: "scroll",
|
||||||
height: "66vh",
|
height: "66vh",
|
||||||
overflowX: "auto",
|
overflowX: "auto",
|
||||||
@@ -1450,7 +1439,9 @@ const AngularWorkflow = (props) => {
|
|||||||
return (
|
return (
|
||||||
<div style={appViewStyle}>
|
<div style={appViewStyle}>
|
||||||
<div style={variableScrollStyle}>
|
<div style={variableScrollStyle}>
|
||||||
{workflow.workflow_variables.map(variable=> {
|
<a href="https://shuffler.io/docs/workflows#variables" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>What are WORKFLOW variables?</a>
|
||||||
|
{workflow.workflow_variables === null ?
|
||||||
|
null : workflow.workflow_variables.map(variable=> {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Paper square style={paperVariableStyle} onClick={() => {
|
<Paper square style={paperVariableStyle} onClick={() => {
|
||||||
@@ -1508,10 +1499,69 @@ const AngularWorkflow = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
<div style={{flex: "1"}}>
|
||||||
|
<Button fullWidth style={{margin: "auto", marginTop: "10px",}} color="primary" variant="outlined" onClick={() => setVariablesModalOpen(true)}>New workflow variable</Button>
|
||||||
|
</div>
|
||||||
|
<Divider style={{marginBottom: 20, marginTop: 20, height: 1, width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
|
||||||
|
<a href="https://shuffler.io/docs/workflows#execution_variables" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>What are EXECUTION variables?</a>
|
||||||
|
{workflow.execution_variables === null ?
|
||||||
|
null : workflow.execution_variables.map(variable=> {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Paper square style={paperVariableStyle} onClick={() => {
|
||||||
|
}}>
|
||||||
|
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: "2px", backgroundColor: "orange", marginRight: "5px"}} />
|
||||||
|
<div style={{display: "flex", width: "100%"}}>
|
||||||
|
<div style={{flex: "10", marginTop: "15px", marginLeft: "10px", overflow: "hidden"}} onClick={() => {
|
||||||
|
setNewVariableName(variable.name)
|
||||||
|
setExecutionVariablesModalOpen(true)}}>
|
||||||
|
Name: {variable.name}
|
||||||
|
</div>
|
||||||
|
<div style={{flex: "1", marginLeft: "0px"}}>
|
||||||
|
<IconButton
|
||||||
|
aria-label="more"
|
||||||
|
aria-controls="long-menu"
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={menuClick}
|
||||||
|
style={{color: "white"}}
|
||||||
|
>
|
||||||
|
<MoreVertIcon />
|
||||||
|
</IconButton>
|
||||||
|
<Menu
|
||||||
|
id="long-menu"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
keepMounted
|
||||||
|
open={open}
|
||||||
|
PaperProps={{
|
||||||
|
style: {
|
||||||
|
backgroundColor: surfaceColor,
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onClose={() => {
|
||||||
|
setOpen(false)
|
||||||
|
setAnchorEl(null)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
</div>
|
<MenuItem style={{backgroundColor: surfaceColor, color: "white"}} onClick={() => {
|
||||||
<div style={{flex: "1"}}>
|
setOpen(false)
|
||||||
<Button fullWidth style={{margin: "auto", marginTop: "10px",}} color="primary" variant="outlined" onClick={() => setVariablesModalOpen(true)}>New workflow variable</Button>
|
setNewVariableName(variable.name)
|
||||||
|
setExecutionVariablesModalOpen(true)
|
||||||
|
}} key={"Edit"}>{"Edit"}</MenuItem>
|
||||||
|
<MenuItem style={{backgroundColor: surfaceColor, color: "white"}} onClick={() => {
|
||||||
|
deleteExecutionVariable(variable.name)
|
||||||
|
setOpen(false)
|
||||||
|
}} key={"Delete"}>{"Delete"}</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<div style={{flex: "1"}}>
|
||||||
|
<Button fullWidth style={{margin: "auto", marginTop: "10px",}} color="primary" variant="outlined" onClick={() => setExecutionVariablesModalOpen(true)}>New execution variable</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -1862,6 +1912,7 @@ const AngularWorkflow = (props) => {
|
|||||||
isStartNode: false,
|
isStartNode: false,
|
||||||
large_image: app.large_image,
|
large_image: app.large_image,
|
||||||
authentication: [],
|
authentication: [],
|
||||||
|
execution_variable: undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
// const image = "url("+app.large_image+")"
|
// const image = "url("+app.large_image+")"
|
||||||
@@ -2361,7 +2412,7 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
} else if (data.variant === "WORKFLOW_VARIABLE") {
|
} else if (data.variant === "WORKFLOW_VARIABLE") {
|
||||||
varcolor = "#f85a3e"
|
varcolor = "#f85a3e"
|
||||||
if (workflow.workflow_variables === null || workflow.workflow_variables === undefined || workflow.workflow_variables.length === 0) {
|
if ((workflow.workflow_variables === null || workflow.workflow_variables === undefined || workflow.workflow_variables.length === 0) && (workflow.execution_variables === null || workflow.execution_variables === undefined || workflow.execution_variables.length === 0)) {
|
||||||
setCurrentView(2)
|
setCurrentView(2)
|
||||||
datafield =
|
datafield =
|
||||||
<div>
|
<div>
|
||||||
@@ -2389,15 +2440,22 @@ const AngularWorkflow = (props) => {
|
|||||||
fullWidth
|
fullWidth
|
||||||
value={selectedAction.parameters[count].action_field}
|
value={selectedAction.parameters[count].action_field}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
console.log(e.target.value)
|
||||||
changeActionParameterVariable(e.target.value, count)
|
changeActionParameterVariable(e.target.value, count)
|
||||||
}}
|
}}
|
||||||
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
||||||
>
|
>
|
||||||
{workflow.workflow_variables.map(data => (
|
{workflow.workflow_variables !== null ? workflow.workflow_variables.map(data => (
|
||||||
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data.name}>
|
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data.name}>
|
||||||
{data.name}
|
{data.name}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
)) : null}
|
||||||
|
<Divider />
|
||||||
|
{workflow.execution_variables !== null ? workflow.execution_variables.map(data => (
|
||||||
|
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data.name}>
|
||||||
|
{data.name}
|
||||||
|
</MenuItem>
|
||||||
|
)) : null}
|
||||||
</Select>
|
</Select>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2544,7 +2602,7 @@ const AngularWorkflow = (props) => {
|
|||||||
placeholder={selectedAction.label}
|
placeholder={selectedAction.label}
|
||||||
onChange={selectedNameChange}
|
onChange={selectedNameChange}
|
||||||
/>
|
/>
|
||||||
{environments !== undefined && environments.length > 1 ?
|
{environments !== undefined && environments !== null && environments.length > 1 ?
|
||||||
<div style={{marginTop: "20px"}}>
|
<div style={{marginTop: "20px"}}>
|
||||||
Environment
|
Environment
|
||||||
<Select
|
<Select
|
||||||
@@ -2576,6 +2634,42 @@ const AngularWorkflow = (props) => {
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
|
{workflow.execution_variables !== undefined && workflow.execution_variables !== null && workflow.execution_variables.length > 0 ?
|
||||||
|
<div style={{marginTop: "20px"}}>
|
||||||
|
Execution variables
|
||||||
|
<Select
|
||||||
|
value={selectedAction.execution_variable !== undefined ? selectedAction.execution_variable.name : {"name": "Select a variable"}}
|
||||||
|
PaperProps={{
|
||||||
|
style: {
|
||||||
|
backgroundColor: inputColor,
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
SelectDisplayProps={{
|
||||||
|
style: {
|
||||||
|
marginLeft: 10,
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
fullWidth
|
||||||
|
onChange={(e) => {
|
||||||
|
console.log("Variable", e.target.value)
|
||||||
|
//selectedAction.
|
||||||
|
const value = workflow.execution_variables.find(a => a.name === e.target.value.name)
|
||||||
|
console.log("FOUND: ", value)
|
||||||
|
selectedAction.execution_variable = value
|
||||||
|
setSelectedAction(selectedAction)
|
||||||
|
//setSelectedActionEnvironment(env)
|
||||||
|
//selectedAction.environment = env.Name
|
||||||
|
}}
|
||||||
|
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
||||||
|
>
|
||||||
|
{workflow.execution_variables.map(data => (
|
||||||
|
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
||||||
|
{data.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
: null}
|
||||||
{/*requiresAuthentication ?
|
{/*requiresAuthentication ?
|
||||||
<div style={{marginTop: "20px"}}>
|
<div style={{marginTop: "20px"}}>
|
||||||
<Button fullWidth style={{margin: "auto", marginTop: "10px",}} color="primary" variant="contained" onClick={() => setAuthenticationModalOpen(true)}>
|
<Button fullWidth style={{margin: "auto", marginTop: "10px",}} color="primary" variant="contained" onClick={() => setAuthenticationModalOpen(true)}>
|
||||||
@@ -4309,7 +4403,7 @@ const AngularWorkflow = (props) => {
|
|||||||
)
|
)
|
||||||
} else if (Object.getOwnPropertyNames(selectedTrigger).length > 0) {
|
} else if (Object.getOwnPropertyNames(selectedTrigger).length > 0) {
|
||||||
if (selectedTrigger.trigger_type === "SCHEDULE") {
|
if (selectedTrigger.trigger_type === "SCHEDULE") {
|
||||||
console.log("SCHEDULE")
|
//console.log("SCHEDULE")
|
||||||
return(
|
return(
|
||||||
<div style={rightsidebarStyle}>
|
<div style={rightsidebarStyle}>
|
||||||
<ScheduleSidebar />
|
<ScheduleSidebar />
|
||||||
@@ -4492,7 +4586,6 @@ const AngularWorkflow = (props) => {
|
|||||||
executionData.results.map(data => {
|
executionData.results.map(data => {
|
||||||
var showResult = data.result.trim()
|
var showResult = data.result.trim()
|
||||||
showResult.split(" None").join(" \"None\"")
|
showResult.split(" None").join(" \"None\"")
|
||||||
console.log("RESULT: ", showResult)
|
|
||||||
|
|
||||||
// showResult = replaceAll(showResult, " None", " \"None\"")
|
// showResult = replaceAll(showResult, " None", " \"None\"")
|
||||||
// Super basic check.
|
// Super basic check.
|
||||||
@@ -4555,7 +4648,7 @@ const AngularWorkflow = (props) => {
|
|||||||
cy={(incy) => {
|
cy={(incy) => {
|
||||||
// FIXME: There's something specific loading when
|
// FIXME: There's something specific loading when
|
||||||
// you do the first hover of a node. Why is this different?
|
// you do the first hover of a node. Why is this different?
|
||||||
console.log("CY: ", incy)
|
//console.log("CY: ", incy)
|
||||||
setCy(incy)
|
setCy(incy)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -4569,6 +4662,104 @@ const AngularWorkflow = (props) => {
|
|||||||
<div style={{color: "white"}}>
|
<div style={{color: "white"}}>
|
||||||
TMP FOR NOT LOGGED IN
|
TMP FOR NOT LOGGED IN
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
const executionVariableModal = executionVariablesModalOpen ?
|
||||||
|
<Dialog modal
|
||||||
|
open={executionVariablesModalOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setNewVariableName("")
|
||||||
|
setExecutionVariablesModalOpen(false)
|
||||||
|
}}
|
||||||
|
PaperProps={{
|
||||||
|
style: {
|
||||||
|
backgroundColor: surfaceColor,
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<DialogTitle><span style={{color: "white"}}>Execution Variable</span></DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
Execution Variables are TEMPORARY variables that you can ony be set and used during execution. Learn more <a href="https://shuffler.io/docs/workflow#execution_variables" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>here</a>
|
||||||
|
<TextField
|
||||||
|
onBlur={(event) => setNewVariableName(event.target.value)}
|
||||||
|
color="primary"
|
||||||
|
placeholder="Name"
|
||||||
|
style={{marginTop: 25}}
|
||||||
|
InputProps={{
|
||||||
|
style:{
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
margin="dense"
|
||||||
|
fullWidth
|
||||||
|
defaultValue={newVariableName}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button
|
||||||
|
style={{borderRadius: "0px"}}
|
||||||
|
onClick={() => {
|
||||||
|
setNewVariableName("")
|
||||||
|
setExecutionVariablesModalOpen(false)
|
||||||
|
}} color="primary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button style={{borderRadius: "0px"}} disabled={newVariableName.length === 0} onClick={() => {
|
||||||
|
console.log("VARIABLES! ", newVariableName)
|
||||||
|
if (workflow.execution_variables === undefined || workflow.execution_variables === null) {
|
||||||
|
workflow.execution_variables = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to find one with the same name
|
||||||
|
const found = workflow.execution_variables.findIndex(data => data.name === newVariableName)
|
||||||
|
//console.log(found)
|
||||||
|
if (found !== -1) {
|
||||||
|
if (newVariableName.length > 0) {
|
||||||
|
workflow.execution_variables[found].name = newVariableName
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
workflow.execution_variables.push({
|
||||||
|
"name": newVariableName,
|
||||||
|
"description": "An execution variable",
|
||||||
|
"value": "",
|
||||||
|
"id": uuid.v4(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setExecutionVariablesModalOpen(false)
|
||||||
|
setNewVariableName("")
|
||||||
|
setWorkflow(workflow)
|
||||||
|
}} color="primary">
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
{workflowExecutions.length > 0 ?
|
||||||
|
<DialogContent>
|
||||||
|
<Divider style={{backgroundColor: "white", marginTop: 15, marginBottom: 15,}}/>
|
||||||
|
<b style={{marginBottom: 10}}>Values from last 3 executions</b>
|
||||||
|
{workflowExecutions.slice(0,3).map((execution, index) => {
|
||||||
|
if (execution.execution_variables === undefined || execution.execution_variables === null || execution.execution_variables === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const variable = execution.execution_variables.find(data => data.name === newVariableName)
|
||||||
|
if (variable === undefined || variable.value === undefined) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{index+1}: {variable.value}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</DialogContent>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
</FormControl>
|
||||||
|
</Dialog>
|
||||||
|
: null
|
||||||
|
|
||||||
const variablesModal = variablesModalOpen ?
|
const variablesModal = variablesModalOpen ?
|
||||||
<Dialog modal
|
<Dialog modal
|
||||||
@@ -4808,6 +4999,7 @@ const AngularWorkflow = (props) => {
|
|||||||
<div>
|
<div>
|
||||||
{newView}
|
{newView}
|
||||||
{variablesModal}
|
{variablesModal}
|
||||||
|
{executionVariableModal}
|
||||||
{conditionsModal}
|
{conditionsModal}
|
||||||
{authenticationModal}
|
{authenticationModal}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -90,13 +90,11 @@ const App = (message, props) => {
|
|||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(responseJson => {
|
.then(responseJson => {
|
||||||
console.log(responseJson)
|
|
||||||
if (responseJson.success === true) {
|
if (responseJson.success === true) {
|
||||||
setUserData(responseJson)
|
setUserData(responseJson)
|
||||||
setIsLoggedIn(true)
|
setIsLoggedIn(true)
|
||||||
|
|
||||||
// Updating cookie every request
|
// Updating cookie every request
|
||||||
console.log("COOKIES: ", cookies)
|
|
||||||
for (var key in responseJson["cookies"]) {
|
for (var key in responseJson["cookies"]) {
|
||||||
setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, {path: "/"})
|
setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, {path: "/"})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -905,6 +905,7 @@ const Apps = (props) => {
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
: null
|
: null
|
||||||
|
|
||||||
|
const circularLoader = validation ? <CircularProgress color="primary" /> : null
|
||||||
const appsModalLoad = loadAppsModalOpen ?
|
const appsModalLoad = loadAppsModalOpen ?
|
||||||
<Dialog modal
|
<Dialog modal
|
||||||
open={loadAppsModalOpen}
|
open={loadAppsModalOpen}
|
||||||
@@ -998,7 +999,6 @@ const Apps = (props) => {
|
|||||||
: null
|
: null
|
||||||
|
|
||||||
const errorText = openApiError.length > 0 ? <div>Error: {openApiError}</div> : null
|
const errorText = openApiError.length > 0 ? <div>Error: {openApiError}</div> : null
|
||||||
const circularLoader = validation ? <CircularProgress color="primary" /> : null
|
|
||||||
const modalView = openApiModal ?
|
const modalView = openApiModal ?
|
||||||
<Dialog modal
|
<Dialog modal
|
||||||
open={openApiModal}
|
open={openApiModal}
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ var orgId = os.Getenv("ORG_ID")
|
|||||||
var sleepTime = 3
|
var sleepTime = 3
|
||||||
|
|
||||||
// Timeout if somethinc rashes
|
// Timeout if somethinc rashes
|
||||||
var workerTimeout = 600
|
//var workerTimeout = 600
|
||||||
|
var workerTimeout = 300
|
||||||
|
|
||||||
type ExecutionRequestWrapper struct {
|
type ExecutionRequestWrapper struct {
|
||||||
Data []ExecutionRequest `json:"data"`
|
Data []ExecutionRequest `json:"data"`
|
||||||
@@ -52,7 +53,7 @@ type ExecutionRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deploys the internal worker whenever something happens
|
// Deploys the internal worker whenever something happens
|
||||||
func deployWorker(cli *dockerclient.Client, image string, identifier string, env []string) error {
|
func deployWorker(cli *dockerclient.Client, image string, identifier string, env []string) {
|
||||||
// Binds is the actual "-v" volume.
|
// Binds is the actual "-v" volume.
|
||||||
hostConfig := &container.HostConfig{
|
hostConfig := &container.HostConfig{
|
||||||
LogConfig: container.LogConfig{
|
LogConfig: container.LogConfig{
|
||||||
@@ -101,16 +102,40 @@ func deployWorker(cli *dockerclient.Client, image string, identifier string, env
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cli.ContainerStart(context.Background(), cont.ID, types.ContainerStartOptions{})
|
err = cli.ContainerStart(context.Background(), cont.ID, types.ContainerStartOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to start container in environment %s: %s", environment, err)
|
log.Printf("Failed to start container in environment %s: %s", environment, err)
|
||||||
|
return
|
||||||
|
|
||||||
|
//stats, err := cli.ContainerInspect(context.Background(), containerName)
|
||||||
|
//if err != nil {
|
||||||
|
// log.Printf("Failed checking worker %s", containerName)
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
|
||||||
|
//containerStatus := stats.ContainerJSONBase.State.Status
|
||||||
|
//if containerStatus != "running" {
|
||||||
|
// log.Printf("Status of %s is %s. Should be running. Will reset", containerName, containerStatus)
|
||||||
|
// err = stopWorker(containerName)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Printf("Failed stopping worker %s", execution.ExecutionId)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// err = deployWorker(cli, workerImage, containerName, env)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Printf("Failed executing worker %s in state %s", execution.ExecutionId, containerStatus)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Container %s was created under environment %s", cont.ID, environment)
|
log.Printf("Container %s was created under environment %s", cont.ID, environment)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopWorker(containername string) error {
|
func stopWorker(containername string) error {
|
||||||
@@ -169,7 +194,7 @@ func initializeImages(dockercli *dockerclient.Client) {
|
|||||||
|
|
||||||
// Initial loop etc
|
// Initial loop etc
|
||||||
func main() {
|
func main() {
|
||||||
zombiecheck()
|
go zombiecheck()
|
||||||
log.Println("Setting up execution environment")
|
log.Println("Setting up execution environment")
|
||||||
|
|
||||||
//FIXME
|
//FIXME
|
||||||
@@ -236,7 +261,7 @@ func main() {
|
|||||||
log.Printf("Failed making request: %s", err)
|
log.Printf("Failed making request: %s", err)
|
||||||
zombiecounter += 1
|
zombiecounter += 1
|
||||||
if zombiecounter*sleepTime > workerTimeout {
|
if zombiecounter*sleepTime > workerTimeout {
|
||||||
zombiecheck()
|
go zombiecheck()
|
||||||
zombiecounter = 0
|
zombiecounter = 0
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(sleepTime) * time.Second)
|
time.Sleep(time.Duration(sleepTime) * time.Second)
|
||||||
@@ -257,7 +282,7 @@ func main() {
|
|||||||
log.Printf("Failed reading body: %s", err)
|
log.Printf("Failed reading body: %s", err)
|
||||||
zombiecounter += 1
|
zombiecounter += 1
|
||||||
if zombiecounter*sleepTime > workerTimeout {
|
if zombiecounter*sleepTime > workerTimeout {
|
||||||
zombiecheck()
|
go zombiecheck()
|
||||||
zombiecounter = 0
|
zombiecounter = 0
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(sleepTime) * time.Second)
|
time.Sleep(time.Duration(sleepTime) * time.Second)
|
||||||
@@ -271,7 +296,7 @@ func main() {
|
|||||||
sleepTime = 10
|
sleepTime = 10
|
||||||
zombiecounter += 1
|
zombiecounter += 1
|
||||||
if zombiecounter*sleepTime > workerTimeout {
|
if zombiecounter*sleepTime > workerTimeout {
|
||||||
zombiecheck()
|
go zombiecheck()
|
||||||
zombiecounter = 0
|
zombiecounter = 0
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(sleepTime) * time.Second)
|
time.Sleep(time.Duration(sleepTime) * time.Second)
|
||||||
@@ -286,7 +311,7 @@ func main() {
|
|||||||
if len(executionRequests.Data) == 0 {
|
if len(executionRequests.Data) == 0 {
|
||||||
zombiecounter += 1
|
zombiecounter += 1
|
||||||
if zombiecounter*sleepTime > workerTimeout {
|
if zombiecounter*sleepTime > workerTimeout {
|
||||||
zombiecheck()
|
go zombiecheck()
|
||||||
zombiecounter = 0
|
zombiecounter = 0
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(sleepTime) * time.Second)
|
time.Sleep(time.Duration(sleepTime) * time.Second)
|
||||||
@@ -322,34 +347,9 @@ func main() {
|
|||||||
env = append(env, fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion))
|
env = append(env, fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion))
|
||||||
}
|
}
|
||||||
|
|
||||||
err = deployWorker(dockercli, workerImage, containerName, env)
|
go deployWorker(dockercli, workerImage, containerName, env)
|
||||||
if err != nil {
|
|
||||||
stats, err := dockercli.ContainerInspect(context.Background(), containerName)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed checking worker %s", execution.ExecutionId)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
containerStatus := stats.ContainerJSONBase.State.Status
|
log.Printf("%s is deployed and to be removed from queue.", execution.ExecutionId)
|
||||||
if containerStatus != "running" {
|
|
||||||
log.Printf("Status of %s is %s. Should be running. Will reset", containerName, containerStatus)
|
|
||||||
err = stopWorker(containerName)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed stopping worker %s", execution.ExecutionId)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = deployWorker(dockercli, workerImage, containerName, env)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed executing worker %s in state %s", execution.ExecutionId, containerStatus)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Should basically never hit here rofl
|
|
||||||
log.Printf("ERROR: I HAVE NO IDEA WHAT WENT WRONG. CHECK %s", containerName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("%s is deployed and to being removed from queue.", execution.ExecutionId)
|
|
||||||
zombiecounter += 1
|
zombiecounter += 1
|
||||||
toBeRemoved.Data = append(toBeRemoved.Data, execution)
|
toBeRemoved.Data = append(toBeRemoved.Data, execution)
|
||||||
}
|
}
|
||||||
@@ -427,34 +427,54 @@ func zombiecheck() error {
|
|||||||
All: true,
|
All: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
containerNames := map[string]string{}
|
||||||
|
|
||||||
stopContainers := []string{}
|
stopContainers := []string{}
|
||||||
removeContainers := []string{}
|
removeContainers := []string{}
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
|
|
||||||
|
// Skip random containers. Only handle things related to Shuffle.
|
||||||
|
if !strings.Contains(container.Image, baseimagename) {
|
||||||
|
shuffleFound := false
|
||||||
|
for _, item := range container.Labels {
|
||||||
|
if item == "shuffle" {
|
||||||
|
shuffleFound = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check image name
|
||||||
|
if !shuffleFound {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, name := range container.Names {
|
for _, name := range container.Names {
|
||||||
// FIXME - add name_version_uid_uid regex check as well
|
// FIXME - add name_version_uid_uid regex check as well
|
||||||
if !strings.HasPrefix(name, "/worker") {
|
if strings.HasPrefix(name, "/shuffle") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.State != "running" {
|
if container.State != "running" {
|
||||||
removeContainers = append(removeContainers, container.ID)
|
removeContainers = append(removeContainers, container.ID)
|
||||||
|
containerNames[container.ID] = name
|
||||||
}
|
}
|
||||||
|
|
||||||
// stopcontainer & removecontainer
|
// stopcontainer & removecontainer
|
||||||
currenttime := time.Now().Unix()
|
currenttime := time.Now().Unix()
|
||||||
|
//log.Printf("Time: %d - %d", currenttime-container.Created, int64(workerTimeout))
|
||||||
if container.State == "running" && currenttime-container.Created > int64(workerTimeout) {
|
if container.State == "running" && currenttime-container.Created > int64(workerTimeout) {
|
||||||
stopContainers = append(stopContainers, container.ID)
|
stopContainers = append(stopContainers, container.ID)
|
||||||
|
containerNames[container.ID] = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME - add killing of apps with same execution ID too
|
// FIXME - add killing of apps with same execution ID too
|
||||||
for _, containername := range stopContainers {
|
for _, containername := range stopContainers {
|
||||||
if err := dockercli.ContainerStop(ctx, containername, nil); err != nil {
|
log.Printf("Stopping and removing container %s", containerNames[containername])
|
||||||
log.Printf("Unable to stop container: %s", err)
|
go dockercli.ContainerStop(ctx, containername, nil)
|
||||||
} else {
|
removeContainers = append(removeContainers, containername)
|
||||||
log.Printf("Stopped container %s", containername)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeOptions := types.ContainerRemoveOptions{
|
removeOptions := types.ContainerRemoveOptions{
|
||||||
@@ -463,11 +483,7 @@ func zombiecheck() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, containername := range removeContainers {
|
for _, containername := range removeContainers {
|
||||||
if err := dockercli.ContainerRemove(ctx, containername, removeOptions); err != nil {
|
go dockercli.ContainerRemove(ctx, containername, removeOptions)
|
||||||
log.Printf("Unable to remove container: %s", err)
|
|
||||||
} else {
|
|
||||||
log.Printf("Removed container %s", containername)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user