From 2e51449ace3053116c38854da63a820f47bf5792 Mon Sep 17 00:00:00 2001 From: John Cowen Date: Mon, 27 Jul 2020 09:30:52 +0000 Subject: [PATCH] ui: Use `X-Range` header/meta to decide whether to reconcile or not Previously we used a `shouldReconcile` method in order to decide whether a response should trigger a reconciliation of the frontend ember-data 'source of truth' or not. It's a lot nicer/clearer if this 'flag' can be set alongside the HTTP request information, moreover we almost have the same functionality in `If-Range`/`Partial Content` HTTP functionality. Here we partly follow this HTTP semantics but use a custom `X-Range` header instead. --- ui-v2/app/serializers/application.js | 9 ++++++++- ui-v2/app/services/client/http.js | 2 +- .../services/data-source/protocols/http.js | 19 +++++++++--------- ui-v2/app/services/repository.js | 3 --- ui-v2/app/services/repository/intention.js | 9 --------- ui-v2/app/services/repository/service.js | 7 ------- .../services/repository/type/event-source.js | 20 +++++++++---------- 7 files changed, 29 insertions(+), 40 deletions(-) diff --git a/ui-v2/app/serializers/application.js b/ui-v2/app/serializers/application.js index af5f1c3d5..fb7397df8 100644 --- a/ui-v2/app/serializers/application.js +++ b/ui-v2/app/serializers/application.js @@ -92,7 +92,11 @@ export default Serializer.extend({ // and they need the slug key AND potential namespace in order to // create the correct uid/fingerprint return { - [primaryKey]: this.fingerprint(primaryKey, slugKey, data[DATACENTER_KEY])({ + [primaryKey]: this.fingerprint( + primaryKey, + slugKey, + data[DATACENTER_KEY] + )({ [slugKey]: data[slugKey], [NSPACE_KEY]: data[NSPACE_KEY], })[primaryKey], @@ -151,6 +155,9 @@ export default Serializer.extend({ dc: headers[HTTP_HEADERS_DATACENTER.toLowerCase()], nspace: headers[HTTP_HEADERS_NAMESPACE.toLowerCase()], }; + if (typeof headers['x-range'] !== 'undefined') { + meta.range = headers['x-range']; + } if (requestType === 'query') { meta.date = this.timestamp(); payload.forEach(function(item) { diff --git a/ui-v2/app/services/client/http.js b/ui-v2/app/services/client/http.js index e98ba07c5..a9525afb3 100644 --- a/ui-v2/app/services/client/http.js +++ b/ui-v2/app/services/client/http.js @@ -68,7 +68,7 @@ const parseBody = function(strs, ...values) { return [body, ...values]; }; -const CLIENT_HEADERS = [CACHE_CONTROL, 'X-Request-ID']; +const CLIENT_HEADERS = [CACHE_CONTROL, 'X-Request-ID', 'X-Range']; export default Service.extend({ dom: service('dom'), connections: service('client/connections'), diff --git a/ui-v2/app/services/data-source/protocols/http.js b/ui-v2/app/services/data-source/protocols/http.js index 5a51a08f8..4dc7070a9 100644 --- a/ui-v2/app/services/data-source/protocols/http.js +++ b/ui-v2/app/services/data-source/protocols/http.js @@ -33,16 +33,17 @@ export default Service.extend({ // so we might get urls like //dc/services let find; const repo = this[model]; - if (repo.shouldReconcile(src)) { - configuration.createEvent = function(result = {}, configuration) { - const event = { - type: 'message', - data: result, - }; - repo.reconcile(get(event, 'data.meta')); - return event; + configuration.createEvent = function(result = {}, configuration) { + const event = { + type: 'message', + data: result, }; - } + const meta = get(event, 'data.meta') || {}; + if (typeof meta.range === 'undefined') { + repo.reconcile(meta); + } + return event; + }; let method, slug; switch (model) { case 'datacenters': diff --git a/ui-v2/app/services/repository.js b/ui-v2/app/services/repository.js index 9e3e13971..a48b4f13e 100644 --- a/ui-v2/app/services/repository.js +++ b/ui-v2/app/services/repository.js @@ -15,9 +15,6 @@ export default Service.extend({ }, // store: service('store'), - shouldReconcile: function(method) { - return true; - }, reconcile: function(meta = {}) { // unload anything older than our current sync date/time if (typeof meta.date !== 'undefined') { diff --git a/ui-v2/app/services/repository/intention.js b/ui-v2/app/services/repository/intention.js index 193ed9373..72b8a6227 100644 --- a/ui-v2/app/services/repository/intention.js +++ b/ui-v2/app/services/repository/intention.js @@ -12,15 +12,6 @@ export default RepositoryService.extend({ delete obj.Namespace; return this._super(obj); }, - shouldReconcile: function(method) { - // TODO: This is to be switched out for something at an adapter level - // so it works for both methods of interacting with data-sources - switch (true) { - case method === 'findByService' || method.indexOf('for-service') !== -1: - return false; - } - return this._super(...arguments); - }, findByService: function(slug, dc, nspace, configuration = {}) { const query = { dc: dc, diff --git a/ui-v2/app/services/repository/service.js b/ui-v2/app/services/repository/service.js index a62a70a53..82c6f4f2d 100644 --- a/ui-v2/app/services/repository/service.js +++ b/ui-v2/app/services/repository/service.js @@ -5,13 +5,6 @@ export default RepositoryService.extend({ getModelName: function() { return modelName; }, - shouldReconcile: function(method) { - switch (method) { - case 'findGatewayBySlug': - return false; - } - return this._super(...arguments); - }, findBySlug: function(slug, dc) { return this._super(...arguments).then(function(item) { // TODO: Move this to the Serializer diff --git a/ui-v2/app/services/repository/type/event-source.js b/ui-v2/app/services/repository/type/event-source.js index 79683aa39..6fffd39ad 100644 --- a/ui-v2/app/services/repository/type/event-source.js +++ b/ui-v2/app/services/repository/type/event-source.js @@ -9,17 +9,17 @@ import { cache as createCache, BlockingEventSource } from 'consul-ui/utils/dom/e const createProxy = function(repo, find, settings, cache, serialize = JSON.stringify) { const client = this.client; // custom createEvent, here used to reconcile the ember-data store for each tick - let createEvent; - if (repo.shouldReconcile(find)) { - createEvent = function(result = {}, configuration) { - const event = { - type: 'message', - data: result, - }; - repo.reconcile(get(event, 'data.meta')); - return event; + const createEvent = function(result = {}, configuration) { + const event = { + type: 'message', + data: result, }; - } + const meta = get(event, 'data.meta') || {}; + if (typeof meta.range === 'undefined') { + repo.reconcile(meta); + } + return event; + }; // proxied find*..(id, dc) return function() { const key = `${repo.getModelName()}.${find}.${serialize([...arguments])}`;