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.
This commit is contained in:
parent
d3be0abf61
commit
af5c01a070
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
ui: Fixed a bug that caused the allocation details page to display the stats bar chart even if the task was pending.
|
||||||
|
```
|
|
@ -1,5 +1,5 @@
|
||||||
import { computed } from '@ember/object';
|
import { computed } from '@ember/object';
|
||||||
import { alias, none, and } from '@ember/object/computed';
|
import { alias, and } from '@ember/object/computed';
|
||||||
import Fragment from 'ember-data-model-fragments/fragment';
|
import Fragment from 'ember-data-model-fragments/fragment';
|
||||||
import { attr } from '@ember-data/model';
|
import { attr } from '@ember-data/model';
|
||||||
import {
|
import {
|
||||||
|
@ -19,7 +19,6 @@ export default class TaskState extends Fragment {
|
||||||
@attr('date') finishedAt;
|
@attr('date') finishedAt;
|
||||||
@attr('boolean') failed;
|
@attr('boolean') failed;
|
||||||
|
|
||||||
@none('finishedAt') isActive;
|
|
||||||
@and('isActive', 'allocation.isRunning') isRunning;
|
@and('isActive', 'allocation.isRunning') isRunning;
|
||||||
|
|
||||||
@computed('task.kind')
|
@computed('task.kind')
|
||||||
|
@ -58,6 +57,11 @@ export default class TaskState extends Fragment {
|
||||||
return classMap[this.state] || 'is-dark';
|
return classMap[this.state] || 'is-dark';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed('state')
|
||||||
|
get isActive() {
|
||||||
|
return this.state === 'running';
|
||||||
|
}
|
||||||
|
|
||||||
restart() {
|
restart() {
|
||||||
return this.allocation.restart(this.name);
|
return this.allocation.restart(this.name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,24 +158,47 @@ module('Acceptance | allocation detail', function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('each task row should list high-level information for the task', async function (assert) {
|
test('each task row should list high-level information for the task', async function (assert) {
|
||||||
const task = server.db.taskStates
|
const job = server.create('job', {
|
||||||
.where({ allocationId: allocation.id })
|
groupsCount: 1,
|
||||||
.sortBy('name')[0];
|
groupTaskCount: 3,
|
||||||
const events = server.db.taskEvents.where({ taskStateId: task.id });
|
withGroupServices: true,
|
||||||
const event = events[events.length - 1];
|
createAllocations: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const allocation = server.create('allocation', 'withTaskWithPorts', {
|
||||||
|
clientStatus: 'running',
|
||||||
|
jobId: job.id,
|
||||||
|
});
|
||||||
|
|
||||||
const taskGroup = server.schema.taskGroups.where({
|
const taskGroup = server.schema.taskGroups.where({
|
||||||
jobId: allocation.jobId,
|
jobId: allocation.jobId,
|
||||||
name: allocation.taskGroup,
|
name: allocation.taskGroup,
|
||||||
}).models[0];
|
}).models[0];
|
||||||
|
|
||||||
|
// Set the expected task states.
|
||||||
|
const states = ['running', 'pending', 'dead'];
|
||||||
|
server.db.taskStates
|
||||||
|
.where({ allocationId: allocation.id })
|
||||||
|
.sortBy('name')
|
||||||
|
.forEach((task, i) => {
|
||||||
|
server.db.taskStates.update(task.id, { state: states[i] });
|
||||||
|
});
|
||||||
|
|
||||||
|
await Allocation.visit({ id: allocation.id });
|
||||||
|
|
||||||
|
Allocation.tasks.forEach((taskRow, i) => {
|
||||||
|
const task = server.db.taskStates
|
||||||
|
.where({ allocationId: allocation.id })
|
||||||
|
.sortBy('name')[i];
|
||||||
|
const events = server.db.taskEvents.where({ taskStateId: task.id });
|
||||||
|
const event = events[events.length - 1];
|
||||||
|
|
||||||
const jobTask = taskGroup.tasks.models.find((m) => m.name === task.name);
|
const jobTask = taskGroup.tasks.models.find((m) => m.name === task.name);
|
||||||
const volumes = jobTask.volumeMounts.map((volume) => ({
|
const volumes = jobTask.volumeMounts.map((volume) => ({
|
||||||
name: volume.Volume,
|
name: volume.Volume,
|
||||||
source: taskGroup.volumes[volume.Volume].Source,
|
source: taskGroup.volumes[volume.Volume].Source,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Allocation.tasks[0].as((taskRow) => {
|
|
||||||
assert.equal(taskRow.name, task.name, 'Name');
|
assert.equal(taskRow.name, task.name, 'Name');
|
||||||
assert.equal(taskRow.state, task.state, 'State');
|
assert.equal(taskRow.state, task.state, 'State');
|
||||||
assert.equal(taskRow.message, event.displayMessage, 'Event Message');
|
assert.equal(taskRow.message, event.displayMessage, 'Event Message');
|
||||||
|
@ -185,6 +208,10 @@ module('Acceptance | allocation detail', function (hooks) {
|
||||||
'Event Time'
|
'Event Time'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const expectStats = task.state === 'running';
|
||||||
|
assert.equal(taskRow.hasCpuMetrics, expectStats, 'CPU metrics');
|
||||||
|
assert.equal(taskRow.hasMemoryMetrics, expectStats, 'Memory metrics');
|
||||||
|
|
||||||
const volumesText = taskRow.volumes;
|
const volumesText = taskRow.volumes;
|
||||||
volumes.forEach((volume) => {
|
volumes.forEach((volume) => {
|
||||||
assert.ok(
|
assert.ok(
|
||||||
|
|
|
@ -27,11 +27,15 @@ module('Acceptance | exec', function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.job.taskGroups.models.forEach((taskGroup) => {
|
this.job.taskGroups.models.forEach((taskGroup) => {
|
||||||
server.create('allocation', {
|
const alloc = server.create('allocation', {
|
||||||
jobId: this.job.id,
|
jobId: this.job.id,
|
||||||
taskGroup: taskGroup.name,
|
taskGroup: taskGroup.name,
|
||||||
forceRunningClientStatus: true,
|
forceRunningClientStatus: true,
|
||||||
});
|
});
|
||||||
|
server.db.taskStates.update(
|
||||||
|
{ allocationId: alloc.id },
|
||||||
|
{ state: 'running' }
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -135,12 +139,11 @@ module('Acceptance | exec', function (hooks) {
|
||||||
|
|
||||||
let runningTaskGroup = this.job.taskGroups.models.sortBy('name')[1];
|
let runningTaskGroup = this.job.taskGroups.models.sortBy('name')[1];
|
||||||
runningTaskGroup.tasks.models.forEach((task, index) => {
|
runningTaskGroup.tasks.models.forEach((task, index) => {
|
||||||
|
let state = 'running';
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
this.server.db.taskStates.update(
|
state = 'dead';
|
||||||
{ name: task.name },
|
|
||||||
{ finishedAt: new Date() }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
this.server.db.taskStates.update({ name: task.name }, { state });
|
||||||
});
|
});
|
||||||
|
|
||||||
await Exec.visitJob({ job: this.job.id });
|
await Exec.visitJob({ job: this.job.id });
|
||||||
|
@ -159,12 +162,11 @@ module('Acceptance | exec', function (hooks) {
|
||||||
let runningTaskGroup = this.job.taskGroups.models.sortBy('name')[1];
|
let runningTaskGroup = this.job.taskGroups.models.sortBy('name')[1];
|
||||||
let changingTaskStateName;
|
let changingTaskStateName;
|
||||||
runningTaskGroup.tasks.models.sortBy('name').forEach((task, index) => {
|
runningTaskGroup.tasks.models.sortBy('name').forEach((task, index) => {
|
||||||
|
let state = 'running';
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
this.server.db.taskStates.update(
|
state = 'dead';
|
||||||
{ name: task.name },
|
|
||||||
{ finishedAt: new Date() }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
this.server.db.taskStates.update({ name: task.name }, { state });
|
||||||
|
|
||||||
if (index === 1) {
|
if (index === 1) {
|
||||||
changingTaskStateName = task.name;
|
changingTaskStateName = task.name;
|
||||||
|
@ -187,7 +189,7 @@ module('Acceptance | exec', function (hooks) {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (changingTaskState) {
|
if (changingTaskState) {
|
||||||
changingTaskState.set('finishedAt', undefined);
|
changingTaskState.set('state', 'running');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,10 @@ module('Acceptance | task detail', function (hooks) {
|
||||||
allocation = server.create('allocation', 'withTaskWithPorts', {
|
allocation = server.create('allocation', 'withTaskWithPorts', {
|
||||||
clientStatus: 'running',
|
clientStatus: 'running',
|
||||||
});
|
});
|
||||||
|
server.db.taskStates.update(
|
||||||
|
{ allocationId: allocation.id },
|
||||||
|
{ state: 'running' }
|
||||||
|
);
|
||||||
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
|
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
|
||||||
|
|
||||||
await Task.visit({ id: allocation.id, name: task.name });
|
await Task.visit({ id: allocation.id, name: task.name });
|
||||||
|
|
|
@ -50,6 +50,8 @@ export default create({
|
||||||
time: text('[data-test-time]'),
|
time: text('[data-test-time]'),
|
||||||
volumes: text('[data-test-volumes]'),
|
volumes: text('[data-test-volumes]'),
|
||||||
|
|
||||||
|
hasCpuMetrics: isPresent('[data-test-cpu] .inline-chart progress'),
|
||||||
|
hasMemoryMetrics: isPresent('[data-test-mem] .inline-chart progress'),
|
||||||
hasUnhealthyDriver: isPresent('[data-test-icon="unhealthy-driver"]'),
|
hasUnhealthyDriver: isPresent('[data-test-icon="unhealthy-driver"]'),
|
||||||
hasProxyTag: isPresent('[data-test-proxy-tag]'),
|
hasProxyTag: isPresent('[data-test-proxy-tag]'),
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue