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!
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

151 行
5.8KB

  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' && cr.priority === 0)
  25. return 'Cancelled';
  26. if (cr.state === 'Uncommitted' || !c || c.state === 'Queued' || c.state === 'Locked')
  27. return 'Pending';
  28. if (c.state === 'Running')
  29. return 'Running';
  30. if (c.state === 'Complete' && c.exit_code === 0)
  31. return 'Complete';
  32. if (c.state === 'Complete' && c.exit_code !== 0)
  33. return 'Failed';
  34. if (c.state === 'Cancelled')
  35. return 'Cancelled';
  36. }
  37. class WBProcessDashboard extends Component {
  38. constructor(...args) {
  39. super(...args);
  40. this.state.rows = Array(5).fill(Array(6).fill('-'));
  41. }
  42. fetchData() {
  43. const { app, parentProcessUuid } = this.props;
  44. const { arvHost, arvToken } = app.state;
  45. let prom = new Promise(accept => accept());
  46. if (parentProcessUuid) {
  47. prom = prom.then(() => {
  48. return makeArvadosRequest(arvHost, arvToken,
  49. '/arvados/v1/container_requests/' + encodeURIComponent(parentProcessUuid));
  50. });
  51. prom = prom.then(xhr => {
  52. const cr = xhr.response;
  53. if (!cr.container_uuid)
  54. return [];
  55. const filters = [ [ 'requesting_container_uuid', '=', cr.container_uuid ] ];
  56. return getAll(ofs =>
  57. makeArvadosRequest(arvHost, arvToken,
  58. '/arvados/v1/container_requests?filters=' +
  59. encodeURIComponent(JSON.stringify(filters)) +
  60. '&order=' + encodeURIComponent(JSON.stringify(['uuid asc'])) +
  61. '&offset=' + ofs));
  62. });
  63. } else {
  64. prom = prom.then(() => {
  65. return getAll(ofs => makeArvadosRequest(arvHost, arvToken,
  66. '/arvados/v1/container_requests?order=' +
  67. encodeURIComponent(JSON.stringify(['uuid asc'])) + '&offset=' + ofs));
  68. });
  69. }
  70. let crlist;
  71. prom = prom.then(crl => {
  72. crlist = crl;
  73. const uuids = crlist.map(a => a.container_uuid);
  74. // uuids = uuids.slice(0, 2);
  75. // crlist.map(a => ( crdict[a.uuid] = a));
  76. const filters = [ [ 'uuid', 'in', uuids ] ];
  77. return getAll(ofs => makeArvadosRequest(arvHost, arvToken,
  78. '/arvados/v1/containers?filters=' + encodeURIComponent(JSON.stringify(filters)) +
  79. '&order=' + encodeURIComponent(JSON.stringify([ 'uuid asc' ])) +
  80. '&offset=' + ofs));
  81. });
  82. prom = prom.then(cl => {
  83. cl.map(a => (crlist.find(b => (b.container_uuid === a.uuid)).container = a));
  84. crlist.map(a => (a.wb_state = determineState(a)));
  85. const stats = {};
  86. for (let state in { 'Pending': 1, 'Running': 1, 'Complete': 1, 'Failed': 1, 'Cancelled': 1 }) {
  87. const f = crlist.filter(a => (a.wb_state === state));
  88. stats[state] = { 'Count': f.length };
  89. if (state === 'Pending')
  90. f.map(a => (a.wb_wait_time = (new Date() - new Date(a.created_at)) / 3.6e6));
  91. else
  92. 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));
  93. f.sort((a, b) => (a.wb_wait_time - b.wb_wait_time));
  94. stats[state]['Shortest Wait Time'] = f.length ? (f[0].wb_wait_time.toFixed(2) + ' hours') : '-';
  95. stats[state]['Longest Wait Time'] = f.length ? (f[f.length - 1].wb_wait_time.toFixed(2) + ' hours') : '-';
  96. if (state === 'Pending')
  97. f.map(a => (a.wb_run_time = 0));
  98. else if (state === 'Running')
  99. f.map(a => (a.wb_run_time = (new Date() - new Date(a.container.started_at)) / 3.6e6));
  100. else
  101. 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));
  102. f.sort((a, b) => (a.wb_run_time - b.wb_run_time));
  103. stats[state]['Shortest Run Time'] = f.length ? (f[0].wb_run_time.toFixed(2) + ' hours') : '-';
  104. stats[state]['Longest Run Time'] = f.length ? (f[f.length - 1].wb_run_time.toFixed(2) + ' hours') : '-';
  105. }
  106. const rows = [];
  107. for (let st in { 'Count': 1, 'Shortest Wait Time': 1, 'Longest Wait Time': 1,
  108. 'Shortest Run Time': 1, 'Longest Run Time': 1}) {
  109. rows.push([st].concat(['Pending', 'Running', 'Complete', 'Failed', 'Cancelled'].map(a => stats[a][st])));
  110. }
  111. this.setState({ rows });
  112. });
  113. }
  114. componentDidMount() {
  115. if (!this.props.lazy)
  116. this.fetchData();
  117. }
  118. componentWillReceiveProps(nextProps) {
  119. if (nextProps.parentProcessUuid === this.props.parentProcessUuid)
  120. return;
  121. if (this.props.lazy) {
  122. this.setState({ rows: Array(5).fill(Array(6).fill('-')) });
  123. return;
  124. }
  125. this.props = nextProps;
  126. this.fetchData();
  127. }
  128. render({ lazy }, { rows }) {
  129. return (
  130. <div>
  131. <WBTable columns={ [ 'State', 'Pending', 'Running', 'Complete', 'Failed', 'Cancelled' ] }
  132. rows={ rows } verticalHeader={ true } />
  133. { lazy ? (
  134. <a href="#" onclick={ e => { e.preventDefault(); this.fetchData(); } }>Refresh</a>
  135. ) : null }
  136. </div>
  137. );
  138. }
  139. }
  140. export default WBProcessDashboard;