@nest-omni/core 3.1.1-12 → 3.1.1-14
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/cache/cache-metrics.service.d.ts +83 -0
- package/cache/cache-metrics.service.js +298 -0
- package/cache/cache-serialization.service.d.ts +29 -0
- package/cache/cache-serialization.service.js +217 -0
- package/cache/cache.health.d.ts +35 -0
- package/cache/cache.health.js +193 -0
- package/cache/cache.module.d.ts +24 -0
- package/cache/cache.module.js +105 -0
- package/cache/cache.service.d.ts +35 -0
- package/cache/cache.service.js +280 -0
- package/cache/cache.warmup.service.d.ts +34 -0
- package/cache/cache.warmup.service.js +199 -0
- package/cache/decorators/cache-evict.decorator.d.ts +2 -0
- package/cache/decorators/cache-evict.decorator.js +72 -0
- package/cache/decorators/cache-put.decorator.d.ts +2 -0
- package/cache/decorators/cache-put.decorator.js +48 -0
- package/cache/decorators/cacheable.decorator.d.ts +4 -0
- package/cache/decorators/cacheable.decorator.js +68 -0
- package/cache/decorators/index.d.ts +3 -0
- package/cache/decorators/index.js +11 -0
- package/cache/dependencies/callback.dependency.d.ts +11 -0
- package/cache/dependencies/callback.dependency.js +92 -0
- package/cache/dependencies/chain.dependency.d.ts +20 -0
- package/cache/dependencies/chain.dependency.js +113 -0
- package/cache/dependencies/db.dependency.d.ts +15 -0
- package/cache/dependencies/db.dependency.js +71 -0
- package/cache/dependencies/file.dependency.d.ts +17 -0
- package/cache/dependencies/file.dependency.js +63 -0
- package/cache/dependencies/index.d.ts +6 -0
- package/cache/dependencies/index.js +22 -0
- package/cache/dependencies/tag.dependency.d.ts +16 -0
- package/cache/dependencies/tag.dependency.js +75 -0
- package/cache/dependencies/time.dependency.d.ts +19 -0
- package/cache/dependencies/time.dependency.js +71 -0
- package/cache/examples/quick-start.d.ts +5 -0
- package/cache/examples/quick-start.js +341 -0
- package/cache/index.d.ts +14 -0
- package/cache/index.js +41 -0
- package/cache/interfaces/cache-dependency.interface.d.ts +11 -0
- package/cache/interfaces/cache-dependency.interface.js +2 -0
- package/cache/interfaces/cache-options.interface.d.ts +32 -0
- package/cache/interfaces/cache-options.interface.js +9 -0
- package/cache/interfaces/cache-provider.interface.d.ts +28 -0
- package/cache/interfaces/cache-provider.interface.js +2 -0
- package/cache/interfaces/index.d.ts +3 -0
- package/cache/interfaces/index.js +19 -0
- package/cache/providers/base-cache.provider.d.ts +16 -0
- package/cache/providers/base-cache.provider.js +32 -0
- package/cache/providers/cls-cache.provider.d.ts +16 -0
- package/cache/providers/cls-cache.provider.js +140 -0
- package/cache/providers/index.d.ts +4 -0
- package/cache/providers/index.js +23 -0
- package/cache/providers/memory-cache.provider.d.ts +26 -0
- package/cache/providers/memory-cache.provider.js +171 -0
- package/cache/providers/redis-cache.provider.d.ts +23 -0
- package/cache/providers/redis-cache.provider.js +215 -0
- package/cache/utils/dependency-manager.util.d.ts +15 -0
- package/cache/utils/dependency-manager.util.js +141 -0
- package/cache/utils/index.d.ts +2 -0
- package/cache/utils/index.js +18 -0
- package/cache/utils/key-generator.util.d.ts +13 -0
- package/cache/utils/key-generator.util.js +74 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +4 -17
- package/redis-lock/index.d.ts +4 -0
- package/redis-lock/index.js +13 -0
- package/{setup → redis-lock}/redis-lock.decorator.d.ts +3 -0
- package/{setup → redis-lock}/redis-lock.decorator.js +25 -14
- package/redis-lock/redis-lock.examples.d.ts +13 -0
- package/redis-lock/redis-lock.examples.js +159 -0
- package/redis-lock/redis-lock.module.d.ts +23 -0
- package/redis-lock/redis-lock.module.js +117 -0
- package/{setup → redis-lock}/redis-lock.service.d.ts +9 -21
- package/{setup → redis-lock}/redis-lock.service.js +29 -103
- package/setup/index.d.ts +1 -2
- package/setup/index.js +1 -2
- package/setup/schedule.decorator.js +1 -1
- package/shared/serviceRegistryModule.js +63 -4
- package/shared/services/api-config.service.d.ts +0 -5
- package/shared/services/api-config.service.js +3 -27
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DependencyManager = void 0;
|
|
13
|
+
class DependencyManager {
|
|
14
|
+
static wrapWithDependencies(value, dependencies) {
|
|
15
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
const wrapped = {
|
|
17
|
+
value,
|
|
18
|
+
cachedAt: Date.now(),
|
|
19
|
+
};
|
|
20
|
+
if (dependencies && dependencies.length > 0) {
|
|
21
|
+
wrapped.dependencies = yield this.captureDependencies(dependencies);
|
|
22
|
+
}
|
|
23
|
+
return wrapped;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
static captureDependencies(dependencies) {
|
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
const results = [];
|
|
29
|
+
for (const dep of dependencies) {
|
|
30
|
+
try {
|
|
31
|
+
const data = yield dep.getData();
|
|
32
|
+
results.push({
|
|
33
|
+
key: dep.getKey(),
|
|
34
|
+
data,
|
|
35
|
+
timestamp: Date.now(),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
results.push({
|
|
40
|
+
key: dep.getKey(),
|
|
41
|
+
data: {
|
|
42
|
+
error: error instanceof Error ? error.message : String(error),
|
|
43
|
+
},
|
|
44
|
+
timestamp: Date.now(),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return results;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
static areDependenciesChanged(dependencies, cachedDependencies) {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
if (!dependencies || dependencies.length === 0) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (!cachedDependencies || cachedDependencies.length === 0) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (dependencies.length !== cachedDependencies.length) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
for (let i = 0; i < dependencies.length; i++) {
|
|
63
|
+
const dep = dependencies[i];
|
|
64
|
+
const cached = cachedDependencies[i];
|
|
65
|
+
if (dep.getKey() !== cached.key) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const changed = yield dep.isChanged(cached.data);
|
|
70
|
+
if (changed) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (_a) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
static unwrapAndValidate(wrapped, dependencies) {
|
|
82
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
83
|
+
if (!wrapped) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
if (!dependencies || dependencies.length === 0) {
|
|
87
|
+
return wrapped.value;
|
|
88
|
+
}
|
|
89
|
+
const changed = yield this.areDependenciesChanged(dependencies, wrapped.dependencies);
|
|
90
|
+
if (changed) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return wrapped.value;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
static getChangedDependencies(dependencies, cachedDependencies) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
if (!dependencies || dependencies.length === 0) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
if (!cachedDependencies || cachedDependencies.length === 0) {
|
|
102
|
+
return dependencies.map((dep) => dep.getKey());
|
|
103
|
+
}
|
|
104
|
+
const changed = [];
|
|
105
|
+
for (let i = 0; i < dependencies.length; i++) {
|
|
106
|
+
const dep = dependencies[i];
|
|
107
|
+
const cached = cachedDependencies[i];
|
|
108
|
+
if (!cached) {
|
|
109
|
+
changed.push(dep.getKey());
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
if (dep.getKey() !== cached.key || (yield dep.isChanged(cached.data))) {
|
|
114
|
+
changed.push(dep.getKey());
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (_a) {
|
|
118
|
+
changed.push(dep.getKey());
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return changed;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
static serializeDependencies(dependencies) {
|
|
125
|
+
try {
|
|
126
|
+
return JSON.stringify(dependencies);
|
|
127
|
+
}
|
|
128
|
+
catch (_a) {
|
|
129
|
+
return '[]';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
static deserializeDependencies(serialized) {
|
|
133
|
+
try {
|
|
134
|
+
return JSON.parse(serialized);
|
|
135
|
+
}
|
|
136
|
+
catch (_a) {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.DependencyManager = DependencyManager;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./dependency-manager.util"), exports);
|
|
18
|
+
__exportStar(require("./key-generator.util"), exports);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CacheKeyOptions } from '../interfaces';
|
|
2
|
+
export declare class KeyGenerator {
|
|
3
|
+
static generate(options: CacheKeyOptions, args: any[]): string;
|
|
4
|
+
static generateFromArgs(args: any[]): string;
|
|
5
|
+
static normalize(key: string, maxLength?: number): string;
|
|
6
|
+
static addNamespace(key: string, namespace?: string): string;
|
|
7
|
+
static hashCode(str: string): string;
|
|
8
|
+
static parsePattern(pattern: string): {
|
|
9
|
+
prefix: string;
|
|
10
|
+
suffix: string;
|
|
11
|
+
hasWildcard: boolean;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KeyGenerator = void 0;
|
|
4
|
+
class KeyGenerator {
|
|
5
|
+
static generate(options, args) {
|
|
6
|
+
let key;
|
|
7
|
+
if (typeof options.key === 'function') {
|
|
8
|
+
key = options.key(...args);
|
|
9
|
+
}
|
|
10
|
+
else if (typeof options.key === 'string') {
|
|
11
|
+
key = options.key;
|
|
12
|
+
}
|
|
13
|
+
else if (options.includeAllArgs) {
|
|
14
|
+
key = this.generateFromArgs(args);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
key = args.length > 0 ? String(args[0]) : 'default';
|
|
18
|
+
}
|
|
19
|
+
if (options.prefix) {
|
|
20
|
+
key = `${options.prefix}${key}`;
|
|
21
|
+
}
|
|
22
|
+
return key;
|
|
23
|
+
}
|
|
24
|
+
static generateFromArgs(args) {
|
|
25
|
+
if (args.length === 0) {
|
|
26
|
+
return 'default';
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
return JSON.stringify(args);
|
|
30
|
+
}
|
|
31
|
+
catch (_a) {
|
|
32
|
+
return args.map((arg) => String(arg)).join(':');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
static normalize(key, maxLength = 250) {
|
|
36
|
+
let normalized = key.replace(/[\s\n\r\t]/g, '_');
|
|
37
|
+
if (normalized.length > maxLength) {
|
|
38
|
+
const hash = this.hashCode(normalized);
|
|
39
|
+
normalized = normalized.substring(0, maxLength - 10) + '_' + hash;
|
|
40
|
+
}
|
|
41
|
+
return normalized;
|
|
42
|
+
}
|
|
43
|
+
static addNamespace(key, namespace) {
|
|
44
|
+
if (!namespace) {
|
|
45
|
+
return key;
|
|
46
|
+
}
|
|
47
|
+
return `${namespace}:${key}`;
|
|
48
|
+
}
|
|
49
|
+
static hashCode(str) {
|
|
50
|
+
let hash = 0;
|
|
51
|
+
for (let i = 0; i < str.length; i++) {
|
|
52
|
+
const char = str.charCodeAt(i);
|
|
53
|
+
hash = (hash << 5) - hash + char;
|
|
54
|
+
hash = hash & hash;
|
|
55
|
+
}
|
|
56
|
+
return Math.abs(hash).toString(36);
|
|
57
|
+
}
|
|
58
|
+
static parsePattern(pattern) {
|
|
59
|
+
const wildcardIndex = pattern.indexOf('*');
|
|
60
|
+
if (wildcardIndex === -1) {
|
|
61
|
+
return {
|
|
62
|
+
prefix: pattern,
|
|
63
|
+
suffix: '',
|
|
64
|
+
hasWildcard: false,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
prefix: pattern.substring(0, wildcardIndex),
|
|
69
|
+
suffix: pattern.substring(wildcardIndex + 1),
|
|
70
|
+
hasWildcard: true,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.KeyGenerator = KeyGenerator;
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -27,5 +27,6 @@ __exportStar(require("./common"), exports);
|
|
|
27
27
|
__exportStar(require("./validator-json"), exports);
|
|
28
28
|
__exportStar(require("./helpers"), exports);
|
|
29
29
|
__exportStar(require("./providers"), exports);
|
|
30
|
+
__exportStar(require("./cache"), exports);
|
|
30
31
|
__exportStar(require("./setup"), exports);
|
|
31
32
|
__exportStar(require("./health-checker"), exports);
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nest-omni/core",
|
|
3
|
-
"version": "3.1.1-
|
|
3
|
+
"version": "3.1.1-14",
|
|
4
4
|
"description": "A comprehensive NestJS framework for building enterprise-grade applications with best practices",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsc -p tsconfig.json",
|
|
9
9
|
"test": "jest --passWithNoTests",
|
|
10
|
+
"test:cache": "jest src/cache --verbose",
|
|
11
|
+
"test:cache:watch": "jest src/cache --watch",
|
|
12
|
+
"test:cache:coverage": "jest src/cache --coverage",
|
|
10
13
|
"lint": "eslint 'src/**/*.ts' --fix"
|
|
11
14
|
},
|
|
12
15
|
"bin": {
|
|
@@ -68,9 +71,7 @@
|
|
|
68
71
|
"peerDependencies": {
|
|
69
72
|
"@dataui/crud": "^5.3.0",
|
|
70
73
|
"@dataui/crud-typeorm": "^5.3.0",
|
|
71
|
-
"@keyv/redis": "^5.1.3",
|
|
72
74
|
"@nestjs/bull": "^11.0.0",
|
|
73
|
-
"@nestjs/cache-manager": "^3.0.0",
|
|
74
75
|
"@nestjs/common": "^11.0.0",
|
|
75
76
|
"@nestjs/config": "^4.0.0",
|
|
76
77
|
"@nestjs/core": "^11.0.0",
|
|
@@ -83,11 +84,9 @@
|
|
|
83
84
|
"@songkeys/nestjs-redis-health": "^11.0.0",
|
|
84
85
|
"bcrypt": "^6.0.0",
|
|
85
86
|
"bull": "^4.16.0",
|
|
86
|
-
"cache-manager": "^7.0.0",
|
|
87
87
|
"connect-redis": "^9.0.0",
|
|
88
88
|
"express": "^5.0.0",
|
|
89
89
|
"express-session": "^1.18.0",
|
|
90
|
-
"keyv": "^5.5.3",
|
|
91
90
|
"mime-types": "^3.0.0",
|
|
92
91
|
"mysql2": "^3.0.0",
|
|
93
92
|
"nestjs-cls": "^6.0.0",
|
|
@@ -105,9 +104,6 @@
|
|
|
105
104
|
"@dataui/crud-typeorm": {
|
|
106
105
|
"optional": false
|
|
107
106
|
},
|
|
108
|
-
"@keyv/redis": {
|
|
109
|
-
"optional": true
|
|
110
|
-
},
|
|
111
107
|
"@songkeys/nestjs-redis": {
|
|
112
108
|
"optional": true
|
|
113
109
|
},
|
|
@@ -117,9 +113,6 @@
|
|
|
117
113
|
"@nestjs/bull": {
|
|
118
114
|
"optional": false
|
|
119
115
|
},
|
|
120
|
-
"@nestjs/cache-manager": {
|
|
121
|
-
"optional": false
|
|
122
|
-
},
|
|
123
116
|
"@nestjs/schedule": {
|
|
124
117
|
"optional": false
|
|
125
118
|
},
|
|
@@ -132,18 +125,12 @@
|
|
|
132
125
|
"bull": {
|
|
133
126
|
"optional": false
|
|
134
127
|
},
|
|
135
|
-
"cache-manager": {
|
|
136
|
-
"optional": false
|
|
137
|
-
},
|
|
138
128
|
"connect-redis": {
|
|
139
129
|
"optional": false
|
|
140
130
|
},
|
|
141
131
|
"express-session": {
|
|
142
132
|
"optional": false
|
|
143
133
|
},
|
|
144
|
-
"keyv": {
|
|
145
|
-
"optional": false
|
|
146
|
-
},
|
|
147
134
|
"mysql2": {
|
|
148
135
|
"optional": false
|
|
149
136
|
},
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { RedisLockModule, type RedisLockModuleOptions, REDIS_LOCK_SERVICE, } from './redis-lock.module';
|
|
2
|
+
export { RedisLockService } from './redis-lock.service';
|
|
3
|
+
export { UseRedisLock, UseRedisLockOrSkip, setLockService, getLockService, } from './redis-lock.decorator';
|
|
4
|
+
export type { LockOptions, LockResult } from './redis-lock.service';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLockService = exports.setLockService = exports.UseRedisLockOrSkip = exports.UseRedisLock = exports.RedisLockService = exports.REDIS_LOCK_SERVICE = exports.RedisLockModule = void 0;
|
|
4
|
+
var redis_lock_module_1 = require("./redis-lock.module");
|
|
5
|
+
Object.defineProperty(exports, "RedisLockModule", { enumerable: true, get: function () { return redis_lock_module_1.RedisLockModule; } });
|
|
6
|
+
Object.defineProperty(exports, "REDIS_LOCK_SERVICE", { enumerable: true, get: function () { return redis_lock_module_1.REDIS_LOCK_SERVICE; } });
|
|
7
|
+
var redis_lock_service_1 = require("./redis-lock.service");
|
|
8
|
+
Object.defineProperty(exports, "RedisLockService", { enumerable: true, get: function () { return redis_lock_service_1.RedisLockService; } });
|
|
9
|
+
var redis_lock_decorator_1 = require("./redis-lock.decorator");
|
|
10
|
+
Object.defineProperty(exports, "UseRedisLock", { enumerable: true, get: function () { return redis_lock_decorator_1.UseRedisLock; } });
|
|
11
|
+
Object.defineProperty(exports, "UseRedisLockOrSkip", { enumerable: true, get: function () { return redis_lock_decorator_1.UseRedisLockOrSkip; } });
|
|
12
|
+
Object.defineProperty(exports, "setLockService", { enumerable: true, get: function () { return redis_lock_decorator_1.setLockService; } });
|
|
13
|
+
Object.defineProperty(exports, "getLockService", { enumerable: true, get: function () { return redis_lock_decorator_1.getLockService; } });
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { LockOptions } from './redis-lock.service';
|
|
2
|
+
import { RedisLockService } from './redis-lock.service';
|
|
3
|
+
export declare function setLockService(lockService: RedisLockService): void;
|
|
4
|
+
export declare function getLockService(): RedisLockService | null;
|
|
2
5
|
export declare function UseRedisLock(lockKey: string, options?: LockOptions & {
|
|
3
6
|
skipReturnValue?: any;
|
|
4
7
|
}): MethodDecorator;
|
|
@@ -9,30 +9,37 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.setLockService = setLockService;
|
|
13
|
+
exports.getLockService = getLockService;
|
|
12
14
|
exports.UseRedisLock = UseRedisLock;
|
|
13
15
|
exports.UseRedisLockOrSkip = UseRedisLockOrSkip;
|
|
14
16
|
const common_1 = require("@nestjs/common");
|
|
17
|
+
const redis_lock_service_1 = require("./redis-lock.service");
|
|
18
|
+
let globalLockService = null;
|
|
19
|
+
function setLockService(lockService) {
|
|
20
|
+
globalLockService = lockService;
|
|
21
|
+
redis_lock_service_1.RedisLockService.setGlobalInstance(lockService);
|
|
22
|
+
}
|
|
23
|
+
function getLockService() {
|
|
24
|
+
return globalLockService;
|
|
25
|
+
}
|
|
15
26
|
function UseRedisLock(lockKey, options = {}) {
|
|
16
27
|
return function (target, propertyKey, descriptor) {
|
|
17
28
|
const originalMethod = descriptor.value;
|
|
18
29
|
const logger = new common_1.Logger(`RedisLock:${String(propertyKey)}`);
|
|
19
30
|
descriptor.value = function (...args) {
|
|
20
31
|
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
-
var _a;
|
|
22
|
-
|
|
23
|
-
let lockService = RedisLockService.getGlobalInstance();
|
|
32
|
+
var _a, _b;
|
|
33
|
+
let lockService = getLockService();
|
|
24
34
|
if (!lockService) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
logger.error(`Failed to auto-initialize RedisLockService: ${error.message}. ` +
|
|
31
|
-
`Please ensure Redis is accessible or call configureRedisLock() in your application setup.`);
|
|
32
|
-
throw new Error(`RedisLockService initialization failed. Please check Redis connection or call configureRedisLock() in your application setup.`);
|
|
35
|
+
const { RedisLockService } = yield Promise.resolve().then(() => require('./redis-lock.service'));
|
|
36
|
+
lockService = RedisLockService.getGlobalInstance();
|
|
37
|
+
if (!lockService) {
|
|
38
|
+
logger.error(`RedisLockService not found. Please ensure RedisLockModule is properly configured with a Redis client.`);
|
|
39
|
+
return (_a = options.skipReturnValue) !== null && _a !== void 0 ? _a : null;
|
|
33
40
|
}
|
|
34
41
|
}
|
|
35
|
-
const skipReturnValue = (
|
|
42
|
+
const skipReturnValue = (_b = options.skipReturnValue) !== null && _b !== void 0 ? _b : null;
|
|
36
43
|
try {
|
|
37
44
|
const lockResult = yield lockService.acquireLock(lockKey, options);
|
|
38
45
|
if (!lockResult.acquired) {
|
|
@@ -56,9 +63,13 @@ function UseRedisLock(lockKey, options = {}) {
|
|
|
56
63
|
}
|
|
57
64
|
}
|
|
58
65
|
catch (error) {
|
|
66
|
+
if (error.message.includes('requires a Redis client to be set')) {
|
|
67
|
+
logger.error(`Redis client not configured for RedisLock in ${String(propertyKey)}: ${error.message}. ` +
|
|
68
|
+
`Skipping execution to prevent issues.`);
|
|
69
|
+
return skipReturnValue;
|
|
70
|
+
}
|
|
59
71
|
if (error.message.includes('ECONNREFUSED') ||
|
|
60
|
-
error.message.includes('Redis connection')
|
|
61
|
-
error.message.includes('RedisLockService initialization failed')) {
|
|
72
|
+
error.message.includes('Redis connection')) {
|
|
62
73
|
logger.error(`Redis connection error in ${String(propertyKey)}: ${error.message}. ` +
|
|
63
74
|
`Skipping execution to prevent issues.`);
|
|
64
75
|
return skipReturnValue;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class ExampleService {
|
|
2
|
+
private readonly logger;
|
|
3
|
+
syncData(): Promise<void>;
|
|
4
|
+
criticalTask(): Promise<void>;
|
|
5
|
+
cleanupTask(): Promise<string>;
|
|
6
|
+
processWithManualLock(data: any): Promise<boolean>;
|
|
7
|
+
processWithWithLock(data: any): Promise<boolean>;
|
|
8
|
+
generateHourlyReport(): Promise<void>;
|
|
9
|
+
private performCriticalOperation;
|
|
10
|
+
private performCleanup;
|
|
11
|
+
private processData;
|
|
12
|
+
private createReport;
|
|
13
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
var ExampleService_1;
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.ExampleService = void 0;
|
|
23
|
+
const common_1 = require("@nestjs/common");
|
|
24
|
+
const redis_lock_decorator_1 = require("./redis-lock.decorator");
|
|
25
|
+
const redis_lock_service_1 = require("./redis-lock.service");
|
|
26
|
+
let ExampleService = ExampleService_1 = class ExampleService {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.logger = new common_1.Logger(ExampleService_1.name);
|
|
29
|
+
}
|
|
30
|
+
syncData() {
|
|
31
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
this.logger.log('Starting data synchronization...');
|
|
33
|
+
yield new Promise((resolve) => setTimeout(resolve, 2000));
|
|
34
|
+
this.logger.log('Data synchronization completed');
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
criticalTask() {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
this.logger.log('Executing critical task...');
|
|
40
|
+
yield this.performCriticalOperation();
|
|
41
|
+
this.logger.log('Critical task completed');
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
cleanupTask() {
|
|
45
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
this.logger.log('Starting cleanup task...');
|
|
47
|
+
yield this.performCleanup();
|
|
48
|
+
this.logger.log('Cleanup task completed');
|
|
49
|
+
return 'completed';
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
processWithManualLock(data) {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
const lockService = new redis_lock_service_1.RedisLockService();
|
|
55
|
+
try {
|
|
56
|
+
const lockResult = yield lockService.acquireLock('process-data', {
|
|
57
|
+
ttl: 60000,
|
|
58
|
+
retryCount: 5,
|
|
59
|
+
retryDelay: 100,
|
|
60
|
+
});
|
|
61
|
+
if (!lockResult.acquired) {
|
|
62
|
+
this.logger.warn('Could not acquire lock, skipping processing');
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
this.logger.log('Lock acquired, processing data...');
|
|
66
|
+
try {
|
|
67
|
+
yield this.processData(data);
|
|
68
|
+
this.logger.log('Data processing completed');
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
yield lockService.releaseLock('process-data', lockResult.lockValue);
|
|
73
|
+
this.logger.log('Lock released');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
this.logger.error('Error in processWithManualLock:', error);
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
processWithWithLock(data) {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
const lockService = new redis_lock_service_1.RedisLockService();
|
|
85
|
+
return yield lockService.withLock('auto-process', () => __awaiter(this, void 0, void 0, function* () {
|
|
86
|
+
this.logger.log('Processing with automatic lock management...');
|
|
87
|
+
yield this.processData(data);
|
|
88
|
+
this.logger.log('Processing completed');
|
|
89
|
+
return true;
|
|
90
|
+
}), {
|
|
91
|
+
ttl: 60000,
|
|
92
|
+
retryCount: 3,
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
generateHourlyReport() {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
this.logger.log('Generating hourly report...');
|
|
99
|
+
yield this.createReport();
|
|
100
|
+
this.logger.log('Hourly report generated');
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
performCriticalOperation() {
|
|
104
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
105
|
+
yield new Promise((resolve) => setTimeout(resolve, 1000));
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
performCleanup() {
|
|
109
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
yield new Promise((resolve) => setTimeout(resolve, 1500));
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
processData(data) {
|
|
114
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
yield new Promise((resolve) => setTimeout(resolve, 800));
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
createReport() {
|
|
119
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
yield new Promise((resolve) => setTimeout(resolve, 2000));
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
exports.ExampleService = ExampleService;
|
|
125
|
+
__decorate([
|
|
126
|
+
(0, redis_lock_decorator_1.UseRedisLock)('data-sync', { ttl: 300000 }),
|
|
127
|
+
__metadata("design:type", Function),
|
|
128
|
+
__metadata("design:paramtypes", []),
|
|
129
|
+
__metadata("design:returntype", Promise)
|
|
130
|
+
], ExampleService.prototype, "syncData", null);
|
|
131
|
+
__decorate([
|
|
132
|
+
(0, redis_lock_decorator_1.UseRedisLock)('critical-task', {
|
|
133
|
+
ttl: 60000,
|
|
134
|
+
retryCount: 3,
|
|
135
|
+
retryDelay: 200,
|
|
136
|
+
throwOnFailure: true,
|
|
137
|
+
}),
|
|
138
|
+
__metadata("design:type", Function),
|
|
139
|
+
__metadata("design:paramtypes", []),
|
|
140
|
+
__metadata("design:returntype", Promise)
|
|
141
|
+
], ExampleService.prototype, "criticalTask", null);
|
|
142
|
+
__decorate([
|
|
143
|
+
(0, redis_lock_decorator_1.UseRedisLock)('cleanup-task', {
|
|
144
|
+
ttl: 120000,
|
|
145
|
+
skipReturnValue: 'skipped',
|
|
146
|
+
}),
|
|
147
|
+
__metadata("design:type", Function),
|
|
148
|
+
__metadata("design:paramtypes", []),
|
|
149
|
+
__metadata("design:returntype", Promise)
|
|
150
|
+
], ExampleService.prototype, "cleanupTask", null);
|
|
151
|
+
__decorate([
|
|
152
|
+
(0, redis_lock_decorator_1.UseRedisLock)('hourly-report', { ttl: 3600000 }),
|
|
153
|
+
__metadata("design:type", Function),
|
|
154
|
+
__metadata("design:paramtypes", []),
|
|
155
|
+
__metadata("design:returntype", Promise)
|
|
156
|
+
], ExampleService.prototype, "generateHourlyReport", null);
|
|
157
|
+
exports.ExampleService = ExampleService = ExampleService_1 = __decorate([
|
|
158
|
+
(0, common_1.Injectable)()
|
|
159
|
+
], ExampleService);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DynamicModule, OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import type { Redis } from 'ioredis';
|
|
3
|
+
export declare const REDIS_LOCK_SERVICE: unique symbol;
|
|
4
|
+
export interface RedisLockModuleOptions {
|
|
5
|
+
isGlobal?: boolean;
|
|
6
|
+
redisClient: Redis;
|
|
7
|
+
defaultTtl?: number;
|
|
8
|
+
defaultKeyPrefix?: string;
|
|
9
|
+
defaultRetryCount?: number;
|
|
10
|
+
defaultRetryDelay?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class RedisLockModule implements OnModuleInit {
|
|
13
|
+
private redisLockService;
|
|
14
|
+
constructor();
|
|
15
|
+
static forRoot(options: RedisLockModuleOptions): DynamicModule;
|
|
16
|
+
static forRootAsync(options: {
|
|
17
|
+
imports?: any[];
|
|
18
|
+
inject?: any[];
|
|
19
|
+
useFactory: (...args: any[]) => Promise<RedisLockModuleOptions> | RedisLockModuleOptions;
|
|
20
|
+
isGlobal?: boolean;
|
|
21
|
+
}): DynamicModule;
|
|
22
|
+
onModuleInit(): void;
|
|
23
|
+
}
|