Even more runtime debugger and docs fixes
This commit is contained in:
@@ -522,6 +522,7 @@ class AppBase:
|
||||
break
|
||||
else:
|
||||
self.logger.info(f"[ERROR] Bad resp {ret.status_code}: {ret.text}")
|
||||
time.sleep(sleeptime)
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
self.logger.info(f"[DEBUG] Request problem: {e}")
|
||||
|
||||
@@ -18,7 +18,7 @@ require (
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/h2non/filetype v1.1.3
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/shuffle/shuffle-shared v0.5.11
|
||||
github.com/shuffle/shuffle-shared v0.5.14
|
||||
golang.org/x/crypto v0.14.0
|
||||
google.golang.org/api v0.125.0
|
||||
google.golang.org/grpc v1.55.0
|
||||
|
||||
@@ -416,6 +416,10 @@ github.com/shuffle/shuffle-shared v0.4.97 h1:1c8LdNteMykKNEV97vwP63oSP2tV/Uso3O4
|
||||
github.com/shuffle/shuffle-shared v0.4.97/go.mod h1:X613gbo0dT3fnYvXDRwjQZyLC+T49T2nSQOrCV5QMlI=
|
||||
github.com/shuffle/shuffle-shared v0.4.98 h1:pgsLdWUpxZ/q+eHpAjOCH9icOsmuO5u2olmirOldy5A=
|
||||
github.com/shuffle/shuffle-shared v0.4.98/go.mod h1:X613gbo0dT3fnYvXDRwjQZyLC+T49T2nSQOrCV5QMlI=
|
||||
github.com/shuffle/shuffle-shared v0.5.11 h1:Eqbs9o8E49QAL5/6aV6BfFtWSjLIvgET7AL3fa4OQTg=
|
||||
github.com/shuffle/shuffle-shared v0.5.11/go.mod h1:X613gbo0dT3fnYvXDRwjQZyLC+T49T2nSQOrCV5QMlI=
|
||||
github.com/shuffle/shuffle-shared v0.5.14 h1:d14u1e4k+qKgnf4Insq4x2S+0MMKlDqdyTTyVP3puRA=
|
||||
github.com/shuffle/shuffle-shared v0.5.14/go.mod h1:X613gbo0dT3fnYvXDRwjQZyLC+T49T2nSQOrCV5QMlI=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
|
||||
@@ -56,6 +56,7 @@ const RuntimeDebugger = (props) => {
|
||||
const [startTime, setStartTime] = useState("")
|
||||
|
||||
const [workflow, setWorkflow] = useState({})
|
||||
const [ignoreOrg, setIgnoreOrg] = useState(false)
|
||||
const [searchLoading, setSearchLoading] = useState(false)
|
||||
const [rowCursor, setCursor] = useState("")
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10)
|
||||
@@ -85,6 +86,7 @@ const RuntimeDebugger = (props) => {
|
||||
status: status.toUpperCase(),
|
||||
start_time: startTime,
|
||||
end_time: endTime,
|
||||
ignore_org: ignoreOrg,
|
||||
}
|
||||
|
||||
fetch(`${globalUrl}/api/v1/workflows/search`, {
|
||||
@@ -185,6 +187,38 @@ const RuntimeDebugger = (props) => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
const forceContinue = (execution) => {
|
||||
console.log(`FORCE CONTINUE execution ${execution.execution_id} for workflow ${execution.workflow.id}`)
|
||||
|
||||
fetch(`${globalUrl}/api/v1/workflows/${execution.workflow.id}/executions/${execution.execution_id}/rerun`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.success) {
|
||||
if (data.reason !== undefined && data.reason !== null && data.reason !== "") {
|
||||
toast("Successful response: " + data.reason)
|
||||
} else {
|
||||
toast("Successfully forced continue")
|
||||
}
|
||||
} else {
|
||||
if (data.reason !== undefined && data.reason !== null && data.reason !== "") {
|
||||
toast(`Failed to force continue: ${data.reason}`)
|
||||
} else {
|
||||
toast("Failed to force continue")
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
toast(`Failed to force continue: ${error}`)
|
||||
})
|
||||
}
|
||||
|
||||
const imageSize = 30
|
||||
const timenowUnix = Math.floor(Date.now() / 1000)
|
||||
const columns: GridColDef[] = [
|
||||
@@ -371,7 +405,7 @@ const RuntimeDebugger = (props) => {
|
||||
{
|
||||
field: 'id',
|
||||
headerName: 'Explore',
|
||||
width: 100,
|
||||
width: 120,
|
||||
renderCell: (params) => {
|
||||
const parsedResult = params.row.result === null || params.row.result === undefined || params.row.result === "" ? "" : params.row.result
|
||||
|
||||
@@ -443,31 +477,47 @@ const RuntimeDebugger = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip arrow placement="right" title={
|
||||
<Typography variant="body2" style={{whiteSpace: "pre-line", padding: 10, }}>
|
||||
Workflow result: {errorReason}<br/><br/>
|
||||
{params.row.result !== null && params.row.result !== undefined && params.row.result !== "" ?
|
||||
params.row.result
|
||||
:
|
||||
null
|
||||
}
|
||||
</Typography>
|
||||
}>
|
||||
<span style={{backgroundColor: !hasError ? "inherit" : "rgba(244,0,0,0.45)", display: "flex", }}>
|
||||
<Link href={`/workflows/${params.row.workflow.id}?execution_id=${params.row.id}`} target="_blank" rel="noopener noreferrer">
|
||||
<OpenInNewIcon fontSize="small" style={{marginTop: 7, }} />
|
||||
</Link>
|
||||
<IconButton
|
||||
style={{marginLeft: 10, }}
|
||||
onClick={() => {
|
||||
window.open(`${globalUrl}/api/v1/workflows/search/${params.row.id}`, "_blank")
|
||||
}}
|
||||
disabled={!userdata.support}
|
||||
>
|
||||
<InsightsIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<div style={{display: "flex", }}>
|
||||
<Tooltip arrow placement="right" title={
|
||||
<Typography variant="body2" style={{whiteSpace: "pre-line", padding: 10, }}>
|
||||
Workflow result: {errorReason}<br/><br/>
|
||||
{params.row.result !== null && params.row.result !== undefined && params.row.result !== "" ?
|
||||
params.row.result
|
||||
:
|
||||
null
|
||||
}
|
||||
</Typography>
|
||||
}>
|
||||
<span style={{backgroundColor: !hasError ? "inherit" : "rgba(244,0,0,0.45)", display: "flex", }}>
|
||||
<Link href={`/workflows/${params.row.workflow.id}?execution_id=${params.row.id}`} target="_blank" rel="noopener noreferrer">
|
||||
<OpenInNewIcon fontSize="small" style={{marginTop: 7, }} />
|
||||
</Link>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip arrow title="Force continue workflow. Only workflows for workflows in EXECUTING state. This is NOT a rerun, but way for Shuffle to figure out the next steps automatically. If the execution doesn't finish even after trying this, please contact support@shuffler.io">
|
||||
<IconButton
|
||||
style={{marginLeft: 5, }}
|
||||
disabled={params.row.status !== "EXECUTING"}
|
||||
onClick={() => {
|
||||
forceContinue(params.row)
|
||||
|
||||
}}
|
||||
>
|
||||
<PlayArrowIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip arrow title="Explore workflow run logs">
|
||||
<IconButton
|
||||
style={{marginLeft: 5, }}
|
||||
onClick={() => {
|
||||
window.open(`${globalUrl}/api/v1/workflows/search/${params.row.id}`, "_blank")
|
||||
}}
|
||||
disabled={!userdata.support}
|
||||
>
|
||||
<InsightsIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
@@ -632,6 +682,19 @@ const RuntimeDebugger = (props) => {
|
||||
</ButtonGroup>
|
||||
|
||||
: null}
|
||||
|
||||
{userdata.support === true ?
|
||||
<Button
|
||||
variant={ignoreOrg ? "contained" : "outlined"}
|
||||
color="primary"
|
||||
style={{maxHeight: 40, marginTop: 25, }}
|
||||
onClick={() => {
|
||||
setIgnoreOrg(!ignoreOrg)
|
||||
}}
|
||||
>
|
||||
{ignoreOrg ? "Ignoring Org" : "Ignore Org"}
|
||||
</Button>
|
||||
: null}
|
||||
</div>
|
||||
<form onSubmit={(e) => {
|
||||
submitSearch(workflowId, status, startTime, endTime, rowCursor, rowsPerPage)
|
||||
@@ -799,7 +862,7 @@ const RuntimeDebugger = (props) => {
|
||||
|
||||
</LocalizationProvider>
|
||||
<Button
|
||||
variant="contained"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
submitSearch(workflowId, status, startTime, endTime, rowCursor, rowsPerPage)
|
||||
|
||||
@@ -1043,16 +1043,16 @@ const AngularWorkflow = (defaultprops) => {
|
||||
execution_id: tmpView,
|
||||
//authorization: data.authorization,
|
||||
}
|
||||
setExecutionRunning(true);
|
||||
setExecutionModalView(1);
|
||||
setExecutionRequest(cur_execution);
|
||||
start();
|
||||
|
||||
//const newitem = removeParam("execution_id", cursearch);
|
||||
//navigate(curpath + newitem)
|
||||
|
||||
setTimeout(() => {
|
||||
stop()
|
||||
}, 5000);
|
||||
//setTimeout(() => {
|
||||
// stop()
|
||||
//}, 5000);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -15114,7 +15114,10 @@ const AngularWorkflow = (defaultprops) => {
|
||||
marginTop: "auto",
|
||||
marginBottom: "auto",
|
||||
}}
|
||||
onClick={() => { }}
|
||||
onClick={() => {
|
||||
setExecutionRunning(false);
|
||||
stop()
|
||||
}}
|
||||
>
|
||||
<ArrowBackIcon style={{ color: "rgba(255,255,255,0.5)" }} />
|
||||
</IconButton>
|
||||
@@ -15124,6 +15127,8 @@ const AngularWorkflow = (defaultprops) => {
|
||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||
const newitem = removeParam("execution_id", cursearch);
|
||||
navigate(curpath + newitem)
|
||||
setExecutionRunning(false);
|
||||
stop()
|
||||
}}
|
||||
>
|
||||
See more runs
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { toast } from 'react-toastify';
|
||||
import Markdown from 'react-markdown'
|
||||
|
||||
import { BrowserView, MobileView } from "react-device-detect";
|
||||
@@ -135,7 +136,7 @@ const Docs = (defaultprops) => {
|
||||
};
|
||||
|
||||
const fetchDocList = () => {
|
||||
fetch(globalUrl + "/api/v1/docs", {
|
||||
fetch(`${globalUrl}/api/v1/docs`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -147,9 +148,8 @@ const Docs = (defaultprops) => {
|
||||
if (responseJson.success) {
|
||||
setList(responseJson.list);
|
||||
} else {
|
||||
setList([
|
||||
"# Error loading documentation. Please contact us if this persists.",
|
||||
]);
|
||||
setList(["# Error loading documentation. Please contact us if this persists.",]);
|
||||
toast("Failed loading documentation. Please reload the window")
|
||||
}
|
||||
setListLoaded(true);
|
||||
})
|
||||
@@ -157,7 +157,7 @@ const Docs = (defaultprops) => {
|
||||
};
|
||||
|
||||
const fetchDocs = (docId) => {
|
||||
fetch(globalUrl + "/api/v1/docs/" + docId, {
|
||||
fetch(`${globalUrl}/api/v1/docs/${docId}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -166,6 +166,10 @@ const Docs = (defaultprops) => {
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success === false) {
|
||||
//toast("Failed loading documentation. Please reload the UI")
|
||||
}
|
||||
|
||||
if (responseJson.success && responseJson.reason !== undefined) {
|
||||
// Find <img> tags and translate them into ![]() format
|
||||
const imgRegex = /<img.*?src="(.*?)"/g;
|
||||
|
||||
Reference in New Issue
Block a user