@@ -89,7 +89,72 @@ engine.weight = function (coll) {
89
89
return hasPromise ? Promise . all ( res ) : res ;
90
90
} ;
91
91
92
+ // Object for storing received scores
92
93
const weightCache = { } ;
94
+ // Object for storing fetch promises.
95
+ const requestCache = { } ;
96
+ // Duration of data storage in cache.
97
+ const cacheStorageTime = 3600000 ; // 1 hour = 60 * 60 * 1000
98
+
99
+ /**
100
+ * Caches score.
101
+ * @param {string } key - key to store score in cache.
102
+ * @param {number|Promise } value - value of score or promise of value.
103
+ */
104
+ function putScoreToCache ( key , value ) {
105
+ weightCache [ key ] = {
106
+ timestamp : Date . now ( ) ,
107
+ value
108
+ } ;
109
+ }
110
+
111
+ /**
112
+ * Checks if there is an unexpired score in the cache.
113
+ * @param {string } key - key to store score in cache.
114
+ * @return {boolean|undefined }
115
+ */
116
+ function hasScoreInCache ( key ) {
117
+ return weightCache [ key ] && Date . now ( ) - weightCache [ key ] . timestamp < cacheStorageTime ;
118
+ }
119
+
120
+ /**
121
+ * Returns a score or promise of score from the cache.
122
+ * @param {string } key - key to store score in cache.
123
+ * @return {number | Promise }
124
+ */
125
+ function getScoreFromCache ( key ) {
126
+ return weightCache [ key ] . value ;
127
+ }
128
+
129
+ /**
130
+ * fetch() wrapper for caching server responses.
131
+ * @param {string } url - a URL of the resource you want to fetch.
132
+ * @param {object } [options] - optional object containing any custom settings
133
+ * that you want to apply to the request.
134
+ * @return {Promise }
135
+ */
136
+ function fetchWithCache ( url , options ) {
137
+ const requestKey = [
138
+ url + ( options ? JSON . stringify ( options ) : '' )
139
+ ] . join ( '|' ) ;
140
+
141
+ const timestamp = Date . now ( ) ;
142
+ for ( const key in requestCache ) {
143
+ if ( timestamp - requestCache [ key ] . timestamp > cacheStorageTime ) {
144
+ // Remove responses older than an hour
145
+ delete requestCache [ key ] ;
146
+ }
147
+ }
148
+
149
+ if ( ! requestCache [ requestKey ] ) {
150
+ requestCache [ requestKey ] = {
151
+ timestamp,
152
+ promise : options ? fetch ( url , options ) : fetch ( url )
153
+ } ;
154
+ }
155
+
156
+ return requestCache [ requestKey ] . promise ;
157
+ }
93
158
94
159
/**
95
160
* Adds the value of score or its promise received from a corresponding value
@@ -110,8 +175,8 @@ function addWeightFromCorrespondingResourcesToResult(res, ctx, questionnaire, vs
110
175
questionnaire ?. url || questionnaire ?. id , vsURL , code , system
111
176
] . join ( '|' ) ;
112
177
113
- if ( Object . prototype . hasOwnProperty . call ( weightCache , cacheKey ) ) {
114
- score = weightCache [ cacheKey ] ;
178
+ if ( hasScoreInCache ( cacheKey ) ) {
179
+ score = getScoreFromCache ( cacheKey ) ;
115
180
} else {
116
181
if ( code ) {
117
182
if ( vsURL ) {
@@ -124,7 +189,7 @@ function addWeightFromCorrespondingResourcesToResult(res, ctx, questionnaire, vs
124
189
125
190
if ( containedVS ) {
126
191
if ( ! containedVS . expansion ) {
127
- score = fetch ( `${ getTerminologyUrl ( ctx ) } /ValueSet/$expand` , {
192
+ score = fetchWithCache ( `${ getTerminologyUrl ( ctx ) } /ValueSet/$expand` , {
128
193
method : 'POST' ,
129
194
headers : {
130
195
'Accept' : 'application/fhir+json' ,
@@ -153,7 +218,7 @@ function addWeightFromCorrespondingResourcesToResult(res, ctx, questionnaire, vs
153
218
) ;
154
219
}
155
220
} else {
156
- score = fetch ( `${ getTerminologyUrl ( ctx ) } /ValueSet/$expand?` + new URLSearchParams ( {
221
+ score = fetchWithCache ( `${ getTerminologyUrl ( ctx ) } /ValueSet/$expand?` + new URLSearchParams ( {
157
222
url : vsURL ,
158
223
property : 'itemWeight'
159
224
} , {
@@ -195,7 +260,7 @@ function addWeightFromCorrespondingResourcesToResult(res, ctx, questionnaire, vs
195
260
}
196
261
}
197
262
198
- weightCache [ cacheKey ] = score ;
263
+ putScoreToCache ( cacheKey , score ) ;
199
264
}
200
265
201
266
if ( score !== undefined ) {
@@ -216,7 +281,7 @@ function addWeightFromCorrespondingResourcesToResult(res, ctx, questionnaire, vs
216
281
* @return {Promise<number|undefined> }
217
282
*/
218
283
function getWeightFromTerminologyCodeSet ( ctx , code , system ) {
219
- return fetch ( `${ getTerminologyUrl ( ctx ) } /CodeSystem/$lookup?` + new URLSearchParams ( {
284
+ return fetchWithCache ( `${ getTerminologyUrl ( ctx ) } /CodeSystem/$lookup?` + new URLSearchParams ( {
220
285
code, system, property : 'itemWeight'
221
286
} , {
222
287
headers : {
0 commit comments