-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
3111: Perf: implement HttpCache service to cache Accounts.read() call r=jniles a=jniles **Original Text** ~~This PR introduces a new factory function for debouncing function calls. The suggested ng-debounce library did not use promises and was cumbersome to use, thus I have implemented my own based on a SO issue. The `Accounts.read()` method has been debounced by 2000 milliseconds to allow for things like `bhAccountSelects` to benefit from the same HTTP request instead of making one each.~~ **Updated Information** This Pull request implements a new service called `HttpCache` that should transparently wrap any HTTP requests and ensure that the same function call will return the same result. This is useful for smaller, more frequently called routes. _Basic Usage:_ ```js // a GET HTTP request to some url function read(id, options) { return $http.get(/*...*/); } // to proxy, simply wrap the function in HttpCache const proxy = HttpCache((id, options) => read(id, options)); // You can now call proxy as proxy(1, { limit : 10 }) .then(() => /*... */); ``` For uncached requests, the behavior is the same a raw HTTP request. For those that have been called multiple times, the web page no longer needs to send an extra HTTP request. If you want to skip the cache (and bust it), simply pass `true` as the third parameter. Closes #2892. Co-authored-by: Jonathan Niles <[email protected]> Co-authored-by: Jonathan Niles <[email protected]>
- Loading branch information
Showing
7 changed files
with
223 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
angular.module('bhima.services') | ||
.service('HttpCacheService', HttpCacheService); | ||
|
||
HttpCacheService.$inject = ['$interval']; | ||
|
||
/** | ||
* @function HttpCacheService | ||
* | ||
* @description | ||
* The HttpCacheService is a generic wrapper for asynchronous requests to ensure | ||
* they requests with identical parameters are only called once. It works by | ||
* serializing the request's parameters and caching the response to those parameters | ||
* for a short time. If any other requests are made during the cached time, the | ||
* previous response is returned directly. | ||
* | ||
* NOTE(@jniles) - we use $interval here to avoid slowing down protractor tests. | ||
* Thanks to @sfount who debugged this in Dec 2016. | ||
*/ | ||
function HttpCacheService($interval) { | ||
|
||
// default cache limit - 15 seconds | ||
const HTTP_CACHE_DEFAULT_TIMEOUT = 15000; | ||
|
||
/** | ||
* @function serialize | ||
* | ||
* @description | ||
* This function serializes the arguments passed in to create a string key | ||
* that can be used to index the callback results. | ||
* | ||
* @returns {String} - string representation of arguments | ||
*/ | ||
const serialize = (...args) => JSON.stringify(args); | ||
|
||
/** | ||
* @function HttpCache | ||
* | ||
* @description | ||
* Takes in a callback function to call if the result is not in the cache. The | ||
* response is cached and returned to the caller. | ||
* | ||
* @param {Function} callback - a callback function to call if there is no cached | ||
* value. The result of this function will be cached. | ||
* @param {Number} duration - the duration the result will be cached. | ||
* | ||
* @returns {Function} - a function that wraps the cache query or original | ||
* callback. | ||
*/ | ||
function HttpCache(callback, duration = HTTP_CACHE_DEFAULT_TIMEOUT) { | ||
const cache = new Map(); | ||
|
||
function read(id, parameters, cacheBust = false) { | ||
const key = serialize(id, parameters); | ||
|
||
// if the cache has been populated return the value from memory | ||
if (cache.has(key) && !cacheBust) { | ||
return cache.get(key); | ||
} | ||
|
||
// call the callback to get the result and cache it | ||
const promise = callback(id, parameters); | ||
cache.set(key, promise); | ||
|
||
// remove the result from the cache after a duration. Repeated only once | ||
$interval(() => cache.delete(key), duration, 1); | ||
|
||
return promise; | ||
} | ||
|
||
return read; | ||
} | ||
|
||
return HttpCache; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.