IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
5.1KB

  1. import { h, Component } from 'preact';
  2. import WBTable from 'wb-table';
  3. import makeArvadosRequest from 'make-arvados-request';
  4. function getAll(makeRequest) {
  5. let prom = makeRequest(0);
  6. prom = prom.then(xhr => {
  7. const { items, limit, items_available } = xhr.response;
  8. let res = [].concat(items);
  9. let prom_1 = new Promise(accept => accept());
  10. for (let ofs = limit; ofs < items_available; ofs += limit) {
  11. prom_1 = prom_1.then(() => makeRequest(ofs));
  12. prom_1 = prom_1.then(xhr_1 => {
  13. res = res.concat(xhr_1.response.items);
  14. });
  15. }
  16. prom_1 = prom_1.then(() => res);
  17. return prom_1;
  18. });
  19. return prom;
  20. }
  21. function determineState(containerRequest) {
  22. const cr = containerRequest;
  23. const c = cr.container;
  24. if (cr.state === 'Uncommitted' || !c || c.state === 'Queued' || c.state === 'Locked')
  25. return 'Pending';
  26. if (c.state === 'Running')
  27. return 'Running';
  28. if (c.state === 'Complete' && c.exit_code === 0)
  29. return 'Complete';
  30. if (c.state === 'Complete' && c.exit_code !== 0)
  31. return 'Failed';
  32. if (c.state === 'Cancelled')
  33. return 'Cancelled';
  34. }
  35. class WBProcessDashboard extends Component {
  36. constructor(...args) {
  37. super(...args);
  38. this.state.rows = Array(5).fill(Array(6).fill('-'));
  39. }
  40. fetchData() {
  41. const { app, parentProcessUuid } = this.props;
  42. const { arvHost, arvToken } = app.state;
  43. let prom = new Promise(accept => accept());
  44. if (parentProcessUuid) {
  45. prom = prom.then(() => {
  46. return makeArvadosRequest(arvHost, arvToken,
  47. '/arvados/v1/container_requests/' + encodeURIComponent(parentProcessUuid));
  48. });
  49. prom = prom.then(xhr => {
  50. const cr = xhr.response;
  51. if (!cr.container_uuid)
  52. return [];
  53. const filters = [ [ 'requesting_container_uuid', '=', cr.container_uuid ] ];
  54. return getAll(ofs =>
  55. makeArvadosRequest(arvHost, arvToken,
  56. '/arvados/v1/container_requests?filters=' +
  57. encodeURIComponent(JSON.stringify(filters)) +
  58. '&order=' + encodeURIComponent(['uuid asc']) +
  59. '&offset=' + ofs));
  60. });
  61. } else {
  62. prom = prom.then(() => {
  63. return getAll(ofs => makeArvadosRequest(arvHost, arvToken,
  64. '/arvados/v1/container_requests?order=' +
  65. encodeURIComponent(['uuid asc']) + '&offset=' + ofs));
  66. });
  67. }
  68. let crlist;
  69. prom = prom.then(crl => {
  70. crlist = crl;
  71. const uuids = crlist.map(a => a.container_uuid);
  72. // uuids = uuids.slice(0, 2);
  73. // crlist.map(a => ( crdict[a.uuid] = a));
  74. const filters = [ [ 'uuid', 'in', uuids ] ];
  75. return getAll(ofs => makeArvadosRequest(arvHost, arvToken,
  76. '/arvados/v1/containers?filters=' + encodeURIComponent(JSON.stringify(filters)) +
  77. '&offset=' + ofs));
  78. });
  79. prom = prom.then(cl => {
  80. cl.map(a => (crlist.find(b => (b.container_uuid === a.uuid)).container = a));
  81. crlist.map(a => (a.wb_state = determineState(a)));
  82. const stats = {};
  83. for (let state in { 'Pending': 1, 'Running': 1, 'Complete': 1, 'Failed': 1, 'Cancelled': 1 }) {
  84. const f = crlist.filter(a => (a.wb_state === state));
  85. stats[state] = { 'Count': f.length };
  86. if (state === 'Pending')
  87. f.map(a => (a.wb_wait_time = (new Date() - new Date(a.created_at)) / 3.6e6));
  88. else
  89. f.map(a => (a.wb_wait_time = (new Date(a.container.started_at) - new Date(a.created_at)) / 3.6e6));
  90. f.sort((a, b) => (a.wb_wait_time - b.wb_wait_time));
  91. stats[state]['Shortest Wait Time'] = f.length ? (f[0].wb_wait_time.toFixed(2) + ' hours') : '-';
  92. stats[state]['Longest Wait Time'] = f.length ? (f[f.length - 1].wb_wait_time.toFixed(2) + ' hours') : '-';
  93. if (state === 'Pending')
  94. f.map(a => (a.wb_run_time = 0));
  95. else if (state === 'Running')
  96. f.map(a => (a.wb_run_time = (new Date() - new Date(a.container.started_at)) / 3.6e6));
  97. else
  98. f.map(a => (a.wb_run_time = Math.max(0, new Date(a.container.finished_at) - new Date(a.container.started_at)) / 3.6e6));
  99. f.sort((a, b) => (a.wb_run_time - b.wb_run_time));
  100. stats[state]['Shortest Run Time'] = f.length ? (f[0].wb_run_time.toFixed(2) + ' hours') : '-';
  101. stats[state]['Longest Run Time'] = f.length ? (f[f.length - 1].wb_run_time.toFixed(2) + ' hours') : '-';
  102. }
  103. const rows = [];
  104. for (let st in { 'Count': 1, 'Shortest Wait Time': 1, 'Longest Wait Time': 1,
  105. 'Shortest Run Time': 1, 'Longest Run Time': 1}) {
  106. rows.push([st].concat(['Pending', 'Running', 'Complete', 'Failed', 'Cancelled'].map(a => stats[a][st])));
  107. }
  108. this.setState({ rows });
  109. });
  110. }
  111. componentDidMount() {
  112. this.fetchData();
  113. }
  114. /* componentWillReceiveProps(nextProps) {
  115. this.props = nextProps;
  116. fetchData();
  117. } */
  118. render({}, { rows }) {
  119. return (
  120. <WBTable columns={ [ '', 'Pending', 'Running', 'Complete', 'Failed', 'Cancelled' ] }
  121. rows={ rows } verticalHeader={ true } />
  122. );
  123. }
  124. }
  125. export default WBProcessDashboard;