// // Copyright (C) Stanislaw Adaszewski, 2020 // Contact: s.adaszewski@gmail.com // Website: https://adared.ch/wba // License: GNU Affero General Public License, Version 3 // import { h, Component } from 'preact'; import WBTable from 'wb-table'; import makeArvadosRequest from 'make-arvados-request'; import wbProcessStateName from 'wb-process-state-name'; function getAll(makeRequest) { let prom = makeRequest(0); prom = prom.then(xhr => { const { items, limit, items_available } = xhr.response; let res = [].concat(items); let prom_1 = new Promise(accept => accept()); for (let ofs = limit; ofs < items_available; ofs += limit) { prom_1 = prom_1.then(() => makeRequest(ofs)); prom_1 = prom_1.then(xhr_1 => { res = res.concat(xhr_1.response.items); }); } prom_1 = prom_1.then(() => res); return prom_1; }); return prom; } class WBProcessDashboard extends Component { constructor(...args) { super(...args); this.state.rows = Array(5).fill(Array(6).fill('-')); } fetchData() { const { app, parentProcessUuid } = this.props; const { arvHost, arvToken } = app.state; let prom = new Promise(accept => accept()); if (parentProcessUuid) { prom = prom.then(() => { return makeArvadosRequest(arvHost, arvToken, '/arvados/v1/container_requests/' + encodeURIComponent(parentProcessUuid)); }); prom = prom.then(xhr => { const cr = xhr.response; 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(JSON.stringify(['uuid asc'])) + '&offset=' + ofs)); }); } else { prom = prom.then(() => { return getAll(ofs => makeArvadosRequest(arvHost, arvToken, '/arvados/v1/container_requests?order=' + encodeURIComponent(JSON.stringify(['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)) + '&order=' + encodeURIComponent(JSON.stringify([ 'uuid asc' ])) + '&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 = wbProcessStateName(a, a.container))); 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 = Math.max(0, (a.container ? new Date(a.container.started_at) : new Date(0)) - 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, a.container ? new Date(a.container.finished_at) - new Date(a.container.started_at) : 0) / 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() { if (!this.props.lazy) this.fetchData(); } componentWillReceiveProps(nextProps) { if (nextProps.parentProcessUuid === this.props.parentProcessUuid) return; if (this.props.lazy) { this.setState({ rows: Array(5).fill(Array(6).fill('-')) }); return; } this.props = nextProps; this.fetchData(); } render({ lazy }, { rows }) { return (
{ lazy ? ( { e.preventDefault(); this.fetchData(); } }>Refresh ) : null }
); } } export default WBProcessDashboard;