From: Jeff Davis Date: Wed, 23 Oct 2019 23:25:41 +0000 (-0700) Subject: LP#1848550: client-side caching of org settings for AngularJS X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=e528125b062e70cc404d9d5625074c12b91bc85d;p=working%2FEvergreen.git LP#1848550: client-side caching of org settings for AngularJS The web client almost always does live lookups any time it needs to check an org setting. But these settings rarely change, so it would make sense to cache them. They're already cached using Lovefield in order to support offline; this commit checks the cache first, and only does a live lookup if the setting is uncached or expired (i.e. added to cache more than 12 hours ago). Offline ignores the 12-hour expire time so that we always have settings to work with when the server is unreachable. Signed-off-by: Jeff Davis --- diff --git a/Open-ILS/web/js/ui/default/staff/offline-db-worker.js b/Open-ILS/web/js/ui/default/staff/offline-db-worker.js index 32399001e7..4a139dd1c1 100644 --- a/Open-ILS/web/js/ui/default/staff/offline-db-worker.js +++ b/Open-ILS/web/js/ui/default/staff/offline-db-worker.js @@ -30,6 +30,7 @@ function createCacheTables(meta) { meta.createTable('Setting'). addColumn('name', lf.Type.STRING). addColumn('value', lf.Type.STRING). + addColumn('cachedate', lf.Type.DATE_TIME). // when was it last updated addPrimaryKey(['name']); meta.createTable('Object'). diff --git a/Open-ILS/web/js/ui/default/staff/services/lovefield.js b/Open-ILS/web/js/ui/default/staff/services/lovefield.js index e7ec4960c8..5a82a12004 100644 --- a/Open-ILS/web/js/ui/default/staff/services/lovefield.js +++ b/Open-ILS/web/js/ui/default/staff/services/lovefield.js @@ -296,7 +296,7 @@ angular.module('egCoreMod') var rows = []; angular.forEach(settings, function (val, key) { - rows.push({name : key, value : JSON.stringify(val)}); + rows.push({name : key, value : JSON.stringify(val), cachedate : new Date()}); }); return service.request({ diff --git a/Open-ILS/web/js/ui/default/staff/services/org.js b/Open-ILS/web/js/ui/default/staff/services/org.js index 36c9ed2e6b..e4b054a8d2 100644 --- a/Open-ILS/web/js/ui/default/staff/services/org.js +++ b/Open-ILS/web/js/ui/default/staff/services/org.js @@ -99,6 +99,7 @@ function($q, egEnv, egAuth, egNet , $injector) { } var egLovefield = null; + // returns a promise, resolved with a hash of setting name => // setting value for the selected org unit. Org unit defaults to // auth workstation org unit. @@ -111,6 +112,9 @@ function($q, egEnv, egAuth, egNet , $injector) { if (!angular.isArray(names)) names = [names]; if (lf.isOffline) { + // for offline, just use whatever we have managed to cache, + // even if the value is expired (since we can't refresh it + // from the server) return egLovefield.getSettingsCache(names).then( function(settings) { var hash = {}; @@ -126,26 +130,73 @@ function($q, egEnv, egAuth, egNet , $injector) { if (!egAuth.user()) return $q.when(); - var deferred = $q.defer(); ou_id = ou_id || egAuth.user().ws_ou(); - var here = (ou_id == egAuth.user().ws_ou()); + if (ou_id != egAuth.user().ws_ou()) { + // we only cache settings for the current working location; + // if we have requested settings for some other org unit, + // skip the cache and pull settings directly from the server + return service.settingsFromServer(names, ou_id); + } - - if (here) { - // only cache org settings retrieved for the current - // workstation org unit. - var newNames = []; + var deferred = $q.defer(); + + var newNames = []; + angular.forEach(names, function(name) { + if (!angular.isDefined(service.cachedSettings[name])) + // we don't have a value for this setting yet + newNames.push(name) + }); + + // only retrieve uncached values + names = newNames; + if (names.length == 0) + return $q.when(service.cachedSettings); + + // get settings from online cache where possible; + // otherwise, get settings from server + egLovefield.getSettingsCache(names) + .then(function(settings) { + + // populate values from offline cache + var cache_expiry = 43200000; // XXX hard-coded to 12 hours; make configurable? + angular.forEach(settings, function (s) { + if ((new Date().getTime() - s.cachedate.getTime()) <= cache_expiry) + service.cachedSettings[s.name] = s.value; + }); + + // check if any requested settings were not in offline cache + var uncached = []; angular.forEach(names, function(name) { if (!angular.isDefined(service.cachedSettings[name])) - newNames.push(name) + uncached.push(name); }); - // only retrieve uncached values - names = newNames; - if (names.length == 0) - return $q.when(service.cachedSettings); + if (uncached.length == 0) { + // all requested settings were in the offline cache already + deferred.resolve(service.cachedSettings); + } else { + // cache was missing some settings; grab those from the server + service.settingsFromServer(uncached, ou_id) + .then(function() { + deferred.resolve(service.cachedSettings); + }); + } + }); + return deferred.promise; + } + + service.settingsFromServer = function(names, ou_id) { + if (!egLovefield) { + egLovefield = $injector.get('egLovefield'); } + // allow non-array + if (!angular.isArray(names)) names = [names]; + + var deferred = $q.defer(); + ou_id = ou_id || egAuth.user().ws_ou(); + var here = (ou_id == egAuth.user().ws_ou()); + egNet.request( 'open-ils.actor', 'open-ils.actor.ou_setting.ancestor_default.batch',