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