From d955e5b1ee5cf93858d95160f9ee473193459df6 Mon Sep 17 00:00:00 2001 From: Stanislaw Adaszewski Date: Thu, 6 Feb 2020 07:37:23 +0100 Subject: [PATCH] Request ordering implemented and seems to be working but decreases responsiveness, perhaps better to manage ordering within components. --- .../src/js/component/wb-collection-listing.js | 3 +- frontend/src/js/misc/make-arvados-request.js | 22 ++----- .../src/js/misc/wb-apply-request-ordering.js | 66 +++++++++++++++++++ 3 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 frontend/src/js/misc/wb-apply-request-ordering.js diff --git a/frontend/src/js/component/wb-collection-listing.js b/frontend/src/js/component/wb-collection-listing.js index a008878..0eeb5e6 100644 --- a/frontend/src/js/component/wb-collection-listing.js +++ b/frontend/src/js/component/wb-collection-listing.js @@ -66,8 +66,7 @@ class WBCollectionListing extends Component { let prom = makeArvadosRequest(arvHost, arvToken, '/arvados/v1/collections?filters=' + encodeURIComponent(JSON.stringify(filters)) + '&limit=' + encodeURIComponent(itemsPerPage) + - '&offset=' + encodeURIComponent(itemsPerPage * activePage), - { 'orderStream': this.state.orderStream }); + '&offset=' + encodeURIComponent(itemsPerPage * activePage)); let collections; let numPages diff --git a/frontend/src/js/misc/make-arvados-request.js b/frontend/src/js/misc/make-arvados-request.js index a285f08..0ce66a0 100644 --- a/frontend/src/js/misc/make-arvados-request.js +++ b/frontend/src/js/misc/make-arvados-request.js @@ -1,4 +1,4 @@ -const requestOrdering = {}; +import wbApplyRequestOrdering from 'wb-apply-request-ordering'; function makeArvadosRequest(arvHost, arvToken, endpoint, params={}) { const defaultParams = { @@ -7,22 +7,12 @@ function makeArvadosRequest(arvHost, arvToken, endpoint, params={}) { 'contentType': 'application/json;charset=utf-8', 'responseType': 'json', 'useSsl': true, - 'requireToken': true, - 'orderStream': null + 'requireToken': true }; Object.keys(defaultParams).map(k => (params[k] = (k in params ? params[k] : defaultParams[k]))); - let { method, data, contentType, responseType, useSsl, requireToken, orderStream } = params; - - let orderId; - if (orderStream) { - if (!(orderStream in requestOrdering)) - requestOrdering[orderStream] = { 'counter': 0, 'started': [], 'completed': [] }; - requestOrdering[orderStream].counter += 1; - orderId = requestOrdering[orderStream].counter; - requestOrdering[orderStream].started.push(orderId); - } + let { method, data, contentType, responseType, useSsl, requireToken } = params; if (!(arvHost && (arvToken || !requireToken))) return new Promise((accept, reject) => reject()); @@ -35,7 +25,7 @@ function makeArvadosRequest(arvHost, arvToken, endpoint, params={}) { xhr.setRequestHeader('Content-Type', contentType); xhr.responseType = responseType; - let res = new Promise((accept, reject) => { + let prom = new Promise((accept, reject) => { xhr.onreadystatechange = () => { if (xhr.readyState !== 4) return; @@ -47,7 +37,9 @@ function makeArvadosRequest(arvHost, arvToken, endpoint, params={}) { xhr.send(data); }); - return res; + // prom = wbApplyRequestOrdering(prom); + + return prom; } export default makeArvadosRequest; diff --git a/frontend/src/js/misc/wb-apply-request-ordering.js b/frontend/src/js/misc/wb-apply-request-ordering.js new file mode 100644 index 0000000..860fd77 --- /dev/null +++ b/frontend/src/js/misc/wb-apply-request-ordering.js @@ -0,0 +1,66 @@ +const defaultOrderRegistry = {}; + +function wbApplyRequestOrdering(prom, orderRegistry) { + let orderId; + + if (!orderRegistry) + orderRegistry = defaultOrderRegistry; + + if (Object.keys(orderRegistry).length === 0) { + orderRegistry.started = 0; + orderRegistry.pendingCompletion = {}; + orderRegistry.completed = { 0: true }; + } + + orderRegistry.started += 1; + orderId = orderRegistry.started; + // console.log('New orderId: ' + orderId); + + const orderCallback = ((isCatch, payload) => { + // console.log('orderId: ' + orderId + + // ', pendingCompletion: ' + Object.keys(orderRegistry.pendingCompletion) + + // ', completed: ' + Object.keys(orderRegistry.completed)); + + if ((orderId - 1) in orderRegistry.completed) { + // console.log('Running: ' + orderId); + orderRegistry.completed[orderId] = true; + delete orderRegistry.pendingCompletion[orderId]; + + const keys = Object.keys(orderRegistry.pendingCompletion); + keys.sort((a, b) => (a - b)); + keys.map(k => { + if ((k - 1) in orderRegistry.completed) { + // console.log('Running: ' + k); + orderRegistry.pendingCompletion[k](); + orderRegistry.completed[k] = true; + delete orderRegistry.pendingCompletion[k]; + } + }); + + if (orderRegistry.started in orderRegistry.completed) { + // console.log('Garbage collect'); + orderRegistry.started = 0; + orderRegistry.completed = { 0: true }; + } + + if (isCatch) + throw payload; + else + return payload; + } + + const prom_1 = new Promise((accept, reject) => { + orderRegistry.pendingCompletion[orderId] = (() => + (isCatch ? reject(payload) : accept(payload))); + }); + + return prom_1; + }); + + prom = prom.then(xhr => orderCallback(false, xhr)); + prom = prom.catch(e => orderCallback(true, e)); + + return prom; +} + +export default wbApplyRequestOrdering;