github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/app/components/allocation-row.js (about) 1 import Ember from 'ember'; 2 import { inject as service } from '@ember/service'; 3 import Component from '@ember/component'; 4 import { computed } from '@ember/object'; 5 import { computed as overridable } from 'ember-overridable-computed'; 6 import { alias } from '@ember/object/computed'; 7 import { scheduleOnce } from '@ember/runloop'; 8 import { task, timeout } from 'ember-concurrency'; 9 import { lazyClick } from '../helpers/lazy-click'; 10 import AllocationStatsTracker from 'nomad-ui/utils/classes/allocation-stats-tracker'; 11 import classic from 'ember-classic-decorator'; 12 import { 13 classNames, 14 tagName, 15 attributeBindings, 16 } from '@ember-decorators/component'; 17 18 @classic 19 @tagName('tr') 20 @classNames('allocation-row', 'is-interactive') 21 @attributeBindings( 22 'data-test-allocation', 23 'data-test-write-allocation', 24 'data-test-read-allocation' 25 ) 26 export default class AllocationRow extends Component { 27 @service store; 28 @service token; 29 30 allocation = null; 31 32 // Used to determine whether the row should mention the node or the job 33 context = null; 34 35 // Internal state 36 statsError = false; 37 38 @overridable(() => !Ember.testing) enablePolling; 39 40 @computed('allocation', 'allocation.isRunning') 41 get stats() { 42 if (!this.get('allocation.isRunning')) return undefined; 43 44 return AllocationStatsTracker.create({ 45 fetch: (url) => this.token.authorizedRequest(url), 46 allocation: this.allocation, 47 }); 48 } 49 50 @alias('stats.cpu.lastObject') cpu; 51 @alias('stats.memory.lastObject') memory; 52 53 onClick() {} 54 55 click(event) { 56 lazyClick([this.onClick, event]); 57 } 58 59 didReceiveAttrs() { 60 super.didReceiveAttrs(); 61 this.updateStatsTracker(); 62 } 63 64 updateStatsTracker() { 65 const allocation = this.allocation; 66 67 if (allocation) { 68 scheduleOnce('afterRender', this, qualifyAllocation); 69 } else { 70 this.fetchStats.cancelAll(); 71 } 72 } 73 74 @(task(function* () { 75 do { 76 if (this.stats) { 77 try { 78 yield this.get('stats.poll').linked().perform(); 79 this.set('statsError', false); 80 } catch (error) { 81 this.set('statsError', true); 82 } 83 } 84 85 yield timeout(500); 86 } while (this.enablePolling); 87 }).drop()) 88 fetchStats; 89 } 90 91 async function qualifyAllocation() { 92 const allocation = this.allocation; 93 94 // Make sure the allocation is a complete record and not a partial so we 95 // can show information such as preemptions and rescheduled allocation. 96 if (allocation.isPartial) { 97 await this.store.findRecord('allocation', allocation.id, { 98 backgroundReload: false, 99 }); 100 } 101 102 if (allocation.get('job.isPending')) { 103 // Make sure the job is loaded before starting the stats tracker 104 await allocation.get('job'); 105 } else if (!allocation.get('taskGroup')) { 106 // Make sure that the job record in the store for this allocation 107 // is complete and not a partial from the list endpoint 108 const job = allocation.get('job.content'); 109 if (job.isPartial) await job.reload(); 110 } 111 112 this.fetchStats.perform(); 113 }