Refactor job summary to a relationship
Now that blocking queries are going to be in play, We can no longer pretend the two requests are one, since they have independent nomad indices.
This commit is contained in:
parent
2228e1fd0c
commit
e7796ccaee
|
@ -1,5 +1,4 @@
|
||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
import RSVP from 'rsvp';
|
|
||||||
import { assign } from '@ember/polyfills';
|
import { assign } from '@ember/polyfills';
|
||||||
import ApplicationAdapter from './application';
|
import ApplicationAdapter from './application';
|
||||||
|
|
||||||
|
@ -26,28 +25,17 @@ export default ApplicationAdapter.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
findRecord(store, { modelName }, id, snapshot) {
|
findRecordSummary(modelName, name, snapshot, namespaceQuery) {
|
||||||
// To make a findRecord response reflect the findMany response, the JobSummary
|
return this.ajax(`${this.buildURL(modelName, name, snapshot, 'findRecord')}/summary`, 'GET', {
|
||||||
// from /summary needs to be stitched into the response.
|
data: assign(this.buildQuery() || {}, namespaceQuery),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// URL is the form of /job/:name?namespace=:namespace with arbitrary additional query params
|
findRecord(store, type, id, snapshot) {
|
||||||
const [name, namespace] = JSON.parse(id);
|
const [name, namespace] = JSON.parse(id);
|
||||||
const namespaceQuery = namespace && namespace !== 'default' ? { namespace } : {};
|
const namespaceQuery = namespace && namespace !== 'default' ? { namespace } : {};
|
||||||
return RSVP.hash({
|
|
||||||
job: this.ajax(this.buildURL(modelName, name, snapshot, 'findRecord'), 'GET', {
|
return this._super(store, type, name, snapshot, namespaceQuery);
|
||||||
data: assign(this.buildQuery() || {}, namespaceQuery),
|
|
||||||
}),
|
|
||||||
summary: this.ajax(
|
|
||||||
`${this.buildURL(modelName, name, snapshot, 'findRecord')}/summary`,
|
|
||||||
'GET',
|
|
||||||
{
|
|
||||||
data: assign(this.buildQuery() || {}, namespaceQuery),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}).then(({ job, summary }) => {
|
|
||||||
job.JobSummary = summary;
|
|
||||||
return job;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
findAllocations(job) {
|
findAllocations(job) {
|
||||||
|
|
39
ui/app/models/job-summary.js
Normal file
39
ui/app/models/job-summary.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { collect, sum } from '@ember/object/computed';
|
||||||
|
import Model from 'ember-data/model';
|
||||||
|
import attr from 'ember-data/attr';
|
||||||
|
import { belongsTo } from 'ember-data/relationships';
|
||||||
|
import { fragmentArray } from 'ember-data-model-fragments/attributes';
|
||||||
|
import sumAggregation from '../utils/properties/sum-aggregation';
|
||||||
|
|
||||||
|
export default Model.extend({
|
||||||
|
job: belongsTo('job'),
|
||||||
|
|
||||||
|
taskGroupSummaries: fragmentArray('task-group-summary'),
|
||||||
|
|
||||||
|
// Aggregate allocation counts across all summaries
|
||||||
|
queuedAllocs: sumAggregation('taskGroupSummaries', 'queuedAllocs'),
|
||||||
|
startingAllocs: sumAggregation('taskGroupSummaries', 'startingAllocs'),
|
||||||
|
runningAllocs: sumAggregation('taskGroupSummaries', 'runningAllocs'),
|
||||||
|
completeAllocs: sumAggregation('taskGroupSummaries', 'completeAllocs'),
|
||||||
|
failedAllocs: sumAggregation('taskGroupSummaries', 'failedAllocs'),
|
||||||
|
lostAllocs: sumAggregation('taskGroupSummaries', 'lostAllocs'),
|
||||||
|
|
||||||
|
allocsList: collect(
|
||||||
|
'queuedAllocs',
|
||||||
|
'startingAllocs',
|
||||||
|
'runningAllocs',
|
||||||
|
'completeAllocs',
|
||||||
|
'failedAllocs',
|
||||||
|
'lostAllocs'
|
||||||
|
),
|
||||||
|
|
||||||
|
totalAllocs: sum('allocsList'),
|
||||||
|
|
||||||
|
pendingChildren: attr('number'),
|
||||||
|
runningChildren: attr('number'),
|
||||||
|
deadChildren: attr('number'),
|
||||||
|
|
||||||
|
childrenList: collect('pendingChildren', 'runningChildren', 'deadChildren'),
|
||||||
|
|
||||||
|
totalChildren: sum('childrenList'),
|
||||||
|
});
|
|
@ -1,10 +1,9 @@
|
||||||
import { collect, sum, bool, equal, or } from '@ember/object/computed';
|
import { alias, bool, equal, or } from '@ember/object/computed';
|
||||||
import { computed } from '@ember/object';
|
import { computed } from '@ember/object';
|
||||||
import Model from 'ember-data/model';
|
import Model from 'ember-data/model';
|
||||||
import attr from 'ember-data/attr';
|
import attr from 'ember-data/attr';
|
||||||
import { belongsTo, hasMany } from 'ember-data/relationships';
|
import { belongsTo, hasMany } from 'ember-data/relationships';
|
||||||
import { fragmentArray } from 'ember-data-model-fragments/attributes';
|
import { fragmentArray } from 'ember-data-model-fragments/attributes';
|
||||||
import sumAggregation from '../utils/properties/sum-aggregation';
|
|
||||||
|
|
||||||
const JOB_TYPES = ['service', 'batch', 'system'];
|
const JOB_TYPES = ['service', 'batch', 'system'];
|
||||||
|
|
||||||
|
@ -83,34 +82,21 @@ export default Model.extend({
|
||||||
|
|
||||||
datacenters: attr(),
|
datacenters: attr(),
|
||||||
taskGroups: fragmentArray('task-group', { defaultValue: () => [] }),
|
taskGroups: fragmentArray('task-group', { defaultValue: () => [] }),
|
||||||
taskGroupSummaries: fragmentArray('task-group-summary'),
|
summary: belongsTo('job-summary'),
|
||||||
|
|
||||||
// Aggregate allocation counts across all summaries
|
// Alias through to the summary, as if there was no relationship
|
||||||
queuedAllocs: sumAggregation('taskGroupSummaries', 'queuedAllocs'),
|
taskGroupSummaries: alias('summary.taskGroupSummaries'),
|
||||||
startingAllocs: sumAggregation('taskGroupSummaries', 'startingAllocs'),
|
queuedAllocs: alias('summary.queuedAllocs'),
|
||||||
runningAllocs: sumAggregation('taskGroupSummaries', 'runningAllocs'),
|
startingAllocs: alias('summary.startingAllocs'),
|
||||||
completeAllocs: sumAggregation('taskGroupSummaries', 'completeAllocs'),
|
runningAllocs: alias('summary.runningAllocs'),
|
||||||
failedAllocs: sumAggregation('taskGroupSummaries', 'failedAllocs'),
|
completeAllocs: alias('summary.completeAllocs'),
|
||||||
lostAllocs: sumAggregation('taskGroupSummaries', 'lostAllocs'),
|
failedAllocs: alias('summary.failedAllocs'),
|
||||||
|
lostAllocs: alias('summary.lostAllocs'),
|
||||||
allocsList: collect(
|
totalAllocs: alias('summary.totalAllocs'),
|
||||||
'queuedAllocs',
|
pendingChildren: alias('summary.pendingChildren'),
|
||||||
'startingAllocs',
|
runningChildren: alias('summary.runningChildren'),
|
||||||
'runningAllocs',
|
deadChildren: alias('summary.deadChildren'),
|
||||||
'completeAllocs',
|
totalChildren: alias('summary.childrenList'),
|
||||||
'failedAllocs',
|
|
||||||
'lostAllocs'
|
|
||||||
),
|
|
||||||
|
|
||||||
totalAllocs: sum('allocsList'),
|
|
||||||
|
|
||||||
pendingChildren: attr('number'),
|
|
||||||
runningChildren: attr('number'),
|
|
||||||
deadChildren: attr('number'),
|
|
||||||
|
|
||||||
childrenList: collect('pendingChildren', 'runningChildren', 'deadChildren'),
|
|
||||||
|
|
||||||
totalChildren: sum('childrenList'),
|
|
||||||
|
|
||||||
version: attr('number'),
|
version: attr('number'),
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ import attr from 'ember-data/attr';
|
||||||
import { fragmentOwner, fragmentArray } from 'ember-data-model-fragments/attributes';
|
import { fragmentOwner, fragmentArray } from 'ember-data-model-fragments/attributes';
|
||||||
import sumAggregation from '../utils/properties/sum-aggregation';
|
import sumAggregation from '../utils/properties/sum-aggregation';
|
||||||
|
|
||||||
|
const maybe = arr => arr || [];
|
||||||
|
|
||||||
export default Fragment.extend({
|
export default Fragment.extend({
|
||||||
job: fragmentOwner(),
|
job: fragmentOwner(),
|
||||||
|
|
||||||
|
@ -13,7 +15,7 @@ export default Fragment.extend({
|
||||||
tasks: fragmentArray('task'),
|
tasks: fragmentArray('task'),
|
||||||
|
|
||||||
allocations: computed('job.allocations.@each.taskGroup', function() {
|
allocations: computed('job.allocations.@each.taskGroup', function() {
|
||||||
return this.get('job.allocations').filterBy('taskGroupName', this.get('name'));
|
return maybe(this.get('job.allocations')).filterBy('taskGroupName', this.get('name'));
|
||||||
}),
|
}),
|
||||||
|
|
||||||
reservedCPU: sumAggregation('tasks', 'reservedCPU'),
|
reservedCPU: sumAggregation('tasks', 'reservedCPU'),
|
||||||
|
@ -32,6 +34,6 @@ export default Fragment.extend({
|
||||||
}),
|
}),
|
||||||
|
|
||||||
summary: computed('job.taskGroupSummaries.[]', function() {
|
summary: computed('job.taskGroupSummaries.[]', function() {
|
||||||
return this.get('job.taskGroupSummaries').findBy('name', this.get('name'));
|
return maybe(this.get('job.taskGroupSummaries')).findBy('name', this.get('name'));
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
32
ui/app/serializers/job-summary.js
Normal file
32
ui/app/serializers/job-summary.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { get } from '@ember/object';
|
||||||
|
import ApplicationSerializer from './application';
|
||||||
|
|
||||||
|
export default ApplicationSerializer.extend({
|
||||||
|
normalize(modelClass, hash) {
|
||||||
|
// Transform the map-based Summary object into an array-based
|
||||||
|
// TaskGroupSummary fragment list
|
||||||
|
hash.PlainJobId = hash.JobID;
|
||||||
|
hash.ID = JSON.stringify([hash.JobID, hash.Namespace || 'default']);
|
||||||
|
|
||||||
|
hash.TaskGroupSummaries = Object.keys(get(hash, 'Summary') || {}).map(key => {
|
||||||
|
const allocStats = get(hash, `Summary.${key}`) || {};
|
||||||
|
const summary = { Name: key };
|
||||||
|
|
||||||
|
Object.keys(allocStats).forEach(
|
||||||
|
allocKey => (summary[`${allocKey}Allocs`] = allocStats[allocKey])
|
||||||
|
);
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Lift the children stats out of the Children object
|
||||||
|
const childrenStats = get(hash, 'Children');
|
||||||
|
if (childrenStats) {
|
||||||
|
Object.keys(childrenStats).forEach(
|
||||||
|
childrenKey => (hash[`${childrenKey}Children`] = childrenStats[childrenKey])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._super(modelClass, hash);
|
||||||
|
},
|
||||||
|
});
|
|
@ -34,27 +34,6 @@ export default ApplicationSerializer.extend({
|
||||||
hash.ParameterizedJob = true;
|
hash.ParameterizedJob = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform the map-based JobSummary object into an array-based
|
|
||||||
// JobSummary fragment list
|
|
||||||
hash.TaskGroupSummaries = Object.keys(get(hash, 'JobSummary.Summary') || {}).map(key => {
|
|
||||||
const allocStats = get(hash, `JobSummary.Summary.${key}`) || {};
|
|
||||||
const summary = { Name: key };
|
|
||||||
|
|
||||||
Object.keys(allocStats).forEach(
|
|
||||||
allocKey => (summary[`${allocKey}Allocs`] = allocStats[allocKey])
|
|
||||||
);
|
|
||||||
|
|
||||||
return summary;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Lift the children stats out of the JobSummary object
|
|
||||||
const childrenStats = get(hash, 'JobSummary.Children');
|
|
||||||
if (childrenStats) {
|
|
||||||
Object.keys(childrenStats).forEach(
|
|
||||||
childrenKey => (hash[`${childrenKey}Children`] = childrenStats[childrenKey])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._super(typeHash, hash);
|
return this._super(typeHash, hash);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -68,6 +47,11 @@ export default ApplicationSerializer.extend({
|
||||||
.buildURL(modelName, hash.PlainId, hash, 'findRecord');
|
.buildURL(modelName, hash.PlainId, hash, 'findRecord');
|
||||||
|
|
||||||
return assign(this._super(...arguments), {
|
return assign(this._super(...arguments), {
|
||||||
|
summary: {
|
||||||
|
links: {
|
||||||
|
related: buildURL(`${jobURL}/summary`, { namespace: namespace }),
|
||||||
|
},
|
||||||
|
},
|
||||||
allocations: {
|
allocations: {
|
||||||
links: {
|
links: {
|
||||||
related: buildURL(`${jobURL}/allocations`, { namespace: namespace }),
|
related: buildURL(`${jobURL}/allocations`, { namespace: namespace }),
|
||||||
|
|
Loading…
Reference in a new issue