mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 02:15:43 +03:00
Prototype watching resources
- Service to manage X-Nomad-Index values - Adapter method for reloading relationships with additional params - Pattern for watching models and model relationships using EC
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { inject as service } from '@ember/service';
|
||||
import { assign } from '@ember/polyfills';
|
||||
import ApplicationAdapter from './application';
|
||||
import Watchable from './watchable';
|
||||
|
||||
export default ApplicationAdapter.extend({
|
||||
export default Watchable.extend({
|
||||
system: service(),
|
||||
|
||||
shouldReloadAll: () => true,
|
||||
// shouldReloadAll: () => true,
|
||||
|
||||
buildQuery() {
|
||||
const namespace = this.get('system.activeNamespace.id');
|
||||
|
||||
60
ui/app/adapters/watchable.js
Normal file
60
ui/app/adapters/watchable.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import { get } from '@ember/object';
|
||||
import { assign } from '@ember/polyfills';
|
||||
import { copy } from '@ember/object/internals';
|
||||
import { inject as service } from '@ember/service';
|
||||
import queryString from 'npm:query-string';
|
||||
import ApplicationAdapter from './application';
|
||||
|
||||
export default ApplicationAdapter.extend({
|
||||
watchList: service(),
|
||||
store: service(),
|
||||
|
||||
findRecord(store, type, id, snapshot, additionalParams = {}) {
|
||||
const params = copy(additionalParams, true);
|
||||
const url = this.buildURL(type.modelName, id, snapshot, 'findRecord');
|
||||
|
||||
if (get(snapshot, 'adapterOptions.watch')) {
|
||||
params.index = this.get('watchList').getIndexFor(url);
|
||||
}
|
||||
|
||||
return this.ajax(url, 'GET', {
|
||||
data: params,
|
||||
});
|
||||
},
|
||||
|
||||
reloadRelationship(model, relationshipName, watch = false) {
|
||||
const relationship = model.relationshipFor(relationshipName);
|
||||
if (relationship.kind !== 'belongsTo' && relationship.kind !== 'hasMany') {
|
||||
throw new Error(
|
||||
`${relationship.key} must be a belongsTo or hasMany, instead it was ${relationship.kind}`
|
||||
);
|
||||
} else {
|
||||
const url = model[relationship.kind](relationship.key).link();
|
||||
let params = {};
|
||||
|
||||
if (watch) {
|
||||
params.index = this.get('watchList').getIndexFor(url);
|
||||
}
|
||||
|
||||
if (url.includes('?')) {
|
||||
params = assign(queryString.parse(url.split('?')[1]), params);
|
||||
}
|
||||
|
||||
this.ajax(url, 'GET', {
|
||||
data: params,
|
||||
}).then(json => {
|
||||
this.get('store').pushPayload(relationship.type, {
|
||||
[relationship.type]: relationship.kind === 'hasMany' ? json : [json],
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
handleResponse(status, headers, payload, requestData) {
|
||||
const newIndex = headers['x-nomad-index'];
|
||||
if (newIndex) {
|
||||
this.get('watchList').setIndexFor(requestData.url, newIndex);
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
@@ -2,9 +2,13 @@ import { inject as service } from '@ember/service';
|
||||
import Route from '@ember/routing/route';
|
||||
import RSVP from 'rsvp';
|
||||
import notifyError from 'nomad-ui/utils/notify-error';
|
||||
import { task } from 'ember-concurrency';
|
||||
import wait from 'nomad-ui/utils/wait';
|
||||
|
||||
export default Route.extend({
|
||||
store: service(),
|
||||
token: service(),
|
||||
watchList: service(),
|
||||
|
||||
serialize(model) {
|
||||
return { job_name: model.get('plainId') };
|
||||
@@ -21,4 +25,41 @@ export default Route.extend({
|
||||
})
|
||||
.catch(notifyError(this));
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('modelTask', this.get('watch').perform(model.get('id')));
|
||||
controller.set('summaryTask', this.get('watchRelationship').perform(model, 'summary'));
|
||||
controller.set('evaluationsTask', this.get('watchRelationship').perform(model, 'evaluations'));
|
||||
controller.set('deploymentsTask', this.get('watchRelationship').perform(model, 'deployments'));
|
||||
},
|
||||
|
||||
watch: task(function*(jobId) {
|
||||
while (true) {
|
||||
try {
|
||||
yield RSVP.all([
|
||||
this.store.findRecord('job', jobId, { reload: true, adapterOptions: { watch: true } }),
|
||||
wait(2000),
|
||||
]);
|
||||
} catch (e) {
|
||||
yield e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
watchRelationship: task(function*(job, relationshipName) {
|
||||
while (true) {
|
||||
try {
|
||||
yield RSVP.all([
|
||||
this.store
|
||||
.adapterFor(job.get('modelName'))
|
||||
.reloadRelationship(job, relationshipName, true),
|
||||
wait(2000),
|
||||
]);
|
||||
} catch (e) {
|
||||
yield e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
19
ui/app/services/watch-list.js
Normal file
19
ui/app/services/watch-list.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { readOnly } from '@ember/object/computed';
|
||||
import { copy } from '@ember/object/internals';
|
||||
import Service from '@ember/service';
|
||||
|
||||
const list = {};
|
||||
|
||||
export default Service.extend({
|
||||
list: readOnly(function() {
|
||||
return copy(list, true);
|
||||
}),
|
||||
|
||||
getIndexFor(url) {
|
||||
return list[url] || 0;
|
||||
},
|
||||
|
||||
setIndexFor(url, value) {
|
||||
list[url] = value;
|
||||
},
|
||||
});
|
||||
10
ui/app/utils/wait.js
Normal file
10
ui/app/utils/wait.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import RSVP from 'rsvp';
|
||||
|
||||
// An always passing promise used to throttle other promises
|
||||
export default function wait(duration) {
|
||||
return new RSVP.Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(`Waited ${duration}ms`);
|
||||
}, duration);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user