petty-cache 3.4.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [3.6.0] - 2026-02-12
10
+ ### Changed
11
+ - Added the ability for `pettyCache.get`, `pettyCache.set`, and `pettyCache.patch` functions to support callbacks and promises.
12
+
13
+ ## [3.5.0] - 2025-05-01
14
+ ### Changed
15
+ - Added the ability for `pettyCache.del` functions to support callbacks and promises.
16
+
9
17
  ## [3.4.0] - 2025-02-21
10
18
  ### Changed
11
19
  - Added the ability for `pettyCache.mutex` functions to support callbacks and promises.
package/LICENSE CHANGED
@@ -1,201 +1,21 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but
32
- not limited to compiled object code, generated documentation,
33
- and conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work
38
- (an example is provided in the Appendix below).
39
-
40
- "Derivative Works" shall mean any work, whether in Source or Object
41
- form, that is based on (or derived from) the Work and for which the
42
- editorial revisions, annotations, elaborations, or other modifications
43
- represent, as a whole, an original work of authorship. For the purposes
44
- of this License, Derivative Works shall not include works that remain
45
- separable from, or merely link (or bind by name) to the interfaces of,
46
- the Work and Derivative Works thereof.
47
-
48
- "Contribution" shall mean any work of authorship, including
49
- the original version of the Work and any modifications or additions
50
- to that Work or Derivative Works thereof, that is intentionally
51
- submitted to Licensor for inclusion in the Work by the copyright owner
52
- or by an individual or Legal Entity authorized to submit on behalf of
53
- the copyright owner. For the purposes of this definition, "submitted"
54
- means any form of electronic, verbal, or written communication sent
55
- to the Licensor or its representatives, including but not limited to
56
- communication on electronic mailing lists, source code control systems,
57
- and issue tracking systems that are managed by, or on behalf of, the
58
- Licensor for the purpose of discussing and improving the Work, but
59
- excluding communication that is conspicuously marked or otherwise
60
- designated in writing by the copyright owner as "Not a Contribution."
61
-
62
- "Contributor" shall mean Licensor and any individual or Legal Entity
63
- on behalf of whom a Contribution has been received by Licensor and
64
- subsequently incorporated within the Work.
65
-
66
- 2. Grant of Copyright License. Subject to the terms and conditions of
67
- this License, each Contributor hereby grants to You a perpetual,
68
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
- copyright license to reproduce, prepare Derivative Works of,
70
- publicly display, publicly perform, sublicense, and distribute the
71
- Work and such Derivative Works in Source or Object form.
72
-
73
- 3. Grant of Patent License. Subject to the terms and conditions of
74
- this License, each Contributor hereby grants to You a perpetual,
75
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
- (except as stated in this section) patent license to make, have made,
77
- use, offer to sell, sell, import, and otherwise transfer the Work,
78
- where such license applies only to those patent claims licensable
79
- by such Contributor that are necessarily infringed by their
80
- Contribution(s) alone or by combination of their Contribution(s)
81
- with the Work to which such Contribution(s) was submitted. If You
82
- institute patent litigation against any entity (including a
83
- cross-claim or counterclaim in a lawsuit) alleging that the Work
84
- or a Contribution incorporated within the Work constitutes direct
85
- or contributory patent infringement, then any patent licenses
86
- granted to You under this License for that Work shall terminate
87
- as of the date such litigation is filed.
88
-
89
- 4. Redistribution. You may reproduce and distribute copies of the
90
- Work or Derivative Works thereof in any medium, with or without
91
- modifications, and in Source or Object form, provided that You
92
- meet the following conditions:
93
-
94
- (a) You must give any other recipients of the Work or
95
- Derivative Works a copy of this License; and
96
-
97
- (b) You must cause any modified files to carry prominent notices
98
- stating that You changed the files; and
99
-
100
- (c) You must retain, in the Source form of any Derivative Works
101
- that You distribute, all copyright, patent, trademark, and
102
- attribution notices from the Source form of the Work,
103
- excluding those notices that do not pertain to any part of
104
- the Derivative Works; and
105
-
106
- (d) If the Work includes a "NOTICE" text file as part of its
107
- distribution, then any Derivative Works that You distribute must
108
- include a readable copy of the attribution notices contained
109
- within such NOTICE file, excluding those notices that do not
110
- pertain to any part of the Derivative Works, in at least one
111
- of the following places: within a NOTICE text file distributed
112
- as part of the Derivative Works; within the Source form or
113
- documentation, if provided along with the Derivative Works; or,
114
- within a display generated by the Derivative Works, if and
115
- wherever such third-party notices normally appear. The contents
116
- of the NOTICE file are for informational purposes only and
117
- do not modify the License. You may add Your own attribution
118
- notices within Derivative Works that You distribute, alongside
119
- or as an addendum to the NOTICE text from the Work, provided
120
- that such additional attribution notices cannot be construed
121
- as modifying the License.
122
-
123
- You may add Your own copyright statement to Your modifications and
124
- may provide additional or different license terms and conditions
125
- for use, reproduction, or distribution of Your modifications, or
126
- for any such Derivative Works as a whole, provided Your use,
127
- reproduction, and distribution of the Work otherwise complies with
128
- the conditions stated in this License.
129
-
130
- 5. Submission of Contributions. Unless You explicitly state otherwise,
131
- any Contribution intentionally submitted for inclusion in the Work
132
- by You to the Licensor shall be under the terms and conditions of
133
- this License, without any additional terms or conditions.
134
- Notwithstanding the above, nothing herein shall supersede or modify
135
- the terms of any separate license agreement you may have executed
136
- with Licensor regarding such Contributions.
137
-
138
- 6. Trademarks. This License does not grant permission to use the trade
139
- names, trademarks, service marks, or product names of the Licensor,
140
- except as required for reasonable and customary use in describing the
141
- origin of the Work and reproducing the content of the NOTICE file.
142
-
143
- 7. Disclaimer of Warranty. Unless required by applicable law or
144
- agreed to in writing, Licensor provides the Work (and each
145
- Contributor provides its Contributions) on an "AS IS" BASIS,
146
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
- implied, including, without limitation, any warranties or conditions
148
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
- PARTICULAR PURPOSE. You are solely responsible for determining the
150
- appropriateness of using or redistributing the Work and assume any
151
- risks associated with Your exercise of permissions under this License.
152
-
153
- 8. Limitation of Liability. In no event and under no legal theory,
154
- whether in tort (including negligence), contract, or otherwise,
155
- unless required by applicable law (such as deliberate and grossly
156
- negligent acts) or agreed to in writing, shall any Contributor be
157
- liable to You for damages, including any direct, indirect, special,
158
- incidental, or consequential damages of any character arising as a
159
- result of this License or out of the use or inability to use the
160
- Work (including but not limited to damages for loss of goodwill,
161
- work stoppage, computer failure or malfunction, or any and all
162
- other commercial damages or losses), even if such Contributor
163
- has been advised of the possibility of such damages.
164
-
165
- 9. Accepting Warranty or Additional Liability. While redistributing
166
- the Work or Derivative Works thereof, You may choose to offer,
167
- and charge a fee for, acceptance of support, warranty, indemnity,
168
- or other liability obligations and/or rights consistent with this
169
- License. However, in accepting such obligations, You may act only
170
- on Your own behalf and on Your sole responsibility, not on behalf
171
- of any other Contributor, and only if You agree to indemnify,
172
- defend, and hold each Contributor harmless for any liability
173
- incurred by, or claims asserted against, such Contributor by reason
174
- of your accepting any such warranty or additional liability.
175
-
176
- END OF TERMS AND CONDITIONS
177
-
178
- APPENDIX: How to apply the Apache License to your work.
179
-
180
- To apply the Apache License to your work, attach the following
181
- boilerplate notice, with the fields enclosed by brackets "{}"
182
- replaced with your own identifying information. (Don't include
183
- the brackets!) The text should be enclosed in the appropriate
184
- comment syntax for the file format. We also recommend that a
185
- file or class name and description of purpose be included on the
186
- same "printed page" as the copyright notice for easier
187
- identification within third-party archives.
188
-
189
- Copyright {yyyy} {name of copyright owner}
190
-
191
- Licensed under the Apache License, Version 2.0 (the "License");
192
- you may not use this file except in compliance with the License.
193
- You may obtain a copy of the License at
194
-
195
- http://www.apache.org/licenses/LICENSE-2.0
196
-
197
- Unless required by applicable law or agreed to in writing, software
198
- distributed under the License is distributed on an "AS IS" BASIS,
199
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
- See the License for the specific language governing permissions and
201
- limitations under the License.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Stores.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # petty-cache
2
2
 
3
- [![Build Status](https://github.com/mediocre/petty-cache/actions/workflows/continuousIntegration.yaml/badge.svg?branch=main)](https://github.com/mediocre/petty-cache/actions?query=workflow%3Abuild+branch%3Amain)
4
- [![Coverage Status](https://coveralls.io/repos/github/mediocre/petty-cache/badge.svg?branch=main)](https://coveralls.io/github/mediocre/petty-cache?branch=main)
3
+ [![Build Status](https://github.com/stores-com/petty-cache/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/stores-com/petty-cache/actions?query=workflow%3Abuild+branch%3Amain)
4
+ [![Coverage Status](https://coveralls.io/repos/github/stores-com/petty-cache/badge.svg?branch=main)](https://coveralls.io/github/stores-com/petty-cache?branch=main)
5
5
 
6
6
  A cache module for Node.js that uses a two-level cache (in-memory cache for recently accessed data plus Redis for distributed caching) with automatic serialization plus some extra features to avoid cache stampedes and thundering herds.
7
7
 
@@ -28,8 +28,8 @@ Provides a pool of distributed locks with the ability to release a slot back to
28
28
 
29
29
  ```javascript
30
30
  // Setup petty-cache
31
- var PettyCache = require('petty-cache');
32
- var pettyCache = new PettyCache();
31
+ const PettyCache = require('petty-cache');
32
+ const pettyCache = new PettyCache();
33
33
 
34
34
  // Fetch some data
35
35
  pettyCache.fetch('key', function(callback) {
@@ -71,7 +71,7 @@ Attempts to retrieve the values of the keys specified in the `keys` array. Any k
71
71
  ```javascript
72
72
  // Let's assume a and b are already cached as 1 and 2
73
73
  pettyCache.bulkFetch(['a', 'b', 'c', 'd'], function(keys, callback) {
74
- var results = {};
74
+ const results = {};
75
75
 
76
76
  keys.forEach(function(key) {
77
77
  results[key] = key.toUpperCase();
@@ -145,6 +145,24 @@ pettyCache.set({ key1: 'one', key2: 2, key3: 'three' }, function(err) {
145
145
  }
146
146
  ```
147
147
 
148
+ ### pettyCache.del(key, [callback])
149
+
150
+ Deletes a value from both the in-memory cache and Redis. Supports both callbacks and promises.
151
+
152
+ **Example**
153
+
154
+ ```javascript
155
+ pettyCache.del('key', function(err) {
156
+ if (err) {
157
+ // Handle redis error
158
+ }
159
+ });
160
+ ```
161
+
162
+ ```javascript
163
+ await pettyCache.del('key');
164
+ ```
165
+
148
166
  ### pettyCache.fetch(key, cacheMissFunction, [options,] callback)
149
167
 
150
168
  Attempts to retrieve the value from cache at the specified key. If it doesn't exist, it executes the specified cacheMissFunction that takes two parameters: an error and a value. `cacheMissFunction` should retrieve the expected value for the key from another source and pass it to the given callback. Either way, the resulting error or value is passed to `callback`.
@@ -222,9 +240,9 @@ pettyCache.fetchAndRefresh('key', function(callback) {
222
240
  }
223
241
  ```
224
242
 
225
- ### pettyCache.get(key, callback)
243
+ ### pettyCache.get(key, [callback])
226
244
 
227
- Attempts to retrieve the value from cache at the specified key. Returns `null` if the key doesn't exist.
245
+ Attempts to retrieve the value from cache at the specified key. Returns `null` if the key doesn't exist. Supports both callbacks and promises.
228
246
 
229
247
  **Example**
230
248
 
@@ -235,14 +253,18 @@ pettyCache.get('key', function(err, value) {
235
253
  });
236
254
  ```
237
255
 
238
- ### pettyCache.patch(key, value, [options,] callback)
256
+ ```javascript
257
+ const value = await pettyCache.get('key');
258
+ ```
259
+
260
+ ### pettyCache.patch(key, value, [options, [callback]])
239
261
 
240
- Updates an object at the given key with the property values provided. Sends an error to the callback if the key does not exist.
262
+ Updates an object at the given key with the property values provided. Sends an error to the callback if the key does not exist. Supports both callbacks and promises.
241
263
 
242
264
  **Example**
243
265
 
244
266
  ```javascript
245
- pettyCache.patch('key', { a: 1 }, function(callback) {
267
+ pettyCache.patch('key', { a: 1 }, function(err) {
246
268
  if (err) {
247
269
  // Handle redis or key not found error
248
270
  }
@@ -251,6 +273,10 @@ pettyCache.patch('key', { a: 1 }, function(callback) {
251
273
  });
252
274
  ```
253
275
 
276
+ ```javascript
277
+ await pettyCache.patch('key', { a: 1 });
278
+ ```
279
+
254
280
  **Options**
255
281
 
256
282
  ```
@@ -269,9 +295,9 @@ pettyCache.patch('key', { a: 1 }, function(callback) {
269
295
  }
270
296
  ```
271
297
 
272
- ### pettyCache.set(key, value, [options,] callback)
298
+ ### pettyCache.set(key, value, [options, [callback]])
273
299
 
274
- Unconditionally sets a value for a given key.
300
+ Unconditionally sets a value for a given key. Supports both callbacks and promises.
275
301
 
276
302
  **Example**
277
303
 
@@ -283,6 +309,10 @@ pettyCache.set('key', { a: 'b' }, function(err) {
283
309
  });
284
310
  ```
285
311
 
312
+ ```javascript
313
+ await pettyCache.set('key', { a: 'b' });
314
+ ```
315
+
286
316
  **Options**
287
317
 
288
318
  ```
@@ -305,7 +335,7 @@ pettyCache.set('key', { a: 'b' }, function(err) {
305
335
 
306
336
  ### pettyCache.mutex.lock(key, [options, [callback]])
307
337
 
308
- Attempts to acquire a distributed lock for the specified key. Optionally retries a specified number of times by waiting a specified amount of time between attempts.
338
+ Attempts to acquire a distributed lock for the specified key. Optionally retries a specified number of times by waiting a specified amount of time between attempts. Supports both callbacks and promises.
309
339
 
310
340
  ```javascript
311
341
  pettyCache.mutex.lock('key', { retry: { interval: 100, times: 5 }, ttl: 1000 }, function(err) {
@@ -318,6 +348,13 @@ pettyCache.mutex.lock('key', { retry: { interval: 100, times: 5 }, ttl: 1000 },
318
348
  });
319
349
  ```
320
350
 
351
+ ```javascript
352
+ await pettyCache.mutex.lock('key', { retry: { interval: 100, times: 5 }, ttl: 1000 });
353
+
354
+ // We were able to acquire the lock. Do work and then unlock.
355
+ await pettyCache.mutex.unlock('key');
356
+ ```
357
+
321
358
  **Options**
322
359
 
323
360
  ```javascript
@@ -332,7 +369,7 @@ pettyCache.mutex.lock('key', { retry: { interval: 100, times: 5 }, ttl: 1000 },
332
369
 
333
370
  ### pettyCache.mutex.unlock(key, [callback])
334
371
 
335
- Releases the distributed lock for the specified key.
372
+ Releases the distributed lock for the specified key. Supports both callbacks and promises.
336
373
 
337
374
  ```javascript
338
375
  pettyCache.mutex.unlock('key', function(err) {
@@ -342,6 +379,10 @@ pettyCache.mutex.unlock('key', function(err) {
342
379
  });
343
380
  ```
344
381
 
382
+ ```javascript
383
+ await pettyCache.mutex.unlock('key');
384
+ ```
385
+
345
386
  ## Semaphore
346
387
 
347
388
  Provides a pool of distributed locks. Once a consumer acquires a lock they have the ability to release the lock back to the pool or mark the lock as "consumed" so that it's not used again.
@@ -471,6 +512,6 @@ pettyCache.semaphore.retrieveOrCreate('key', { size: 10 }, function(err) {
471
512
 
472
513
  ```javascript
473
514
  {
474
- size: 1 || function() { var x = 1 + 1; callback(null, x); } // The number of locks to create in the semaphore's pool. Optionally, size can be a `callback(err, size)` function.
515
+ size: 1 || function() { const x = 1 + 1; callback(null, x); } // The number of locks to create in the semaphore's pool. Optionally, size can be a `callback(err, size)` function.
475
516
  }
476
517
  ```
@@ -0,0 +1,30 @@
1
+ const globals = require('globals');
2
+ const js = require('@eslint/js');
3
+
4
+ module.exports = [
5
+ js.configs.recommended,
6
+ {
7
+ languageOptions: {
8
+ globals: {
9
+ ...globals.node
10
+ }
11
+ },
12
+ rules: {
13
+ 'brace-style': ['error', '1tbs', { allowSingleLine: true }],
14
+ 'comma-dangle': ['error', 'never'],
15
+ 'dot-notation': 'error',
16
+ 'no-console': 'error',
17
+ 'no-inline-comments': 'warn',
18
+ 'no-trailing-spaces': 'error',
19
+ 'no-unused-vars': ['error', { caughtErrors: 'none' }],
20
+ 'object-curly-spacing': ['error', 'always'],
21
+ quotes: ['error', 'single'],
22
+ semi: ['error', 'always'],
23
+ 'space-before-function-paren': ['error', {
24
+ anonymous: 'never',
25
+ named: 'never',
26
+ asyncArrow: 'always'
27
+ }]
28
+ }
29
+ }
30
+ ];
package/index.js CHANGED
@@ -13,20 +13,21 @@ function PettyCache() {
13
13
  redisClient = redis.createClient(...arguments);
14
14
  }
15
15
 
16
+ //eslint-disable-next-line no-console
16
17
  redisClient.on('error', err => console.warn(`Warning: Redis reported a client error: ${err}`));
17
18
 
18
19
  function bulkGetFromRedis(keys, callback) {
19
20
  // Try to get values from Redis
20
- redisClient.mget(keys, function(err, data) {
21
+ redisClient.mget(keys, (err, data) => {
21
22
  if (err) {
22
23
  return callback(err);
23
24
  }
24
25
 
25
26
  const values = {};
26
27
 
27
- for (var i = 0; i < keys.length; i++) {
28
- var key = keys[i];
29
- var value = data[i];
28
+ for (let i = 0; i < keys.length; i++) {
29
+ const key = keys[i];
30
+ const value = data[i];
30
31
 
31
32
  if (value === null) {
32
33
  values[key] = { exists: false };
@@ -60,7 +61,7 @@ function PettyCache() {
60
61
 
61
62
  function getFromRedis(key, callback) {
62
63
  // Try to get value from Redis
63
- redisClient.get(key, function(err, data) {
64
+ redisClient.get(key, (err, data) => {
64
65
  if (err) {
65
66
  return callback(err);
66
67
  }
@@ -102,7 +103,7 @@ function PettyCache() {
102
103
  /**
103
104
  * @param {Array} keys - An array of keys.
104
105
  */
105
- this.bulkFetch = function(keys, func, options, callback) {
106
+ this.bulkFetch = (keys, func, options, callback) => {
106
107
  // Options are optional
107
108
  if (!callback) {
108
109
  callback = options;
@@ -118,7 +119,7 @@ function PettyCache() {
118
119
  const values = {};
119
120
 
120
121
  // Try to get values from memory cache
121
- for (var i = _keys.length - 1; i >= 0; i--) {
122
+ for (let i = _keys.length - 1; i >= 0; i--) {
122
123
  const key = _keys[i];
123
124
  const result = getFromMemoryCache(key);
124
125
 
@@ -136,12 +137,12 @@ function PettyCache() {
136
137
  const _this = this;
137
138
 
138
139
  // Try to get values from Redis
139
- bulkGetFromRedis(_keys, function(err, results) {
140
+ bulkGetFromRedis(_keys, (err, results) => {
140
141
  if (err) {
141
142
  return callback(err);
142
143
  }
143
144
 
144
- for (var i = _keys.length - 1; i >= 0; i--) {
145
+ for (let i = _keys.length - 1; i >= 0; i--) {
145
146
  const key = _keys[i];
146
147
  const result = results[key];
147
148
 
@@ -160,7 +161,7 @@ function PettyCache() {
160
161
  }
161
162
 
162
163
  // Execute the specified function for remaining keys
163
- func(_keys, function(err, data) {
164
+ func(_keys, (err, data) => {
164
165
  if (err) {
165
166
  return callback(err);
166
167
  }
@@ -175,7 +176,7 @@ function PettyCache() {
175
176
  /**
176
177
  * @param {Array} keys - An array of keys.
177
178
  */
178
- this.bulkGet = function(keys, callback) {
179
+ this.bulkGet = (keys, callback) => {
179
180
  // If there aren't any keys, return
180
181
  if (!keys.length) {
181
182
  return callback(null, {});
@@ -185,7 +186,7 @@ function PettyCache() {
185
186
  const values = {};
186
187
 
187
188
  // Try to get values from memory cache
188
- for (var i = _keys.length - 1; i >= 0; i--) {
189
+ for (let i = _keys.length - 1; i >= 0; i--) {
189
190
  const key = _keys[i];
190
191
  const result = getFromMemoryCache(key);
191
192
 
@@ -201,14 +202,14 @@ function PettyCache() {
201
202
  }
202
203
 
203
204
  // Try to get values from Redis
204
- bulkGetFromRedis(_keys, function(err, results) {
205
+ bulkGetFromRedis(_keys, (err, results) => {
205
206
  if (err) {
206
207
  return callback(err);
207
208
  }
208
209
 
209
- for (var i = 0; i < _keys.length; i++) {
210
- var key = _keys[i];
211
- var result = results[key];
210
+ for (let i = 0; i < _keys.length; i++) {
211
+ const key = _keys[i];
212
+ const result = results[key];
212
213
 
213
214
  if (!result.exists) {
214
215
  values[key] = null;
@@ -225,7 +226,7 @@ function PettyCache() {
225
226
  });
226
227
  };
227
228
 
228
- this.bulkSet = function(values, options, callback) {
229
+ this.bulkSet = (values, options, callback) => {
229
230
  // Options are optional
230
231
  if (!callback) {
231
232
  callback = options;
@@ -248,25 +249,35 @@ function PettyCache() {
248
249
  batch.psetex(key, random(ttl.min, ttl.max), PettyCache.stringify(value));
249
250
  });
250
251
 
251
- batch.exec(function(err) {
252
+ batch.exec((err) => {
252
253
  callback(err);
253
254
  });
254
255
  };
255
256
 
256
- this.del = function(key, callback) {
257
- redisClient.del(key, function(err) {
258
- if (err) {
259
- return callback(err);
260
- }
257
+ this.del = (key, callback) => {
258
+ const executor = () => {
259
+ return new Promise((resolve, reject) => {
260
+ redisClient.del(key, (err) => {
261
+ if (err) {
262
+ return reject(err);
263
+ }
261
264
 
262
- memoryCache.del(key);
263
- callback();
264
- });
265
+ memoryCache.del(key);
266
+ resolve();
267
+ });
268
+ });
269
+ };
270
+
271
+ if (callback) {
272
+ executor().then(result => callback(null, result)).catch(callback);
273
+ } else {
274
+ return executor();
275
+ }
265
276
  };
266
277
 
267
278
  // Returns data from cache if available;
268
279
  // otherwise executes the specified function and places the results in cache before returning the data.
269
- this.fetch = function(key, func, options, callback) {
280
+ this.fetch = (key, func, options, callback) => {
270
281
  options = options || {};
271
282
 
272
283
  if (typeof options === 'function') {
@@ -275,10 +286,10 @@ function PettyCache() {
275
286
  }
276
287
 
277
288
  // Default callback is a noop
278
- callback = callback || function() {};
289
+ callback = callback || (() => {});
279
290
 
280
291
  // Try to get value from memory cache
281
- var result = getFromMemoryCache(key);
292
+ let result = getFromMemoryCache(key);
282
293
 
283
294
  // Return value from memory cache if it exists
284
295
  if (result.exists) {
@@ -288,8 +299,8 @@ function PettyCache() {
288
299
  const _this = this;
289
300
 
290
301
  // Double-checked locking: http://en.wikipedia.org/wiki/Double-checked_locking
291
- lock(`fetch-memory-cache-lock-${key}`, function(releaseMemoryCacheLock) {
292
- async.reflect(function(callback) {
302
+ lock(`fetch-memory-cache-lock-${key}`, (releaseMemoryCacheLock) => {
303
+ async.reflect((callback) => {
293
304
  // Try to get value from memory cache
294
305
  result = getFromMemoryCache(key);
295
306
 
@@ -299,7 +310,7 @@ function PettyCache() {
299
310
  }
300
311
 
301
312
  // Try to get value from Redis
302
- getFromRedis(key, function(err, result) {
313
+ getFromRedis(key, (err, result) => {
303
314
  if (err) {
304
315
  return callback(err);
305
316
  }
@@ -311,8 +322,8 @@ function PettyCache() {
311
322
  }
312
323
 
313
324
  // Double-checked locking: http://en.wikipedia.org/wiki/Double-checked_locking
314
- lock(`fetch-redis-lock-${key}`, function(releaseRedisLock) {
315
- async.reflect(function(callback) {
325
+ lock(`fetch-redis-lock-${key}`, (releaseRedisLock) => {
326
+ async.reflect((callback) => {
316
327
  // Try to get value from memory cache
317
328
  result = getFromMemoryCache(key);
318
329
 
@@ -322,7 +333,7 @@ function PettyCache() {
322
333
  }
323
334
 
324
335
  // Try to get value from Redis
325
- getFromRedis(key, async function(err, result) {
336
+ getFromRedis(key, async (err, result) => {
326
337
  if (err) {
327
338
  return callback(err);
328
339
  }
@@ -339,7 +350,7 @@ function PettyCache() {
339
350
  try {
340
351
  const data = await func();
341
352
 
342
- _this.set(key, data, options, function(err) {
353
+ _this.set(key, data, options, (err) => {
343
354
  callback(err, data);
344
355
  });
345
356
  } catch(err) {
@@ -347,18 +358,18 @@ function PettyCache() {
347
358
  }
348
359
  } else {
349
360
  // If the function has arguments, there was a callback provided
350
- func(function(err, data) {
361
+ func((err, data) => {
351
362
  if (err) {
352
363
  return callback(err);
353
364
  }
354
365
 
355
- _this.set(key, data, options, function(err) {
366
+ _this.set(key, data, options, (err) => {
356
367
  callback(err, data);
357
368
  });
358
369
  });
359
370
  }
360
371
  });
361
- })(releaseRedisLock(function(err, result) {
372
+ })(releaseRedisLock((err, result) => {
362
373
  if (result.error) {
363
374
  return callback(result.error);
364
375
  }
@@ -367,7 +378,7 @@ function PettyCache() {
367
378
  }));
368
379
  });
369
380
  });
370
- })(releaseMemoryCacheLock(function(err, result) {
381
+ })(releaseMemoryCacheLock((err, result) => {
371
382
  if (result.error) {
372
383
  return callback(result.error);
373
384
  }
@@ -377,7 +388,7 @@ function PettyCache() {
377
388
  });
378
389
  };
379
390
 
380
- this.fetchAndRefresh = function(key, func, options, callback) {
391
+ this.fetchAndRefresh = (key, func, options, callback) => {
381
392
  options = options || {};
382
393
 
383
394
  if (typeof options === 'function') {
@@ -389,22 +400,22 @@ function PettyCache() {
389
400
  const ttl = getTtl(options);
390
401
 
391
402
  // Default callback is a noop
392
- callback = callback || function() {};
403
+ callback = callback || (() => {});
393
404
 
394
405
  const _this = this;
395
406
 
396
407
  if (!intervals[key]) {
397
408
  const delay = ttl.min / 2;
398
409
 
399
- intervals[key] = setInterval(function() {
410
+ intervals[key] = setInterval(() => {
400
411
  // This distributed lock prevents multiple clients from executing func at the same time
401
- _this.mutex.lock(`interval-${key}`, { ttl: delay - 100 }, function(err) {
412
+ _this.mutex.lock(`interval-${key}`, { ttl: delay - 100 }, (err) => {
402
413
  if (err) {
403
414
  return;
404
415
  }
405
416
 
406
417
  // Execute the specified function and update cache
407
- func(function(err, data) {
418
+ func((err, data) => {
408
419
  if (err) {
409
420
  return;
410
421
  }
@@ -418,46 +429,56 @@ function PettyCache() {
418
429
  this.fetch(key, func, options, callback);
419
430
  };
420
431
 
421
- this.get = function(key, callback) {
422
- // Try to get value from memory cache
423
- let result = getFromMemoryCache(key);
424
-
425
- // Return value from memory cache if it exists
426
- if (result.exists) {
427
- return callback(null, result.value);
428
- }
429
-
430
- // Double-checked locking: http://en.wikipedia.org/wiki/Double-checked_locking
431
- lock(`get-memory-cache-lock-${key}`, function(releaseMemoryCacheLock) {
432
- async.reflect(function(callback) {
432
+ this.get = (key, callback) => {
433
+ const executor = () => {
434
+ return new Promise((resolve, reject) => {
433
435
  // Try to get value from memory cache
434
- result = getFromMemoryCache(key);
436
+ let result = getFromMemoryCache(key);
435
437
 
436
438
  // Return value from memory cache if it exists
437
439
  if (result.exists) {
438
- return callback(null, result.value);
440
+ return resolve(result.value);
439
441
  }
440
442
 
441
- getFromRedis(key, function(err, result) {
442
- if (err) {
443
- return callback(err);
444
- }
443
+ // Double-checked locking: http://en.wikipedia.org/wiki/Double-checked_locking
444
+ lock(`get-memory-cache-lock-${key}`, (releaseMemoryCacheLock) => {
445
+ async.reflect((callback) => {
446
+ // Try to get value from memory cache
447
+ result = getFromMemoryCache(key);
445
448
 
446
- if (!result.exists) {
447
- return callback(null, null);
448
- }
449
+ // Return value from memory cache if it exists
450
+ if (result.exists) {
451
+ return callback(null, result.value);
452
+ }
449
453
 
450
- memoryCache.put(key, result.value, random(2000, 5000));
451
- callback(null, result.value);
454
+ getFromRedis(key, (err, result) => {
455
+ if (err) {
456
+ return callback(err);
457
+ }
458
+
459
+ if (!result.exists) {
460
+ return callback(null, null);
461
+ }
462
+
463
+ memoryCache.put(key, result.value, random(2000, 5000));
464
+ callback(null, result.value);
465
+ });
466
+ })(releaseMemoryCacheLock((err, result) => {
467
+ if (result.error) {
468
+ return reject(result.error);
469
+ }
470
+
471
+ resolve(result.value);
472
+ }));
452
473
  });
453
- })(releaseMemoryCacheLock(function(err, result) {
454
- if (result.error) {
455
- return callback(result.error);
456
- }
474
+ });
475
+ };
457
476
 
458
- callback(null, result.value);
459
- }));
460
- });
477
+ if (callback) {
478
+ executor().then(result => callback(null, result)).catch(callback);
479
+ } else {
480
+ return executor();
481
+ }
461
482
  };
462
483
 
463
484
  this.mutex = {
@@ -478,7 +499,7 @@ function PettyCache() {
478
499
  const executor = () => {
479
500
  return new Promise((resolve, reject) => {
480
501
  async.retry({ interval: options.retry.interval, times: options.retry.times }, callback => {
481
- redisClient.set(key, '1', 'NX', 'PX', options.ttl, function(err, res) {
502
+ redisClient.set(key, '1', 'NX', 'PX', options.ttl, (err, res) => {
482
503
  if (err) {
483
504
  return callback(err);
484
505
  }
@@ -493,7 +514,7 @@ function PettyCache() {
493
514
 
494
515
  callback();
495
516
  });
496
- }, function(err) {
517
+ }, (err) => {
497
518
  if (err) {
498
519
  return reject(err);
499
520
  }
@@ -512,7 +533,7 @@ function PettyCache() {
512
533
  unlock: (key, callback) => {
513
534
  const executor = () => {
514
535
  return new Promise((resolve, reject) => {
515
- redisClient.del(key, function(err) {
536
+ redisClient.del(key, (err) => {
516
537
  if (err) {
517
538
  return reject(err);
518
539
  }
@@ -530,33 +551,51 @@ function PettyCache() {
530
551
  }
531
552
  };
532
553
 
533
- this.patch = function(key, value, options, callback) {
534
- if (!callback) {
554
+ this.patch = (key, value, options, callback) => {
555
+ if (!callback && typeof options === 'function') {
535
556
  callback = options;
536
557
  options = {};
537
558
  }
538
559
 
560
+ options = options || {};
561
+
539
562
  const _this = this;
540
563
 
541
- this.get(key, function(err, data) {
542
- if (err) {
543
- return callback(err);
544
- }
564
+ const executor = () => {
565
+ return new Promise((resolve, reject) => {
566
+ _this.get(key, (err, data) => {
567
+ if (err) {
568
+ return reject(err);
569
+ }
545
570
 
546
- if (!data) {
547
- return callback(new Error(`Key ${key} does not exist`));
548
- }
571
+ if (!data) {
572
+ return reject(new Error(`Key ${key} does not exist`));
573
+ }
549
574
 
550
- for (var k in value) {
551
- data[k] = value[k];
552
- }
575
+ for (let k in value) {
576
+ data[k] = value[k];
577
+ }
553
578
 
554
- _this.set(key, data, options, callback);
555
- });
579
+ _this.set(key, data, options, (err) => {
580
+ if (err) {
581
+ return reject(err);
582
+ }
583
+
584
+ resolve();
585
+ });
586
+ });
587
+ });
588
+ };
589
+
590
+ if (callback) {
591
+ executor().then(result => callback(null, result)).catch(callback);
592
+ } else {
593
+ return executor();
594
+ }
556
595
  };
557
596
 
558
597
  this.semaphore = {
559
- acquireLock: function(key, options, callback) {
598
+ acquireLock: (key, options, callback) => {
560
599
  // Options are optional
561
600
  if (!callback && typeof options === 'function') {
562
601
  callback = options;
@@ -572,14 +611,14 @@ function PettyCache() {
572
611
 
573
612
  const _this = this;
574
613
 
575
- async.retry({ interval: options.retry.interval, times: options.retry.times }, function(callback) {
614
+ async.retry({ interval: options.retry.interval, times: options.retry.times }, (callback) => {
576
615
  // Mutex lock around semaphore
577
- _this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, function(err) {
616
+ _this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, (err) => {
578
617
  if (err) {
579
618
  return callback(err);
580
619
  }
581
620
 
582
- redisClient.get(key, function(err, data) {
621
+ redisClient.get(key, (err, data) => {
583
622
  // If we encountered an error, unlock the mutex lock and return error
584
623
  if (err) {
585
624
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
@@ -590,10 +629,10 @@ function PettyCache() {
590
629
  return _this.mutex.unlock(`lock:${key}`, () => { callback(new Error(`Semaphore ${key} doesn't exist.`)); });
591
630
  }
592
631
 
593
- var pool = JSON.parse(data);
632
+ const pool = JSON.parse(data);
594
633
 
595
634
  // Try to find a slot that's available.
596
- var index = pool.findIndex(s => s.status === 'available');
635
+ let index = pool.findIndex(s => s.status === 'available');
597
636
 
598
637
  if (index === -1) {
599
638
  index = pool.findIndex(s => s.ttl <= Date.now());
@@ -606,7 +645,7 @@ function PettyCache() {
606
645
 
607
646
  pool[index] = { status: 'acquired', ttl: Date.now() + options.ttl };
608
647
 
609
- redisClient.set(key, JSON.stringify(pool), function(err) {
648
+ redisClient.set(key, JSON.stringify(pool), (err) => {
610
649
  if (err) {
611
650
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
612
651
  }
@@ -617,18 +656,18 @@ function PettyCache() {
617
656
  });
618
657
  }, callback);
619
658
  },
620
- consumeLock: function(key, index, callback) {
621
- callback = callback || function() {};
659
+ consumeLock: (key, index, callback) => {
660
+ callback = callback || (() => {});
622
661
 
623
662
  const _this = this;
624
663
 
625
664
  // Mutex lock around semaphore
626
- _this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, function(err) {
665
+ _this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, (err) => {
627
666
  if (err) {
628
667
  return callback(err);
629
668
  }
630
669
 
631
- redisClient.get(key, function(err, data) {
670
+ redisClient.get(key, (err, data) => {
632
671
  // If we encountered an error, unlock the mutex lock and return error
633
672
  if (err) {
634
673
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
@@ -639,7 +678,7 @@ function PettyCache() {
639
678
  return _this.mutex.unlock(`lock:${key}`, () => { callback(new Error(`Semaphore ${key} doesn't exist.`)); });
640
679
  }
641
680
 
642
- var pool = JSON.parse(data);
681
+ const pool = JSON.parse(data);
643
682
 
644
683
  // Ensure index exists.
645
684
  if (pool.length <= index) {
@@ -653,7 +692,7 @@ function PettyCache() {
653
692
  pool[index] = { status: 'available' };
654
693
  }
655
694
 
656
- redisClient.set(key, JSON.stringify(pool), function(err) {
695
+ redisClient.set(key, JSON.stringify(pool), (err) => {
657
696
  if (err) {
658
697
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
659
698
  }
@@ -663,17 +702,17 @@ function PettyCache() {
663
702
  });
664
703
  });
665
704
  },
666
- expand: function(key, size, callback) {
667
- callback = callback || function() {};
705
+ expand: (key, size, callback) => {
706
+ callback = callback || (() => {});
668
707
 
669
708
  const _this = this;
670
709
 
671
- _this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, function(err) {
710
+ _this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, (err) => {
672
711
  if (err) {
673
712
  return callback(err);
674
713
  }
675
714
 
676
- redisClient.get(key, function(err, data) {
715
+ redisClient.get(key, (err, data) => {
677
716
  // If we encountered an error, unlock the mutex lock and return error
678
717
  if (err) {
679
718
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
@@ -684,7 +723,7 @@ function PettyCache() {
684
723
  return _this.mutex.unlock(`lock:${key}`, () => { callback(new Error(`Semaphore ${key} doesn't exist.`)); });
685
724
  }
686
725
 
687
- var pool = JSON.parse(data);
726
+ let pool = JSON.parse(data);
688
727
 
689
728
  if (pool.length > size) {
690
729
  return _this.mutex.unlock(`lock:${key}`, () => { callback(new Error(`Cannot shrink pool, size is ${pool.length} and you requested a size of ${size}.`)); });
@@ -696,7 +735,7 @@ function PettyCache() {
696
735
 
697
736
  pool = pool.concat(Array(size - pool.length).fill({ status: 'available' }));
698
737
 
699
- redisClient.set(key, JSON.stringify(pool), function(err) {
738
+ redisClient.set(key, JSON.stringify(pool), (err) => {
700
739
  if (err) {
701
740
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
702
741
  }
@@ -706,18 +745,18 @@ function PettyCache() {
706
745
  });
707
746
  });
708
747
  },
709
- releaseLock: function(key, index, callback) {
710
- callback = callback || function() {};
748
+ releaseLock: (key, index, callback) => {
749
+ callback = callback || (() => {});
711
750
 
712
751
  const _this = this;
713
752
 
714
753
  // Mutex lock around semaphore
715
- _this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, function(err) {
754
+ _this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, (err) => {
716
755
  if (err) {
717
756
  return callback(err);
718
757
  }
719
758
 
720
- redisClient.get(key, function(err, data) {
759
+ redisClient.get(key, (err, data) => {
721
760
  // If we encountered an error, unlock the mutex lock and return error
722
761
  if (err) {
723
762
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
@@ -728,7 +767,7 @@ function PettyCache() {
728
767
  return _this.mutex.unlock(`lock:${key}`, () => { callback(new Error(`Semaphore ${key} doesn't exist.`)); });
729
768
  }
730
769
 
731
- var pool = JSON.parse(data);
770
+ const pool = JSON.parse(data);
732
771
 
733
772
  // Ensure index exists.
734
773
  if (pool.length <= index) {
@@ -737,7 +776,7 @@ function PettyCache() {
737
776
 
738
777
  pool[index] = { status: 'available' };
739
778
 
740
- redisClient.set(key, JSON.stringify(pool), function(err) {
779
+ redisClient.set(key, JSON.stringify(pool), (err) => {
741
780
  if (err) {
742
781
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
743
782
  }
@@ -747,19 +786,19 @@ function PettyCache() {
747
786
  });
748
787
  });
749
788
  },
750
- reset: function(key, callback) {
751
- callback = callback || function() {};
789
+ reset: (key, callback) => {
790
+ callback = callback || (() => {});
752
791
 
753
792
  const _this = this;
754
793
 
755
794
  // Mutex lock around semaphore
756
- this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, function(err) {
795
+ this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, (err) => {
757
796
  if (err) {
758
797
  return callback(err);
759
798
  }
760
799
 
761
800
  // Try to get previously created semaphore
762
- redisClient.get(key, function(err, data) {
801
+ redisClient.get(key, (err, data) => {
763
802
  // If we encountered an error, unlock the mutex lock and return error
764
803
  if (err) {
765
804
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
@@ -770,10 +809,10 @@ function PettyCache() {
770
809
  return _this.mutex.unlock(`lock:${key}`, () => { callback(new Error(`Semaphore ${key} doesn't exist.`)); });
771
810
  }
772
811
 
773
- var pool = JSON.parse(data);
812
+ let pool = JSON.parse(data);
774
813
  pool = Array(pool.length).fill({ status: 'available' });
775
814
 
776
- redisClient.set(key, JSON.stringify(pool), function(err) {
815
+ redisClient.set(key, JSON.stringify(pool), (err) => {
777
816
  if (err) {
778
817
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
779
818
  }
@@ -783,26 +822,26 @@ function PettyCache() {
783
822
  });
784
823
  });
785
824
  },
786
- retrieveOrCreate: function(key, options, callback) {
825
+ retrieveOrCreate: (key, options, callback) => {
787
826
  // Options are optional
788
827
  if (!callback && typeof options === 'function') {
789
828
  callback = options;
790
829
  options = {};
791
830
  }
792
831
 
793
- callback = callback || function() {};
832
+ callback = callback || (() => {});
794
833
  options = options || {};
795
834
 
796
835
  const _this = this;
797
836
 
798
837
  // Mutex lock around semaphore retrival or creation
799
- this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, function(err) {
838
+ this.mutex.lock(`lock:${key}`, { retry: { times: 100 } }, (err) => {
800
839
  if (err) {
801
840
  return callback(err);
802
841
  }
803
842
 
804
843
  // Try to get previously created semaphore
805
- redisClient.get(key, function(err, data) {
844
+ redisClient.get(key, (err, data) => {
806
845
  // If we encountered an error, unlock the mutex lock and return error
807
846
  if (err) {
808
847
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
@@ -813,7 +852,7 @@ function PettyCache() {
813
852
  return _this.mutex.unlock(`lock:${key}`, () => { callback(null, JSON.parse(data)); });
814
853
  }
815
854
 
816
- var getSize = function(callback) {
855
+ const getSize = (callback) => {
817
856
  if (typeof options.size === 'function') {
818
857
  return options.size(callback);
819
858
  }
@@ -821,15 +860,15 @@ function PettyCache() {
821
860
  callback(null, Object.prototype.hasOwnProperty.call(options, 'size') ? options.size : 1);
822
861
  };
823
862
 
824
- getSize(function(err, size) {
863
+ getSize((err, size) => {
825
864
  // If we encountered an error, unlock the mutex lock and return error
826
865
  if (err) {
827
866
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
828
867
  }
829
868
 
830
- var pool = Array(Math.max(size, 1)).fill({ status: 'available' });
869
+ const pool = Array(Math.max(size, 1)).fill({ status: 'available' });
831
870
 
832
- redisClient.set(key, JSON.stringify(pool), function(err) {
871
+ redisClient.set(key, JSON.stringify(pool), (err) => {
833
872
  if (err) {
834
873
  return _this.mutex.unlock(`lock:${key}`, () => { callback(err); });
835
874
  }
@@ -842,7 +881,7 @@ function PettyCache() {
842
881
  }
843
882
  };
844
883
 
845
- this.set = function(key, value, options, callback) {
884
+ this.set = (key, value, options, callback) => {
846
885
  options = options || {};
847
886
 
848
887
  if (typeof options === 'function') {
@@ -853,18 +892,31 @@ function PettyCache() {
853
892
  // Get TTL based on specified options
854
893
  const ttl = getTtl(options);
855
894
 
856
- // Default callback is a noop
857
- callback = callback || function() {};
895
+ const executor = () => {
896
+ return new Promise((resolve, reject) => {
897
+ // Store value in memory cache with a short expiration
898
+ memoryCache.put(key, value, random(2000, 5000));
899
+
900
+ // Store value in Redis
901
+ redisClient.psetex(key, random(ttl.min, ttl.max), PettyCache.stringify(value), (err) => {
902
+ if (err) {
903
+ return reject(err);
904
+ }
858
905
 
859
- // Store value in memory cache with a short expiration
860
- memoryCache.put(key, value, random(2000, 5000));
906
+ resolve();
907
+ });
908
+ });
909
+ };
861
910
 
862
- // Store value is Redis
863
- redisClient.psetex(key, random(ttl.min, ttl.max), PettyCache.stringify(value), callback);
911
+ if (callback) {
912
+ executor().then(result => callback(null, result)).catch(callback);
913
+ } else {
914
+ return executor();
915
+ }
864
916
  };
865
917
 
866
918
  // Semaphore functions need to be bound to the main PettyCache object
867
- for (var method in this.semaphore) {
919
+ for (const method in this.semaphore) {
868
920
  this.semaphore[method] = this.semaphore[method].bind(this);
869
921
  }
870
922
  }
@@ -877,8 +929,8 @@ function random(min, max) {
877
929
  return Math.floor(Math.random() * (max - min + 1) + min);
878
930
  }
879
931
 
880
- PettyCache.parse = function(text) {
881
- return JSON.parse(text, function(k, v) {
932
+ PettyCache.parse = (text) => {
933
+ return JSON.parse(text, (k, v) => {
882
934
  if (v === '__NaN') {
883
935
  return NaN;
884
936
  } else if (v === '__null') {
@@ -891,8 +943,8 @@ PettyCache.parse = function(text) {
891
943
  });
892
944
  };
893
945
 
894
- PettyCache.stringify = function(value) {
895
- return JSON.stringify(value, function(k, v) {
946
+ PettyCache.stringify = (value) => {
947
+ return JSON.stringify(value, (k, v) => {
896
948
  if (typeof v === 'number' && isNaN(v)) {
897
949
  return '__NaN';
898
950
  } else if (v === null) {
package/package.json CHANGED
@@ -1,34 +1,30 @@
1
1
  {
2
- "description": "A cache module for node.js that uses a two-level cache (in-memory cache for recently accessed data plus Redis for distributed caching) with some extra features to avoid cache stampedes and thundering herds.",
3
- "dependencies": {
4
- "async": "~3.2.6",
5
- "lock": "~1.1.0",
6
- "memory-cache": "~0.2.0",
7
- "redis": "~3.1.0"
8
- },
9
- "devDependencies": {
10
- "coveralls": "*",
11
- "mocha": "*",
12
- "nyc": "*"
13
- },
14
- "homepage": "https://github.com/mediocre/petty-cache",
15
- "keywords": [
16
- "cache",
17
- "lock",
18
- "mutex",
19
- "redis",
20
- "semaphore"
21
- ],
22
- "license": "Apache-2.0",
23
- "main": "index.js",
24
- "name": "petty-cache",
25
- "scripts": {
26
- "coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls",
27
- "test": "mocha --exit --reporter spec"
28
- },
29
- "repository": {
30
- "type": "git",
31
- "url": "https://github.com/mediocre/petty-cache.git"
32
- },
33
- "version": "3.4.0"
2
+ "dependencies": {
3
+ "async": "~3.2.6",
4
+ "lock": "~1.1.0",
5
+ "memory-cache": "~0.2.0",
6
+ "redis": "~3.1.0"
7
+ },
8
+ "description": "A cache module for node.js that uses a two-level cache (in-memory cache for recently accessed data plus Redis for distributed caching) with some extra features to avoid cache stampedes and thundering herds.",
9
+ "devDependencies": {
10
+ "@eslint/js": "*",
11
+ "globals": "*"
12
+ },
13
+ "homepage": "https://github.com/stores-com/petty-cache",
14
+ "keywords": [
15
+ "cache",
16
+ "lock",
17
+ "mutex",
18
+ "redis",
19
+ "semaphore"
20
+ ],
21
+ "license": "MIT",
22
+ "main": "index.js",
23
+ "name": "petty-cache",
24
+ "repository": "https://github.com/stores-com/petty-cache",
25
+ "scripts": {
26
+ "coveralls": "node --test --test-concurrency=true --test-force-exit --experimental-test-coverage --test-reporter=spec --test-reporter-destination=stdout --test-reporter=lcov --test-reporter-destination=lcov.info && coveralls < lcov.info",
27
+ "test": "node --test --test-concurrency=true --test-force-exit --test-reporter=spec"
28
+ },
29
+ "version": "3.6.0"
34
30
  }