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:
Michael Lange 2018-02-08 15:02:48 -08:00
parent 2228e1fd0c
commit e7796ccaee
6 changed files with 103 additions and 72 deletions

View file

@ -1,5 +1,4 @@
import { inject as service } from '@ember/service';
import RSVP from 'rsvp';
import { assign } from '@ember/polyfills';
import ApplicationAdapter from './application';
@ -26,28 +25,17 @@ export default ApplicationAdapter.extend({
});
},
findRecord(store, { modelName }, id, snapshot) {
// To make a findRecord response reflect the findMany response, the JobSummary
// from /summary needs to be stitched into the response.
findRecordSummary(modelName, name, snapshot, namespaceQuery) {
return this.ajax(`${this.buildURL(modelName, name, snapshot, 'findRecord')}/summary`, 'GET', {
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 namespaceQuery = namespace && namespace !== 'default' ? { namespace } : {};
return RSVP.hash({
job: this.ajax(this.buildURL(modelName, name, snapshot, 'findRecord'), 'GET', {
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;
});
return this._super(store, type, name, snapshot, namespaceQuery);
},
findAllocations(job) {

View 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'),
});

View file

@ -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 Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { belongsTo, hasMany } from 'ember-data/relationships';
import { fragmentArray } from 'ember-data-model-fragments/attributes';
import sumAggregation from '../utils/properties/sum-aggregation';
const JOB_TYPES = ['service', 'batch', 'system'];
@ -83,34 +82,21 @@ export default Model.extend({
datacenters: attr(),
taskGroups: fragmentArray('task-group', { defaultValue: () => [] }),
taskGroupSummaries: fragmentArray('task-group-summary'),
summary: belongsTo('job-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'),
// Alias through to the summary, as if there was no relationship
taskGroupSummaries: alias('summary.taskGroupSummaries'),
queuedAllocs: alias('summary.queuedAllocs'),
startingAllocs: alias('summary.startingAllocs'),
runningAllocs: alias('summary.runningAllocs'),
completeAllocs: alias('summary.completeAllocs'),
failedAllocs: alias('summary.failedAllocs'),
lostAllocs: alias('summary.lostAllocs'),
totalAllocs: alias('summary.totalAllocs'),
pendingChildren: alias('summary.pendingChildren'),
runningChildren: alias('summary.runningChildren'),
deadChildren: alias('summary.deadChildren'),
totalChildren: alias('summary.childrenList'),
version: attr('number'),

View file

@ -4,6 +4,8 @@ import attr from 'ember-data/attr';
import { fragmentOwner, fragmentArray } from 'ember-data-model-fragments/attributes';
import sumAggregation from '../utils/properties/sum-aggregation';
const maybe = arr => arr || [];
export default Fragment.extend({
job: fragmentOwner(),
@ -13,7 +15,7 @@ export default Fragment.extend({
tasks: fragmentArray('task'),
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'),
@ -32,6 +34,6 @@ export default Fragment.extend({
}),
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'));
}),
});

View 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);
},
});

View file

@ -34,27 +34,6 @@ export default ApplicationSerializer.extend({
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);
},
@ -68,6 +47,11 @@ export default ApplicationSerializer.extend({
.buildURL(modelName, hash.PlainId, hash, 'findRecord');
return assign(this._super(...arguments), {
summary: {
links: {
related: buildURL(`${jobURL}/summary`, { namespace: namespace }),
},
},
allocations: {
links: {
related: buildURL(`${jobURL}/allocations`, { namespace: namespace }),