|
|
@@ -1,4 +1,5 @@ |
|
|
|
import { h, Component } from 'preact';
|
|
|
|
import WBTable from 'wb-table';
|
|
|
|
import makeArvadosRequest from 'make-arvados-request';
|
|
|
|
|
|
|
|
function getAll(makeRequest) {
|
|
|
@@ -19,38 +20,114 @@ function getAll(makeRequest) { |
|
|
|
return prom;
|
|
|
|
}
|
|
|
|
|
|
|
|
function determineState(containerRequest) {
|
|
|
|
const cr = containerRequest;
|
|
|
|
const c = cr.container;
|
|
|
|
if (cr.state === 'Uncommitted' || !c || c.state === 'Queued' || c.state === 'Locked')
|
|
|
|
return 'Pending';
|
|
|
|
if (c.state === 'Running')
|
|
|
|
return 'Running';
|
|
|
|
if (c.state === 'Complete' && c.exit_code === 0)
|
|
|
|
return 'Complete';
|
|
|
|
if (c.state === 'Complete' && c.exit_code !== 0)
|
|
|
|
return 'Failed';
|
|
|
|
if (c.state === 'Cancelled')
|
|
|
|
return 'Cancelled';
|
|
|
|
}
|
|
|
|
|
|
|
|
class WBProcessDashboard extends Component {
|
|
|
|
constructor(...args) {
|
|
|
|
super(...args);
|
|
|
|
this.state.rows = Array(5).fill(Array(6).fill('-'));
|
|
|
|
}
|
|
|
|
|
|
|
|
fetchData() {
|
|
|
|
const { app, uuid } = this.props;
|
|
|
|
const { app, parentProcessUuid } = this.props;
|
|
|
|
const { arvHost, arvToken } = app.state;
|
|
|
|
let prom = new Promise(accept => accept());
|
|
|
|
if (uuid) {
|
|
|
|
if (parentProcessUuid) {
|
|
|
|
prom = prom.then(() => {
|
|
|
|
return makeArvadosRequest(arvHost, arvToken,
|
|
|
|
'/arvados/v1/container_requests/' + encodeURIComponent(uuid));
|
|
|
|
'/arvados/v1/container_requests/' + encodeURIComponent(parentProcessUuid));
|
|
|
|
});
|
|
|
|
prom = prom.then(xhr => {
|
|
|
|
const cr = xhr.response;
|
|
|
|
return makeArvadosRequest(arvHost, arvToken,
|
|
|
|
'/arvados/v1/containers/' + encodeURIComponent(cr.container_uuid));
|
|
|
|
});
|
|
|
|
prom = prom.then(xhr => {
|
|
|
|
const c = xhr.response;
|
|
|
|
const filters = [ [ 'requesting_container_uuid', '=', c.uuid ] ];
|
|
|
|
return makeArvadosRequest(arvHost, arvToken,
|
|
|
|
'/arvados/v1/container_requests?filters=' +
|
|
|
|
encodeURIComponent(JSON.stringify(filters)));
|
|
|
|
if (!cr.container_uuid)
|
|
|
|
return [];
|
|
|
|
const filters = [ [ 'requesting_container_uuid', '=', cr.container_uuid ] ];
|
|
|
|
return getAll(ofs =>
|
|
|
|
makeArvadosRequest(arvHost, arvToken,
|
|
|
|
'/arvados/v1/container_requests?filters=' +
|
|
|
|
encodeURIComponent(JSON.stringify(filters)) +
|
|
|
|
'&order=' + encodeURIComponent(['uuid asc']) +
|
|
|
|
'&offset=' + ofs));
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
prom = prom.then(() => {
|
|
|
|
return makeArvadosRequest(arvHost, arvToken,
|
|
|
|
'/arvados/v1/container_requests');
|
|
|
|
return getAll(ofs => makeArvadosRequest(arvHost, arvToken,
|
|
|
|
'/arvados/v1/container_requests?order=' +
|
|
|
|
encodeURIComponent(['uuid asc']) + '&offset=' + ofs));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
let crlist;
|
|
|
|
prom = prom.then(crl => {
|
|
|
|
crlist = crl;
|
|
|
|
const uuids = crlist.map(a => a.container_uuid);
|
|
|
|
// uuids = uuids.slice(0, 2);
|
|
|
|
// crlist.map(a => ( crdict[a.uuid] = a));
|
|
|
|
const filters = [ [ 'uuid', 'in', uuids ] ];
|
|
|
|
return getAll(ofs => makeArvadosRequest(arvHost, arvToken,
|
|
|
|
'/arvados/v1/containers?filters=' + encodeURIComponent(JSON.stringify(filters)) +
|
|
|
|
'&offset=' + ofs));
|
|
|
|
});
|
|
|
|
prom = prom.then(cl => {
|
|
|
|
cl.map(a => (crlist.find(b => (b.container_uuid === a.uuid)).container = a));
|
|
|
|
crlist.map(a => (a.wb_state = determineState(a)));
|
|
|
|
const stats = {};
|
|
|
|
for (let state in { 'Pending': 1, 'Running': 1, 'Complete': 1, 'Failed': 1, 'Cancelled': 1 }) {
|
|
|
|
const f = crlist.filter(a => (a.wb_state === state));
|
|
|
|
stats[state] = { 'Count': f.length };
|
|
|
|
if (state === 'Pending')
|
|
|
|
f.map(a => (a.wb_wait_time = (new Date() - new Date(a.created_at)) / 3.6e6));
|
|
|
|
else
|
|
|
|
f.map(a => (a.wb_wait_time = (new Date(a.container.started_at) - new Date(a.created_at)) / 3.6e6));
|
|
|
|
f.sort((a, b) => (a.wb_wait_time - b.wb_wait_time));
|
|
|
|
stats[state]['Shortest Wait Time'] = f.length ? (f[0].wb_wait_time.toFixed(2) + ' hours') : '-';
|
|
|
|
stats[state]['Longest Wait Time'] = f.length ? (f[f.length - 1].wb_wait_time.toFixed(2) + ' hours') : '-';
|
|
|
|
if (state === 'Pending')
|
|
|
|
f.map(a => (a.wb_run_time = 0));
|
|
|
|
else if (state === 'Running')
|
|
|
|
f.map(a => (a.wb_run_time = (new Date() - new Date(a.container.started_at)) / 3.6e6));
|
|
|
|
else
|
|
|
|
f.map(a => (a.wb_run_time = Math.max(0, new Date(a.container.finished_at) - new Date(a.container.started_at)) / 3.6e6));
|
|
|
|
f.sort((a, b) => (a.wb_run_time - b.wb_run_time));
|
|
|
|
stats[state]['Shortest Run Time'] = f.length ? (f[0].wb_run_time.toFixed(2) + ' hours') : '-';
|
|
|
|
stats[state]['Longest Run Time'] = f.length ? (f[f.length - 1].wb_run_time.toFixed(2) + ' hours') : '-';
|
|
|
|
}
|
|
|
|
const rows = [];
|
|
|
|
for (let st in { 'Count': 1, 'Shortest Wait Time': 1, 'Longest Wait Time': 1,
|
|
|
|
'Shortest Run Time': 1, 'Longest Run Time': 1}) {
|
|
|
|
rows.push([st].concat(['Pending', 'Running', 'Complete', 'Failed', 'Cancelled'].map(a => stats[a][st])));
|
|
|
|
}
|
|
|
|
this.setState({ rows });
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
this.fetchData();
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
/* componentWillReceiveProps(nextProps) {
|
|
|
|
this.props = nextProps;
|
|
|
|
fetchData();
|
|
|
|
} */
|
|
|
|
|
|
|
|
render({}, { rows }) {
|
|
|
|
return (
|
|
|
|
<WBTable columns={ [ '', 'Pending', 'Running', 'Complete', 'Failed', 'Cancelled' ] }
|
|
|
|
rows={ rows } verticalHeader={ true } />
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default WBProcessDashboard;
|