@ferrox-node/redis 1.1.1 → 1.1.2
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/dist/smart-cache.d.ts +51 -4
- package/dist/smart-cache.js +34 -4
- package/package.json +20 -19
- package/src/smart-cache.ts +55 -7
package/dist/smart-cache.d.ts
CHANGED
|
@@ -1,23 +1,70 @@
|
|
|
1
1
|
import { RedisHelper } from './index';
|
|
2
|
+
/**
|
|
3
|
+
* Options for fetching and caching resources using the SmartCacheManager.
|
|
4
|
+
*/
|
|
2
5
|
export interface CacheFetchOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Mandatory user identifier.
|
|
8
|
+
* Enforced to prevent cross-tenant data leakage and ensure strict cache isolation per user.
|
|
9
|
+
*/
|
|
3
10
|
userId: string;
|
|
11
|
+
/**
|
|
12
|
+
* The name or identifier of the resource being fetched (e.g., 'profile', 'billing').
|
|
13
|
+
*/
|
|
4
14
|
resourceName: string;
|
|
15
|
+
/**
|
|
16
|
+
* Time-to-Live (TTL) for the cached item in seconds.
|
|
17
|
+
*/
|
|
5
18
|
ttlSeconds: number;
|
|
19
|
+
/**
|
|
20
|
+
* The asynchronous function that fetches the data from the primary data store (e.g., Database)
|
|
21
|
+
* in the event of a cache miss.
|
|
22
|
+
*/
|
|
6
23
|
fetcher: () => Promise<any>;
|
|
7
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Enterprise Smart Cache Manager.
|
|
27
|
+
*
|
|
28
|
+
* Implements advanced caching patterns to guarantee extreme performance and stability:
|
|
29
|
+
* - **Thundering Herd Protection**: Uses in-memory Promise multiplexing to deduplicate concurrent requests on the same Node.js instance.
|
|
30
|
+
* - **Cache Stampede Prevention**: Utilizes distributed Redis locks (Redlock pattern) to ensure only a single worker across the cluster hits the database when a cache miss occurs.
|
|
31
|
+
* - **Strict Tenant Isolation**: Automatically namespaces cache keys by `userId` to prevent data leakage.
|
|
32
|
+
*/
|
|
8
33
|
export declare class SmartCacheManager {
|
|
34
|
+
/**
|
|
35
|
+
* In-memory multiplexing map to track currently active fetches and prevent duplicate DB queries.
|
|
36
|
+
*/
|
|
9
37
|
private inFlightPromises;
|
|
10
38
|
private redis;
|
|
39
|
+
/**
|
|
40
|
+
* Initializes the SmartCacheManager with a Redis connection helper.
|
|
41
|
+
* @param redisHelper An instance of RedisHelper connected to the cache cluster.
|
|
42
|
+
*/
|
|
11
43
|
constructor(redisHelper: RedisHelper);
|
|
12
44
|
/**
|
|
13
|
-
* Generates a hyper-strict, isolated cache key.
|
|
45
|
+
* Generates a hyper-strict, isolated cache key scoped by user.
|
|
46
|
+
* @param userId The ID of the user requesting the resource.
|
|
47
|
+
* @param resourceName The resource being requested.
|
|
48
|
+
* @returns {string} A Redis-compatible namespaced key string.
|
|
49
|
+
* @private
|
|
14
50
|
*/
|
|
15
51
|
private generateKey;
|
|
16
52
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
53
|
+
* Retrieves data from the cache or securely fetches it from the database.
|
|
54
|
+
* Implements a Multi-tier Thundering Herd & Cache Stampede Protection system.
|
|
55
|
+
*
|
|
56
|
+
* - **Tier 1**: In-Memory Promise Deduplication (Single-Node Lock).
|
|
57
|
+
* - **Tier 2**: Distributed Redis Cache Check.
|
|
58
|
+
* - **Tier 3**: Distributed Redis Lock (Multi-Node Lock) before DB fetch.
|
|
59
|
+
*
|
|
60
|
+
* @template T The expected type of the data returned.
|
|
61
|
+
* @param {CacheFetchOptions} options The fetch configuration options.
|
|
62
|
+
* @returns {Promise<T>} The requested data, either from cache or freshly fetched.
|
|
20
63
|
*/
|
|
21
64
|
getOrFetch<T>(options: CacheFetchOptions): Promise<T>;
|
|
65
|
+
/**
|
|
66
|
+
* Internal routine for handling Redis checking, locking, and DB fetching.
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
22
69
|
private internalFetch;
|
|
23
70
|
}
|
package/dist/smart-cache.js
CHANGED
|
@@ -3,22 +3,48 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SmartCacheManager = void 0;
|
|
4
4
|
const logger_1 = require("@node-yalc/logger");
|
|
5
5
|
const logger = (0, logger_1.AppLoggerFactory)('SmartCacheManager');
|
|
6
|
+
/**
|
|
7
|
+
* Enterprise Smart Cache Manager.
|
|
8
|
+
*
|
|
9
|
+
* Implements advanced caching patterns to guarantee extreme performance and stability:
|
|
10
|
+
* - **Thundering Herd Protection**: Uses in-memory Promise multiplexing to deduplicate concurrent requests on the same Node.js instance.
|
|
11
|
+
* - **Cache Stampede Prevention**: Utilizes distributed Redis locks (Redlock pattern) to ensure only a single worker across the cluster hits the database when a cache miss occurs.
|
|
12
|
+
* - **Strict Tenant Isolation**: Automatically namespaces cache keys by `userId` to prevent data leakage.
|
|
13
|
+
*/
|
|
6
14
|
class SmartCacheManager {
|
|
15
|
+
/**
|
|
16
|
+
* In-memory multiplexing map to track currently active fetches and prevent duplicate DB queries.
|
|
17
|
+
*/
|
|
7
18
|
inFlightPromises = new Map();
|
|
8
19
|
redis;
|
|
20
|
+
/**
|
|
21
|
+
* Initializes the SmartCacheManager with a Redis connection helper.
|
|
22
|
+
* @param redisHelper An instance of RedisHelper connected to the cache cluster.
|
|
23
|
+
*/
|
|
9
24
|
constructor(redisHelper) {
|
|
10
25
|
this.redis = redisHelper;
|
|
11
26
|
}
|
|
12
27
|
/**
|
|
13
|
-
* Generates a hyper-strict, isolated cache key.
|
|
28
|
+
* Generates a hyper-strict, isolated cache key scoped by user.
|
|
29
|
+
* @param userId The ID of the user requesting the resource.
|
|
30
|
+
* @param resourceName The resource being requested.
|
|
31
|
+
* @returns {string} A Redis-compatible namespaced key string.
|
|
32
|
+
* @private
|
|
14
33
|
*/
|
|
15
34
|
generateKey(userId, resourceName) {
|
|
16
35
|
return `ferrox:cache:user:${userId}:res:${resourceName}`;
|
|
17
36
|
}
|
|
18
37
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
38
|
+
* Retrieves data from the cache or securely fetches it from the database.
|
|
39
|
+
* Implements a Multi-tier Thundering Herd & Cache Stampede Protection system.
|
|
40
|
+
*
|
|
41
|
+
* - **Tier 1**: In-Memory Promise Deduplication (Single-Node Lock).
|
|
42
|
+
* - **Tier 2**: Distributed Redis Cache Check.
|
|
43
|
+
* - **Tier 3**: Distributed Redis Lock (Multi-Node Lock) before DB fetch.
|
|
44
|
+
*
|
|
45
|
+
* @template T The expected type of the data returned.
|
|
46
|
+
* @param {CacheFetchOptions} options The fetch configuration options.
|
|
47
|
+
* @returns {Promise<T>} The requested data, either from cache or freshly fetched.
|
|
22
48
|
*/
|
|
23
49
|
async getOrFetch(options) {
|
|
24
50
|
const cacheKey = this.generateKey(options.userId, options.resourceName);
|
|
@@ -38,6 +64,10 @@ class SmartCacheManager {
|
|
|
38
64
|
this.inFlightPromises.delete(cacheKey);
|
|
39
65
|
}
|
|
40
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Internal routine for handling Redis checking, locking, and DB fetching.
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
41
71
|
async internalFetch(cacheKey, options) {
|
|
42
72
|
// TIER 2: Check Redis Cache
|
|
43
73
|
const cachedValue = await this.redis.getCache(cacheKey);
|
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@ferrox-node/redis",
|
|
3
|
+
"version": "1.1.2",
|
|
4
|
+
"description": "Advanced Redis, Distributed Locks, and Caching for Ferrox-Node",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@ferrox-node/core": "*",
|
|
12
|
+
"ioredis": "^5.4.1",
|
|
13
|
+
"redlock": "^5.0.0-beta.2"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"typescript": "^5.0.0",
|
|
17
|
+
"@types/node": "^20.0.0"
|
|
18
|
+
},
|
|
19
|
+
"type": "module"
|
|
20
|
+
}
|
package/src/smart-cache.ts
CHANGED
|
@@ -3,32 +3,75 @@ import { AppLoggerFactory } from '@node-yalc/logger';
|
|
|
3
3
|
|
|
4
4
|
const logger = AppLoggerFactory('SmartCacheManager');
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Options for fetching and caching resources using the SmartCacheManager.
|
|
8
|
+
*/
|
|
6
9
|
export interface CacheFetchOptions {
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Mandatory user identifier.
|
|
12
|
+
* Enforced to prevent cross-tenant data leakage and ensure strict cache isolation per user.
|
|
13
|
+
*/
|
|
14
|
+
userId: string;
|
|
15
|
+
/**
|
|
16
|
+
* The name or identifier of the resource being fetched (e.g., 'profile', 'billing').
|
|
17
|
+
*/
|
|
18
|
+
resourceName: string;
|
|
19
|
+
/**
|
|
20
|
+
* Time-to-Live (TTL) for the cached item in seconds.
|
|
21
|
+
*/
|
|
9
22
|
ttlSeconds: number;
|
|
10
|
-
|
|
23
|
+
/**
|
|
24
|
+
* The asynchronous function that fetches the data from the primary data store (e.g., Database)
|
|
25
|
+
* in the event of a cache miss.
|
|
26
|
+
*/
|
|
27
|
+
fetcher: () => Promise<any>;
|
|
11
28
|
}
|
|
12
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Enterprise Smart Cache Manager.
|
|
32
|
+
*
|
|
33
|
+
* Implements advanced caching patterns to guarantee extreme performance and stability:
|
|
34
|
+
* - **Thundering Herd Protection**: Uses in-memory Promise multiplexing to deduplicate concurrent requests on the same Node.js instance.
|
|
35
|
+
* - **Cache Stampede Prevention**: Utilizes distributed Redis locks (Redlock pattern) to ensure only a single worker across the cluster hits the database when a cache miss occurs.
|
|
36
|
+
* - **Strict Tenant Isolation**: Automatically namespaces cache keys by `userId` to prevent data leakage.
|
|
37
|
+
*/
|
|
13
38
|
export class SmartCacheManager {
|
|
39
|
+
/**
|
|
40
|
+
* In-memory multiplexing map to track currently active fetches and prevent duplicate DB queries.
|
|
41
|
+
*/
|
|
14
42
|
private inFlightPromises = new Map<string, Promise<any>>();
|
|
15
43
|
private redis: RedisHelper;
|
|
16
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Initializes the SmartCacheManager with a Redis connection helper.
|
|
47
|
+
* @param redisHelper An instance of RedisHelper connected to the cache cluster.
|
|
48
|
+
*/
|
|
17
49
|
constructor(redisHelper: RedisHelper) {
|
|
18
50
|
this.redis = redisHelper;
|
|
19
51
|
}
|
|
20
52
|
|
|
21
53
|
/**
|
|
22
|
-
* Generates a hyper-strict, isolated cache key.
|
|
54
|
+
* Generates a hyper-strict, isolated cache key scoped by user.
|
|
55
|
+
* @param userId The ID of the user requesting the resource.
|
|
56
|
+
* @param resourceName The resource being requested.
|
|
57
|
+
* @returns {string} A Redis-compatible namespaced key string.
|
|
58
|
+
* @private
|
|
23
59
|
*/
|
|
24
60
|
private generateKey(userId: string, resourceName: string): string {
|
|
25
61
|
return `ferrox:cache:user:${userId}:res:${resourceName}`;
|
|
26
62
|
}
|
|
27
63
|
|
|
28
64
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
65
|
+
* Retrieves data from the cache or securely fetches it from the database.
|
|
66
|
+
* Implements a Multi-tier Thundering Herd & Cache Stampede Protection system.
|
|
67
|
+
*
|
|
68
|
+
* - **Tier 1**: In-Memory Promise Deduplication (Single-Node Lock).
|
|
69
|
+
* - **Tier 2**: Distributed Redis Cache Check.
|
|
70
|
+
* - **Tier 3**: Distributed Redis Lock (Multi-Node Lock) before DB fetch.
|
|
71
|
+
*
|
|
72
|
+
* @template T The expected type of the data returned.
|
|
73
|
+
* @param {CacheFetchOptions} options The fetch configuration options.
|
|
74
|
+
* @returns {Promise<T>} The requested data, either from cache or freshly fetched.
|
|
32
75
|
*/
|
|
33
76
|
public async getOrFetch<T>(options: CacheFetchOptions): Promise<T> {
|
|
34
77
|
const cacheKey = this.generateKey(options.userId, options.resourceName);
|
|
@@ -51,6 +94,10 @@ export class SmartCacheManager {
|
|
|
51
94
|
}
|
|
52
95
|
}
|
|
53
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Internal routine for handling Redis checking, locking, and DB fetching.
|
|
99
|
+
* @private
|
|
100
|
+
*/
|
|
54
101
|
private async internalFetch<T>(cacheKey: string, options: CacheFetchOptions): Promise<T> {
|
|
55
102
|
// TIER 2: Check Redis Cache
|
|
56
103
|
const cachedValue = await this.redis.getCache<T>(cacheKey);
|
|
@@ -97,4 +144,5 @@ export class SmartCacheManager {
|
|
|
97
144
|
}
|
|
98
145
|
}
|
|
99
146
|
}
|
|
147
|
+
|
|
100
148
|
|