Skip to content

Commit e7028be

Browse files
committed
ui: use task state to determine if task is active (#14224)
The current implementation uses the task's finishedAt field to determine if a task is active of not, but this check is not accurate. A task in the "pending" state will not have finishedAt value but it's also not active. This discrepancy results in some components, like the inline stats chart of the task row component, to be displayed even whey they shouldn't.
1 parent 6da33f1 commit e7028be

File tree

6 files changed

+63
-17
lines changed

6 files changed

+63
-17
lines changed

.changelog/14224.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:bug
2+
ui: Fixed a bug that caused the allocation details page to display the stats bar chart even if the task was pending.
3+
```

ui/app/models/task-state.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { computed } from '@ember/object';
2-
import { alias, none, and } from '@ember/object/computed';
2+
import { alias, and } from '@ember/object/computed';
33
import Fragment from 'ember-data-model-fragments/fragment';
44
import { attr } from '@ember-data/model';
55
import { fragment, fragmentOwner, fragmentArray } from 'ember-data-model-fragments/attributes';
@@ -15,7 +15,6 @@ export default class TaskState extends Fragment {
1515
@attr('date') finishedAt;
1616
@attr('boolean') failed;
1717

18-
@none('finishedAt') isActive;
1918
@and('isActive', 'allocation.isRunning') isRunning;
2019

2120
@computed('task.kind')
@@ -54,6 +53,11 @@ export default class TaskState extends Fragment {
5453
return classMap[this.state] || 'is-dark';
5554
}
5655

56+
@computed('state')
57+
get isActive() {
58+
return this.state === 'running';
59+
}
60+
5761
restart() {
5862
return this.allocation.restart(this.name);
5963
}

ui/tests/acceptance/allocation-detail-test.js

+39-10
Original file line numberDiff line numberDiff line change
@@ -122,22 +122,45 @@ module('Acceptance | allocation detail', function(hooks) {
122122
});
123123

124124
test('each task row should list high-level information for the task', async function(assert) {
125-
const task = server.db.taskStates.where({ allocationId: allocation.id }).sortBy('name')[0];
126-
const events = server.db.taskEvents.where({ taskStateId: task.id });
127-
const event = events[events.length - 1];
125+
const job = server.create('job', {
126+
groupsCount: 1,
127+
groupTaskCount: 3,
128+
withGroupServices: true,
129+
createAllocations: false,
130+
});
131+
132+
const allocation = server.create('allocation', 'withTaskWithPorts', {
133+
clientStatus: 'running',
134+
jobId: job.id,
135+
});
128136

129137
const taskGroup = server.schema.taskGroups.where({
130138
jobId: allocation.jobId,
131139
name: allocation.taskGroup,
132140
}).models[0];
133141

134-
const jobTask = taskGroup.tasks.models.find(m => m.name === task.name);
135-
const volumes = jobTask.volumeMounts.map(volume => ({
136-
name: volume.Volume,
137-
source: taskGroup.volumes[volume.Volume].Source,
138-
}));
142+
// Set the expected task states.
143+
const states = ['running', 'pending', 'dead'];
144+
server.db.taskStates
145+
.where({ allocationId: allocation.id })
146+
.sortBy('name')
147+
.forEach((task, i) => {
148+
server.db.taskStates.update(task.id, { state: states[i] });
149+
});
150+
151+
await Allocation.visit({ id: allocation.id });
152+
153+
Allocation.tasks.forEach((taskRow, i) => {
154+
const task = server.db.taskStates.where({ allocationId: allocation.id }).sortBy('name')[i];
155+
const events = server.db.taskEvents.where({ taskStateId: task.id });
156+
const event = events[events.length - 1];
157+
158+
const jobTask = taskGroup.tasks.models.find(m => m.name === task.name);
159+
const volumes = jobTask.volumeMounts.map(volume => ({
160+
name: volume.Volume,
161+
source: taskGroup.volumes[volume.Volume].Source,
162+
}));
139163

140-
Allocation.tasks[0].as(taskRow => {
141164
assert.equal(taskRow.name, task.name, 'Name');
142165
assert.equal(taskRow.state, task.state, 'State');
143166
assert.equal(taskRow.message, event.displayMessage, 'Event Message');
@@ -147,6 +170,10 @@ module('Acceptance | allocation detail', function(hooks) {
147170
'Event Time'
148171
);
149172

173+
const expectStats = task.state === 'running';
174+
assert.equal(taskRow.hasCpuMetrics, expectStats, 'CPU metrics');
175+
assert.equal(taskRow.hasMemoryMetrics, expectStats, 'Memory metrics');
176+
150177
const volumesText = taskRow.volumes;
151178
volumes.forEach(volume => {
152179
assert.ok(volumesText.includes(volume.name), `Found label ${volume.name}`);
@@ -271,7 +298,9 @@ module('Acceptance | allocation detail', function(hooks) {
271298
await Allocation.stop.confirm();
272299

273300
assert.equal(
274-
server.pretender.handledRequests.reject(request => request.url.includes('fuzzy')).findBy('method', 'POST').url,
301+
server.pretender.handledRequests
302+
.reject(request => request.url.includes('fuzzy'))
303+
.findBy('method', 'POST').url,
275304
`/v1/allocation/${allocation.id}/stop`,
276305
'Stop request is made for the allocation'
277306
);

ui/tests/acceptance/exec-test.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ module('Acceptance | exec', function(hooks) {
2626
});
2727

2828
this.job.taskGroups.models.forEach(taskGroup => {
29-
server.create('allocation', {
29+
const alloc = server.create('allocation', {
3030
jobId: this.job.id,
3131
taskGroup: taskGroup.name,
3232
forceRunningClientStatus: true,
3333
});
34+
server.db.taskStates.update({ allocationId: alloc.id }, { state: 'running' });
3435
});
3536
});
3637

@@ -127,9 +128,11 @@ module('Acceptance | exec', function(hooks) {
127128

128129
let runningTaskGroup = this.job.taskGroups.models.sortBy('name')[1];
129130
runningTaskGroup.tasks.models.forEach((task, index) => {
131+
let state = 'running';
130132
if (index > 0) {
131-
this.server.db.taskStates.update({ name: task.name }, { finishedAt: new Date() });
133+
state = 'dead';
132134
}
135+
this.server.db.taskStates.update({ name: task.name }, { state });
133136
});
134137

135138
await Exec.visitJob({ job: this.job.id });
@@ -148,9 +151,11 @@ module('Acceptance | exec', function(hooks) {
148151
let runningTaskGroup = this.job.taskGroups.models.sortBy('name')[1];
149152
let changingTaskStateName;
150153
runningTaskGroup.tasks.models.sortBy('name').forEach((task, index) => {
154+
let state = 'running';
151155
if (index > 0) {
152-
this.server.db.taskStates.update({ name: task.name }, { finishedAt: new Date() });
156+
state = 'dead';
153157
}
158+
this.server.db.taskStates.update({ name: task.name }, { state });
154159

155160
if (index === 1) {
156161
changingTaskStateName = task.name;
@@ -170,7 +175,7 @@ module('Acceptance | exec', function(hooks) {
170175
const changingTaskState = allocation.states.findBy('name', changingTaskStateName);
171176

172177
if (changingTaskState) {
173-
changingTaskState.set('finishedAt', undefined);
178+
changingTaskState.set('state', 'running');
174179
}
175180
});
176181

ui/tests/acceptance/task-detail-test.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ module('Acceptance | task detail', function(hooks) {
1818
server.create('agent');
1919
server.create('node');
2020
server.create('job', { createAllocations: false });
21-
allocation = server.create('allocation', 'withTaskWithPorts', { clientStatus: 'running' });
21+
allocation = server.create('allocation', 'withTaskWithPorts', {
22+
clientStatus: 'running',
23+
});
24+
server.db.taskStates.update({ allocationId: allocation.id }, { state: 'running' });
2225
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
2326

2427
await Task.visit({ id: allocation.id, name: task.name });

ui/tests/pages/allocations/detail.js

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ export default create({
5050
time: text('[data-test-time]'),
5151
volumes: text('[data-test-volumes]'),
5252

53+
hasCpuMetrics: isPresent('[data-test-cpu] .inline-chart progress'),
54+
hasMemoryMetrics: isPresent('[data-test-mem] .inline-chart progress'),
5355
hasUnhealthyDriver: isPresent('[data-test-icon="unhealthy-driver"]'),
5456
hasProxyTag: isPresent('[data-test-proxy-tag]'),
5557

0 commit comments

Comments
 (0)