@nest-omni/core 4.1.3-2 → 4.1.3-4
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/audit/audit.module.d.ts +10 -0
- package/audit/audit.module.js +15 -0
- package/audit/controllers/audit.controller.d.ts +24 -0
- package/audit/controllers/audit.controller.js +24 -0
- package/audit/decorators/audit-controller.decorator.d.ts +8 -0
- package/audit/decorators/audit-controller.decorator.js +9 -0
- package/audit/decorators/audit-operation.decorator.d.ts +45 -0
- package/audit/decorators/audit-operation.decorator.js +49 -0
- package/audit/decorators/entity-audit.decorator.d.ts +8 -0
- package/audit/decorators/entity-audit.decorator.js +9 -0
- package/audit/dto/audit-log-query.dto.d.ts +3 -0
- package/audit/dto/audit-log-query.dto.js +3 -0
- package/audit/dto/begin-transaction.dto.d.ts +3 -0
- package/audit/dto/begin-transaction.dto.js +3 -0
- package/audit/dto/compare-entities.dto.d.ts +3 -0
- package/audit/dto/compare-entities.dto.js +3 -0
- package/audit/dto/pre-check-restore.dto.d.ts +3 -0
- package/audit/dto/pre-check-restore.dto.js +3 -0
- package/audit/dto/restore-entity.dto.d.ts +3 -0
- package/audit/dto/restore-entity.dto.js +3 -0
- package/audit/entities/entity-audit-log.entity.d.ts +3 -0
- package/audit/entities/entity-audit-log.entity.js +3 -0
- package/audit/entities/entity-transaction.entity.d.ts +3 -0
- package/audit/entities/entity-transaction.entity.js +3 -0
- package/audit/entities/manual-operation-log.entity.d.ts +4 -0
- package/audit/entities/manual-operation-log.entity.js +4 -0
- package/audit/entities/operation-template.entity.d.ts +4 -0
- package/audit/entities/operation-template.entity.js +4 -0
- package/audit/enums/audit.enums.d.ts +17 -2
- package/audit/enums/audit.enums.js +15 -0
- package/audit/index.js +10 -0
- package/audit/interceptors/audit.interceptor.d.ts +15 -0
- package/audit/interceptors/audit.interceptor.js +23 -1
- package/audit/interfaces/audit.interfaces.d.ts +42 -0
- package/audit/services/audit-context.service.d.ts +15 -0
- package/audit/services/audit-context.service.js +15 -0
- package/audit/services/audit-strategy.service.d.ts +6 -0
- package/audit/services/audit-strategy.service.js +13 -0
- package/audit/services/entity-audit.service.d.ts +57 -0
- package/audit/services/entity-audit.service.js +91 -0
- package/audit/services/manual-audit-log.service.d.ts +124 -0
- package/audit/services/manual-audit-log.service.js +138 -0
- package/audit/services/multi-database.service.d.ts +12 -0
- package/audit/services/multi-database.service.js +12 -0
- package/audit/services/operation-description.service.d.ts +59 -0
- package/audit/services/operation-description.service.js +76 -2
- package/audit/services/transaction-audit.service.d.ts +30 -0
- package/audit/services/transaction-audit.service.js +47 -0
- package/audit/subscribers/entity-audit.subscriber.d.ts +15 -0
- package/audit/subscribers/entity-audit.subscriber.js +29 -1
- package/cache/cache-metrics.service.d.ts +67 -0
- package/cache/cache-metrics.service.js +68 -4
- package/cache/cache-serialization.service.d.ts +31 -0
- package/cache/cache-serialization.service.js +25 -0
- package/cache/cache.constants.d.ts +9 -0
- package/cache/cache.constants.js +9 -0
- package/cache/cache.health.d.ts +26 -0
- package/cache/cache.health.js +30 -0
- package/cache/cache.module.d.ts +86 -0
- package/cache/cache.module.js +71 -0
- package/cache/cache.service.d.ts +140 -0
- package/cache/cache.service.js +157 -0
- package/cache/cache.warmup.service.d.ts +39 -0
- package/cache/cache.warmup.service.js +32 -0
- package/cache/decorators/cache-evict.decorator.d.ts +47 -0
- package/cache/decorators/cache-evict.decorator.js +56 -0
- package/cache/decorators/cache-put.decorator.d.ts +34 -0
- package/cache/decorators/cache-put.decorator.js +39 -0
- package/cache/decorators/cacheable.decorator.d.ts +40 -0
- package/cache/decorators/cacheable.decorator.js +55 -0
- package/cache/dependencies/callback.dependency.d.ts +33 -0
- package/cache/dependencies/callback.dependency.js +39 -1
- package/cache/dependencies/chain.dependency.d.ts +28 -0
- package/cache/dependencies/chain.dependency.js +34 -0
- package/cache/dependencies/db.dependency.d.ts +45 -0
- package/cache/dependencies/db.dependency.js +48 -1
- package/cache/dependencies/file.dependency.d.ts +32 -0
- package/cache/dependencies/file.dependency.js +34 -0
- package/cache/dependencies/tag.dependency.d.ts +36 -0
- package/cache/dependencies/tag.dependency.js +36 -0
- package/cache/dependencies/time.dependency.d.ts +43 -0
- package/cache/dependencies/time.dependency.js +43 -0
- package/cache/examples/basic-usage.d.ts +15 -0
- package/cache/examples/basic-usage.js +62 -8
- package/cache/index.js +9 -0
- package/cache/interfaces/cache-dependency.interface.d.ts +53 -0
- package/cache/interfaces/cache-options.interface.d.ts +81 -0
- package/cache/interfaces/cache-options.interface.js +6 -0
- package/cache/interfaces/cache-provider.interface.d.ts +78 -0
- package/cache/providers/base-cache.provider.d.ts +14 -0
- package/cache/providers/base-cache.provider.js +16 -0
- package/cache/providers/cls-cache.provider.d.ts +20 -0
- package/cache/providers/cls-cache.provider.js +28 -0
- package/cache/providers/memory-cache.provider.d.ts +23 -0
- package/cache/providers/memory-cache.provider.js +26 -0
- package/cache/providers/redis-cache.provider.d.ts +26 -0
- package/cache/providers/redis-cache.provider.js +29 -0
- package/cache/utils/dependency-manager.util.d.ts +52 -0
- package/cache/utils/dependency-manager.util.js +59 -0
- package/cache/utils/key-generator.util.d.ts +42 -0
- package/cache/utils/key-generator.util.js +53 -1
- package/common/abstract.entity.d.ts +14 -0
- package/common/abstract.entity.js +14 -0
- package/common/boilerplate.polyfill.d.ts +142 -0
- package/common/boilerplate.polyfill.js +17 -0
- package/common/dto/dto-container.d.ts +16 -0
- package/common/dto/dto-container.js +20 -0
- package/common/dto/dto-decorators.d.ts +18 -0
- package/common/dto/dto-decorators.js +14 -0
- package/common/dto/dto-extensions.d.ts +11 -0
- package/common/dto/dto-extensions.js +9 -0
- package/common/dto/dto-service-accessor.d.ts +17 -0
- package/common/dto/dto-service-accessor.js +18 -0
- package/common/dto/dto-transformer.d.ts +12 -0
- package/common/dto/dto-transformer.js +9 -0
- package/common/dto/index.js +2 -0
- package/common/examples/paginate-and-map.example.d.ts +6 -0
- package/common/examples/paginate-and-map.example.js +26 -0
- package/common/utils.d.ts +15 -0
- package/common/utils.js +15 -0
- package/constants/language-code.js +1 -0
- package/decorators/field.decorators.js +8 -1
- package/decorators/property.decorators.js +1 -0
- package/decorators/public-route.decorator.js +1 -0
- package/decorators/transform.decorators.d.ts +27 -0
- package/decorators/transform.decorators.js +29 -0
- package/decorators/translate.decorator.js +1 -0
- package/decorators/user.decorator.js +1 -0
- package/decorators/validator.decorators.d.ts +8 -18
- package/decorators/validator.decorators.js +22 -190
- package/filters/constraint-errors.js +1 -0
- package/helpers/common.helper.d.ts +13 -0
- package/helpers/common.helper.js +13 -0
- package/http-client/config/http-client.config.d.ts +15 -0
- package/http-client/config/http-client.config.js +25 -9
- package/http-client/decorators/http-client.decorators.d.ts +63 -0
- package/http-client/decorators/http-client.decorators.js +71 -3
- package/http-client/entities/http-log.entity.d.ts +229 -0
- package/http-client/entities/http-log.entity.js +6 -1
- package/http-client/errors/http-client.errors.d.ts +57 -0
- package/http-client/errors/http-client.errors.js +58 -0
- package/http-client/examples/advanced-usage.example.d.ts +41 -0
- package/http-client/examples/advanced-usage.example.js +68 -24
- package/http-client/examples/auth-with-waiting-lock.example.d.ts +31 -0
- package/http-client/examples/auth-with-waiting-lock.example.js +52 -5
- package/http-client/examples/basic-usage.example.d.ts +60 -0
- package/http-client/examples/basic-usage.example.js +60 -0
- package/http-client/examples/multi-api-configuration.example.d.ts +60 -0
- package/http-client/examples/multi-api-configuration.example.js +76 -5
- package/http-client/http-client.module.d.ts +13 -0
- package/http-client/http-client.module.js +19 -0
- package/http-client/index.js +8 -0
- package/http-client/interfaces/api-client-config.interface.d.ts +125 -0
- package/http-client/interfaces/api-client-config.interface.js +3 -0
- package/http-client/interfaces/http-client-config.interface.d.ts +60 -0
- package/http-client/services/api-client-registry.service.d.ts +57 -0
- package/http-client/services/api-client-registry.service.js +84 -1
- package/http-client/services/cache.service.d.ts +52 -0
- package/http-client/services/cache.service.js +72 -3
- package/http-client/services/circuit-breaker.service.d.ts +46 -0
- package/http-client/services/circuit-breaker.service.js +52 -0
- package/http-client/services/http-client.service.d.ts +67 -0
- package/http-client/services/http-client.service.js +105 -4
- package/http-client/services/http-log-query.service.d.ts +83 -0
- package/http-client/services/http-log-query.service.js +122 -1
- package/http-client/services/http-replay.service.d.ts +101 -0
- package/http-client/services/http-replay.service.js +86 -0
- package/http-client/services/log-cleanup.service.d.ts +63 -0
- package/http-client/services/log-cleanup.service.js +54 -2
- package/http-client/services/logging.service.d.ts +40 -0
- package/http-client/services/logging.service.js +53 -0
- package/http-client/utils/call-stack-extractor.util.d.ts +37 -0
- package/http-client/utils/call-stack-extractor.util.js +48 -0
- package/http-client/utils/context-extractor.util.d.ts +49 -0
- package/http-client/utils/context-extractor.util.js +52 -0
- package/http-client/utils/curl-generator.util.d.ts +21 -0
- package/http-client/utils/curl-generator.util.js +44 -3
- package/http-client/utils/request-id.util.d.ts +18 -0
- package/http-client/utils/request-id.util.js +20 -0
- package/http-client/utils/retry-recorder.util.d.ts +42 -0
- package/http-client/utils/retry-recorder.util.js +44 -0
- package/index.js +8 -0
- package/interceptors/translation-interceptor.service.js +5 -0
- package/package.json +1 -1
- package/providers/context.provider.js +2 -0
- package/providers/generator.provider.d.ts +4 -0
- package/providers/generator.provider.js +4 -0
- package/redis-lock/examples/lock-strategy.examples.d.ts +89 -0
- package/redis-lock/examples/lock-strategy.examples.js +130 -15
- package/redis-lock/index.js +3 -0
- package/redis-lock/redis-lock.decorator.d.ts +101 -0
- package/redis-lock/redis-lock.decorator.js +120 -0
- package/redis-lock/redis-lock.module.d.ts +60 -0
- package/redis-lock/redis-lock.module.js +46 -0
- package/redis-lock/redis-lock.service.d.ts +251 -0
- package/redis-lock/redis-lock.service.js +219 -3
- package/setup/bootstrap.setup.js +20 -0
- package/setup/mode.setup.d.ts +44 -0
- package/setup/mode.setup.js +44 -0
- package/setup/schedule.decorator.d.ts +226 -0
- package/setup/schedule.decorator.js +214 -1
- package/setup/worker.decorator.d.ts +86 -0
- package/setup/worker.decorator.js +88 -0
- package/shared/serviceRegistryModule.js +5 -1
- package/shared/services/api-config.service.d.ts +3 -0
- package/shared/services/api-config.service.js +20 -9
- package/validator-json/decorators.d.ts +17 -0
- package/validator-json/decorators.js +17 -2
- package/validator-json/default.d.ts +6 -0
- package/validator-json/default.js +30 -2
- package/validator-json/defaultConverters.js +1 -0
- package/validator-json/options.d.ts +23 -0
- package/validators/common-validators.d.ts +143 -0
- package/validators/common-validators.js +249 -0
- package/validators/custom-validate.examples.d.ts +23 -0
- package/validators/custom-validate.examples.js +78 -6
- package/validators/custom-validate.validator.d.ts +107 -0
- package/validators/custom-validate.validator.js +84 -0
- package/validators/index.d.ts +1 -0
- package/validators/index.js +1 -0
- package/validators/is-exists.validator.d.ts +11 -0
- package/validators/is-exists.validator.js +22 -0
- package/validators/is-unique.validator.d.ts +11 -0
- package/validators/is-unique.validator.js +31 -3
- package/validators/skip-empty.validator.d.ts +5 -0
- package/validators/skip-empty.validator.js +5 -0
- package/vault/interfaces/vault-options.interface.d.ts +9 -0
- package/vault/vault-config.loader.d.ts +30 -0
- package/vault/vault-config.loader.js +48 -1
- package/vault/vault-config.service.d.ts +53 -0
- package/vault/vault-config.service.js +57 -0
- package/vault/vault.module.d.ts +4 -0
- package/vault/vault.module.js +4 -0
- package/decorators/examples/validation-decorators.example.d.ts +0 -69
- package/decorators/examples/validation-decorators.example.js +0 -331
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Lock Strategy Examples
|
|
4
|
+
*
|
|
5
|
+
* This file demonstrates the different lock acquisition strategies available in Redis Lock module.
|
|
6
|
+
*/
|
|
2
7
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
8
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
9
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -23,18 +28,33 @@ exports.CombinedStrategiesExample = exports.WaitStrategyExample = exports.ThrowS
|
|
|
23
28
|
const common_1 = require("@nestjs/common");
|
|
24
29
|
const schedule_1 = require("@nestjs/schedule");
|
|
25
30
|
const index_1 = require("../index");
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Strategy 1: SKIP (Default)
|
|
33
|
+
// ============================================================================
|
|
34
|
+
/**
|
|
35
|
+
* SKIP strategy - Skip execution if lock cannot be acquired
|
|
36
|
+
* This is the default behavior and is useful for scheduled tasks where you don't
|
|
37
|
+
* want to queue up requests if a previous execution is still running.
|
|
38
|
+
*/
|
|
26
39
|
let SkipStrategyExample = SkipStrategyExample_1 = class SkipStrategyExample {
|
|
27
40
|
constructor(lockService) {
|
|
28
41
|
this.lockService = lockService;
|
|
29
42
|
this.logger = new common_1.Logger(SkipStrategyExample_1.name);
|
|
30
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Example 1: Using decorator with SKIP strategy (default)
|
|
46
|
+
*/
|
|
31
47
|
scheduledTask() {
|
|
32
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
49
|
this.logger.log('Executing scheduled task...');
|
|
50
|
+
// This will skip if another instance is already running
|
|
34
51
|
yield this.simulateLongRunning();
|
|
35
52
|
this.logger.log('Scheduled task completed');
|
|
36
53
|
});
|
|
37
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Example 2: Using service directly with SKIP strategy
|
|
57
|
+
*/
|
|
38
58
|
processWithSkip() {
|
|
39
59
|
return __awaiter(this, void 0, void 0, function* () {
|
|
40
60
|
const lockResult = yield this.lockService.acquireLock('process-task', {
|
|
@@ -55,13 +75,16 @@ let SkipStrategyExample = SkipStrategyExample_1 = class SkipStrategyExample {
|
|
|
55
75
|
}
|
|
56
76
|
});
|
|
57
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Example 3: SKIP with retries
|
|
80
|
+
*/
|
|
58
81
|
processWithRetries() {
|
|
59
82
|
return __awaiter(this, void 0, void 0, function* () {
|
|
60
83
|
const lockResult = yield this.lockService.acquireLock('retry-task', {
|
|
61
84
|
strategy: index_1.LockStrategy.SKIP,
|
|
62
85
|
ttl: 30000,
|
|
63
|
-
retryCount: 3,
|
|
64
|
-
retryDelay: 500,
|
|
86
|
+
retryCount: 3, // Try 3 times
|
|
87
|
+
retryDelay: 500, // Wait 500ms between retries
|
|
65
88
|
});
|
|
66
89
|
if (!lockResult.acquired) {
|
|
67
90
|
this.logger.warn('Failed to acquire lock after 3 retries');
|
|
@@ -84,10 +107,11 @@ let SkipStrategyExample = SkipStrategyExample_1 = class SkipStrategyExample {
|
|
|
84
107
|
};
|
|
85
108
|
exports.SkipStrategyExample = SkipStrategyExample;
|
|
86
109
|
__decorate([
|
|
87
|
-
(0, schedule_1.Cron)('* * * * *')
|
|
110
|
+
(0, schedule_1.Cron)('* * * * *') // Every minute
|
|
111
|
+
,
|
|
88
112
|
(0, index_1.UseRedisLock)('scheduled-task', {
|
|
89
113
|
ttl: 60000,
|
|
90
|
-
strategy: index_1.LockStrategy.SKIP,
|
|
114
|
+
strategy: index_1.LockStrategy.SKIP, // Can be omitted as it's the default
|
|
91
115
|
}),
|
|
92
116
|
__metadata("design:type", Function),
|
|
93
117
|
__metadata("design:paramtypes", []),
|
|
@@ -97,18 +121,33 @@ exports.SkipStrategyExample = SkipStrategyExample = SkipStrategyExample_1 = __de
|
|
|
97
121
|
(0, common_1.Injectable)(),
|
|
98
122
|
__metadata("design:paramtypes", [index_1.RedisLockService])
|
|
99
123
|
], SkipStrategyExample);
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Strategy 2: THROW
|
|
126
|
+
// ============================================================================
|
|
127
|
+
/**
|
|
128
|
+
* THROW strategy - Throw an error if lock cannot be acquired
|
|
129
|
+
* Use this for critical operations that must have exclusive access.
|
|
130
|
+
* If the lock cannot be acquired, an exception will be thrown.
|
|
131
|
+
*/
|
|
100
132
|
let ThrowStrategyExample = ThrowStrategyExample_1 = class ThrowStrategyExample {
|
|
101
133
|
constructor(lockService) {
|
|
102
134
|
this.lockService = lockService;
|
|
103
135
|
this.logger = new common_1.Logger(ThrowStrategyExample_1.name);
|
|
104
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Example 1: Using decorator with THROW strategy
|
|
139
|
+
*/
|
|
105
140
|
criticalOperation() {
|
|
106
141
|
return __awaiter(this, void 0, void 0, function* () {
|
|
107
142
|
this.logger.log('Executing critical operation...');
|
|
143
|
+
// If lock cannot be acquired, an error will be thrown
|
|
108
144
|
yield this.processData();
|
|
109
145
|
this.logger.log('Critical operation completed');
|
|
110
146
|
});
|
|
111
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Example 2: Using service with error handling
|
|
150
|
+
*/
|
|
112
151
|
processWithThrow() {
|
|
113
152
|
return __awaiter(this, void 0, void 0, function* () {
|
|
114
153
|
try {
|
|
@@ -127,20 +166,26 @@ let ThrowStrategyExample = ThrowStrategyExample_1 = class ThrowStrategyExample {
|
|
|
127
166
|
}
|
|
128
167
|
catch (error) {
|
|
129
168
|
this.logger.error(`Failed to acquire lock: ${error.message}`);
|
|
169
|
+
// Handle the error appropriately
|
|
130
170
|
throw new Error('Operation cannot proceed without exclusive access');
|
|
131
171
|
}
|
|
132
172
|
});
|
|
133
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Example 3: Critical payment processing
|
|
176
|
+
*/
|
|
134
177
|
processPayment(orderId, amount) {
|
|
135
178
|
return __awaiter(this, void 0, void 0, function* () {
|
|
136
179
|
const lockKey = `payment:${orderId}`;
|
|
137
180
|
try {
|
|
181
|
+
// Must have exclusive access for payment processing
|
|
138
182
|
const lockResult = yield this.lockService.acquireLock(lockKey, {
|
|
139
183
|
strategy: index_1.LockStrategy.THROW,
|
|
140
184
|
ttl: 60000,
|
|
141
185
|
});
|
|
142
186
|
try {
|
|
143
187
|
this.logger.log(`Processing payment for order ${orderId}...`);
|
|
188
|
+
// Payment logic here
|
|
144
189
|
yield this.chargePayment(orderId, amount);
|
|
145
190
|
yield this.updateOrderStatus(orderId, 'paid');
|
|
146
191
|
return { success: true };
|
|
@@ -162,11 +207,13 @@ let ThrowStrategyExample = ThrowStrategyExample_1 = class ThrowStrategyExample {
|
|
|
162
207
|
}
|
|
163
208
|
chargePayment(orderId, amount) {
|
|
164
209
|
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
+
// Simulate payment processing
|
|
165
211
|
yield new Promise((resolve) => setTimeout(resolve, 1000));
|
|
166
212
|
});
|
|
167
213
|
}
|
|
168
214
|
updateOrderStatus(orderId, status) {
|
|
169
215
|
return __awaiter(this, void 0, void 0, function* () {
|
|
216
|
+
// Update order status
|
|
170
217
|
yield new Promise((resolve) => setTimeout(resolve, 500));
|
|
171
218
|
});
|
|
172
219
|
}
|
|
@@ -185,24 +232,39 @@ exports.ThrowStrategyExample = ThrowStrategyExample = ThrowStrategyExample_1 = _
|
|
|
185
232
|
(0, common_1.Injectable)(),
|
|
186
233
|
__metadata("design:paramtypes", [index_1.RedisLockService])
|
|
187
234
|
], ThrowStrategyExample);
|
|
235
|
+
// ============================================================================
|
|
236
|
+
// Strategy 3: WAIT
|
|
237
|
+
// ============================================================================
|
|
238
|
+
/**
|
|
239
|
+
* WAIT strategy - Block/wait until lock can be acquired
|
|
240
|
+
* Use this when you want to queue execution and ensure the operation eventually runs.
|
|
241
|
+
* The function will wait indefinitely (or until waitTimeout) for the lock to become available.
|
|
242
|
+
*/
|
|
188
243
|
let WaitStrategyExample = WaitStrategyExample_1 = class WaitStrategyExample {
|
|
189
244
|
constructor(lockService) {
|
|
190
245
|
this.lockService = lockService;
|
|
191
246
|
this.logger = new common_1.Logger(WaitStrategyExample_1.name);
|
|
192
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Example 1: Using decorator with WAIT strategy
|
|
250
|
+
*/
|
|
193
251
|
sequentialTask() {
|
|
194
252
|
return __awaiter(this, void 0, void 0, function* () {
|
|
195
253
|
this.logger.log('Executing sequential task...');
|
|
254
|
+
// This will wait until lock is available
|
|
196
255
|
yield this.processInOrder();
|
|
197
256
|
this.logger.log('Sequential task completed');
|
|
198
257
|
});
|
|
199
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* Example 2: WAIT with timeout
|
|
261
|
+
*/
|
|
200
262
|
processWithWaitTimeout() {
|
|
201
263
|
return __awaiter(this, void 0, void 0, function* () {
|
|
202
264
|
const lockResult = yield this.lockService.acquireLock('wait-task', {
|
|
203
265
|
strategy: index_1.LockStrategy.WAIT,
|
|
204
|
-
waitTimeout: 30000,
|
|
205
|
-
retryDelay: 200,
|
|
266
|
+
waitTimeout: 30000, // Wait maximum 30 seconds
|
|
267
|
+
retryDelay: 200, // Check every 200ms
|
|
206
268
|
ttl: 60000,
|
|
207
269
|
});
|
|
208
270
|
if (!lockResult.acquired) {
|
|
@@ -219,16 +281,21 @@ let WaitStrategyExample = WaitStrategyExample_1 = class WaitStrategyExample {
|
|
|
219
281
|
}
|
|
220
282
|
});
|
|
221
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Example 3: Sequential data processing
|
|
286
|
+
* Perfect for operations that must be processed in order
|
|
287
|
+
*/
|
|
222
288
|
processDataSequentially(userId, data) {
|
|
223
289
|
return __awaiter(this, void 0, void 0, function* () {
|
|
224
290
|
const lockKey = `user-data:${userId}`;
|
|
225
291
|
const lockResult = yield this.lockService.acquireLock(lockKey, {
|
|
226
292
|
strategy: index_1.LockStrategy.WAIT,
|
|
227
293
|
retryDelay: 50,
|
|
228
|
-
ttl: 120000,
|
|
294
|
+
ttl: 120000, // 2 minutes
|
|
229
295
|
});
|
|
230
296
|
try {
|
|
231
297
|
this.logger.log(`Processing data for user ${userId}...`);
|
|
298
|
+
// These operations will execute sequentially across all instances
|
|
232
299
|
yield this.validateData(data);
|
|
233
300
|
yield this.saveData(userId, data);
|
|
234
301
|
yield this.notifyUser(userId);
|
|
@@ -239,6 +306,10 @@ let WaitStrategyExample = WaitStrategyExample_1 = class WaitStrategyExample {
|
|
|
239
306
|
}
|
|
240
307
|
});
|
|
241
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* Example 4: Queue-like behavior
|
|
311
|
+
* Multiple requests will queue and execute one by one
|
|
312
|
+
*/
|
|
242
313
|
processQueue(queueName, item) {
|
|
243
314
|
return __awaiter(this, void 0, void 0, function* () {
|
|
244
315
|
const lockKey = `queue:${queueName}`;
|
|
@@ -258,15 +329,19 @@ let WaitStrategyExample = WaitStrategyExample_1 = class WaitStrategyExample {
|
|
|
258
329
|
}
|
|
259
330
|
});
|
|
260
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Example 5: Database migration with WAIT
|
|
334
|
+
* Ensures migrations run sequentially across all instances
|
|
335
|
+
*/
|
|
261
336
|
runMigration(migrationName) {
|
|
262
337
|
return __awaiter(this, void 0, void 0, function* () {
|
|
263
338
|
const lockKey = `migration:${migrationName}`;
|
|
264
339
|
this.logger.log(`Waiting to run migration ${migrationName}...`);
|
|
265
340
|
const lockResult = yield this.lockService.acquireLock(lockKey, {
|
|
266
341
|
strategy: index_1.LockStrategy.WAIT,
|
|
267
|
-
waitTimeout: 300000,
|
|
268
|
-
retryDelay: 1000,
|
|
269
|
-
ttl: 600000,
|
|
342
|
+
waitTimeout: 300000, // Wait up to 5 minutes
|
|
343
|
+
retryDelay: 1000, // Check every second
|
|
344
|
+
ttl: 600000, // Hold lock for 10 minutes max
|
|
270
345
|
});
|
|
271
346
|
if (!lockResult.acquired) {
|
|
272
347
|
throw new Error(`Migration ${migrationName} timed out waiting for lock`);
|
|
@@ -318,7 +393,7 @@ __decorate([
|
|
|
318
393
|
(0, index_1.UseRedisLock)('sequential-task', {
|
|
319
394
|
ttl: 30000,
|
|
320
395
|
strategy: index_1.LockStrategy.WAIT,
|
|
321
|
-
retryDelay: 100,
|
|
396
|
+
retryDelay: 100, // Check every 100ms
|
|
322
397
|
}),
|
|
323
398
|
__metadata("design:type", Function),
|
|
324
399
|
__metadata("design:paramtypes", []),
|
|
@@ -328,16 +403,50 @@ exports.WaitStrategyExample = WaitStrategyExample = WaitStrategyExample_1 = __de
|
|
|
328
403
|
(0, common_1.Injectable)(),
|
|
329
404
|
__metadata("design:paramtypes", [index_1.RedisLockService])
|
|
330
405
|
], WaitStrategyExample);
|
|
406
|
+
// ============================================================================
|
|
407
|
+
// Comparison: When to use each strategy
|
|
408
|
+
// ============================================================================
|
|
409
|
+
/**
|
|
410
|
+
* USE SKIP WHEN:
|
|
411
|
+
* - Running scheduled tasks where you don't want overlapping executions
|
|
412
|
+
* - Cron jobs that should skip if previous run is still in progress
|
|
413
|
+
* - Non-critical background tasks
|
|
414
|
+
* - Operations where it's okay to skip if busy
|
|
415
|
+
*
|
|
416
|
+
* USE THROW WHEN:
|
|
417
|
+
* - Critical operations that require exclusive access
|
|
418
|
+
* - Financial transactions
|
|
419
|
+
* - Operations where failure to acquire lock is an error
|
|
420
|
+
* - When you want to alert/fail fast if resource is busy
|
|
421
|
+
*
|
|
422
|
+
* USE WAIT WHEN:
|
|
423
|
+
* - Operations that must execute eventually
|
|
424
|
+
* - Sequential processing requirements
|
|
425
|
+
* - Queue-like behavior needed
|
|
426
|
+
* - Database migrations
|
|
427
|
+
* - Operations where order matters
|
|
428
|
+
* - When you want to ensure the operation runs (with optional timeout)
|
|
429
|
+
*/
|
|
430
|
+
/**
|
|
431
|
+
* Example: Combining strategies in a single service
|
|
432
|
+
*/
|
|
331
433
|
let CombinedStrategiesExample = CombinedStrategiesExample_1 = class CombinedStrategiesExample {
|
|
332
434
|
constructor(lockService) {
|
|
333
435
|
this.lockService = lockService;
|
|
334
436
|
this.logger = new common_1.Logger(CombinedStrategiesExample_1.name);
|
|
335
437
|
}
|
|
438
|
+
/**
|
|
439
|
+
* Background cleanup - SKIP if already running
|
|
440
|
+
*/
|
|
336
441
|
cleanupOldData() {
|
|
337
442
|
return __awaiter(this, void 0, void 0, function* () {
|
|
338
443
|
this.logger.log('Running cleanup...');
|
|
444
|
+
// Cleanup logic
|
|
339
445
|
});
|
|
340
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Payment processing - THROW if cannot get exclusive access
|
|
449
|
+
*/
|
|
341
450
|
processPayment(orderId) {
|
|
342
451
|
return __awaiter(this, void 0, void 0, function* () {
|
|
343
452
|
const lockResult = yield this.lockService.acquireLock(`payment:${orderId}`, {
|
|
@@ -345,24 +454,29 @@ let CombinedStrategiesExample = CombinedStrategiesExample_1 = class CombinedStra
|
|
|
345
454
|
ttl: 60000,
|
|
346
455
|
});
|
|
347
456
|
try {
|
|
457
|
+
// Payment logic
|
|
348
458
|
}
|
|
349
459
|
finally {
|
|
350
460
|
yield this.lockService.releaseLock(`payment:${orderId}`, lockResult.lockValue);
|
|
351
461
|
}
|
|
352
462
|
});
|
|
353
463
|
}
|
|
464
|
+
/**
|
|
465
|
+
* Report generation - WAIT to ensure it runs eventually
|
|
466
|
+
*/
|
|
354
467
|
generateReport(reportId) {
|
|
355
468
|
return __awaiter(this, void 0, void 0, function* () {
|
|
356
469
|
const lockResult = yield this.lockService.acquireLock(`report:${reportId}`, {
|
|
357
470
|
strategy: index_1.LockStrategy.WAIT,
|
|
358
|
-
waitTimeout: 180000,
|
|
471
|
+
waitTimeout: 180000, // Wait up to 3 minutes
|
|
359
472
|
retryDelay: 500,
|
|
360
|
-
ttl: 300000,
|
|
473
|
+
ttl: 300000, // 5 minutes
|
|
361
474
|
});
|
|
362
475
|
if (!lockResult.acquired) {
|
|
363
476
|
throw new Error('Report generation timed out');
|
|
364
477
|
}
|
|
365
478
|
try {
|
|
479
|
+
// Report generation logic
|
|
366
480
|
}
|
|
367
481
|
finally {
|
|
368
482
|
yield this.lockService.releaseLock(`report:${reportId}`, lockResult.lockValue);
|
|
@@ -372,10 +486,11 @@ let CombinedStrategiesExample = CombinedStrategiesExample_1 = class CombinedStra
|
|
|
372
486
|
};
|
|
373
487
|
exports.CombinedStrategiesExample = CombinedStrategiesExample;
|
|
374
488
|
__decorate([
|
|
375
|
-
(0, schedule_1.Cron)('0 */6 * * *')
|
|
489
|
+
(0, schedule_1.Cron)('0 */6 * * *') // Every 6 hours
|
|
490
|
+
,
|
|
376
491
|
(0, index_1.UseRedisLock)('cleanup-task', {
|
|
377
492
|
strategy: index_1.LockStrategy.SKIP,
|
|
378
|
-
ttl: 3600000,
|
|
493
|
+
ttl: 3600000, // 1 hour
|
|
379
494
|
}),
|
|
380
495
|
__metadata("design:type", Function),
|
|
381
496
|
__metadata("design:paramtypes", []),
|
package/redis-lock/index.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getLockService = exports.setLockService = exports.UseRedisLockOrSkipSmart = exports.UseRedisLockSmart = exports.UseRedisLockOrSkip = exports.UseRedisLock = exports.LockStrategy = exports.RedisLockService = exports.REDIS_LOCK_SERVICE = exports.RedisLockModule = void 0;
|
|
4
|
+
// Module
|
|
4
5
|
var redis_lock_module_1 = require("./redis-lock.module");
|
|
5
6
|
Object.defineProperty(exports, "RedisLockModule", { enumerable: true, get: function () { return redis_lock_module_1.RedisLockModule; } });
|
|
6
7
|
Object.defineProperty(exports, "REDIS_LOCK_SERVICE", { enumerable: true, get: function () { return redis_lock_module_1.REDIS_LOCK_SERVICE; } });
|
|
8
|
+
// Service
|
|
7
9
|
var redis_lock_service_1 = require("./redis-lock.service");
|
|
8
10
|
Object.defineProperty(exports, "RedisLockService", { enumerable: true, get: function () { return redis_lock_service_1.RedisLockService; } });
|
|
9
11
|
Object.defineProperty(exports, "LockStrategy", { enumerable: true, get: function () { return redis_lock_service_1.LockStrategy; } });
|
|
12
|
+
// Decorators
|
|
10
13
|
var redis_lock_decorator_1 = require("./redis-lock.decorator");
|
|
11
14
|
Object.defineProperty(exports, "UseRedisLock", { enumerable: true, get: function () { return redis_lock_decorator_1.UseRedisLock; } });
|
|
12
15
|
Object.defineProperty(exports, "UseRedisLockOrSkip", { enumerable: true, get: function () { return redis_lock_decorator_1.UseRedisLockOrSkip; } });
|
|
@@ -1,12 +1,113 @@
|
|
|
1
1
|
import type { LockOptions } from './redis-lock.service';
|
|
2
2
|
import { RedisLockService } from './redis-lock.service';
|
|
3
|
+
/**
|
|
4
|
+
* Set global LockService instance
|
|
5
|
+
* Called by RedisLockModule during initialization
|
|
6
|
+
*/
|
|
3
7
|
export declare function setLockService(lockService: RedisLockService): void;
|
|
8
|
+
/**
|
|
9
|
+
* Get global LockService instance
|
|
10
|
+
*/
|
|
4
11
|
export declare function getLockService(): RedisLockService | null;
|
|
12
|
+
/**
|
|
13
|
+
* Method decorator that wraps the method execution with a distributed Redis lock
|
|
14
|
+
*
|
|
15
|
+
* This decorator automatically acquires a lock before executing the method
|
|
16
|
+
* and releases it afterwards. If the lock cannot be acquired, the method
|
|
17
|
+
* execution is skipped and returns null (or the value specified in skipReturnValue).
|
|
18
|
+
*
|
|
19
|
+
* @param lockKey - The Redis lock key (required)
|
|
20
|
+
* @param options - Lock options
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* @Injectable()
|
|
25
|
+
* class MyService {
|
|
26
|
+
* @UseRedisLock('my-task', { ttl: 60000 })
|
|
27
|
+
* async processTask() {
|
|
28
|
+
* // This will only execute if the lock is acquired
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
5
33
|
export declare function UseRedisLock(lockKey: string, options?: LockOptions & {
|
|
6
34
|
skipReturnValue?: any;
|
|
7
35
|
}): MethodDecorator;
|
|
36
|
+
/**
|
|
37
|
+
* Simplified decorator for methods that should skip execution if lock cannot be acquired
|
|
38
|
+
* Returns false when skipped, true when executed successfully
|
|
39
|
+
*
|
|
40
|
+
* @param lockKey - The Redis lock key (required)
|
|
41
|
+
* @param ttl - Lock TTL in milliseconds (default: 300000 / 5 minutes)
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* @Injectable()
|
|
46
|
+
* class MyScheduler {
|
|
47
|
+
* @Cron('0 * * * *')
|
|
48
|
+
* @UseRedisLockOrSkip('hourly-task', 3600000)
|
|
49
|
+
* async hourlyTask() {
|
|
50
|
+
* // This will only execute on one instance
|
|
51
|
+
* }
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
8
55
|
export declare function UseRedisLockOrSkip(lockKey: string, ttl?: number): MethodDecorator;
|
|
56
|
+
/**
|
|
57
|
+
* Smart decorator that auto-generates lock key from class and method name
|
|
58
|
+
* Lock key format: ClassName:methodName
|
|
59
|
+
*
|
|
60
|
+
* This decorator is useful for simple cases where you don't need custom lock keys.
|
|
61
|
+
*
|
|
62
|
+
* @param options - Lock options
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* @Injectable()
|
|
67
|
+
* class MyService {
|
|
68
|
+
* // Lock key will be auto-generated as "MyService:processData"
|
|
69
|
+
* @UseRedisLockSmart({ ttl: 60000 })
|
|
70
|
+
* async processData() {
|
|
71
|
+
* // Business logic
|
|
72
|
+
* }
|
|
73
|
+
*
|
|
74
|
+
* // With strategy
|
|
75
|
+
* @UseRedisLockSmart({
|
|
76
|
+
* ttl: 120000,
|
|
77
|
+
* strategy: LockStrategy.WAIT,
|
|
78
|
+
* waitTimeout: 60000,
|
|
79
|
+
* })
|
|
80
|
+
* async generateReport() {
|
|
81
|
+
* // Business logic
|
|
82
|
+
* }
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
9
86
|
export declare function UseRedisLockSmart(options?: LockOptions & {
|
|
10
87
|
skipReturnValue?: any;
|
|
11
88
|
}): MethodDecorator;
|
|
89
|
+
/**
|
|
90
|
+
* Smart decorator for simple skip-on-busy scenarios with auto-generated lock key
|
|
91
|
+
* Lock key format: ClassName:methodName
|
|
92
|
+
*
|
|
93
|
+
* @param ttl - Lock TTL in milliseconds (default: 300000 / 5 minutes)
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* @Injectable()
|
|
98
|
+
* class MyScheduler {
|
|
99
|
+
* @Cron('0 * * * *')
|
|
100
|
+
* @UseRedisLockOrSkipSmart(3600000) // 1 hour TTL
|
|
101
|
+
* async hourlyTask() {
|
|
102
|
+
* // Lock key: "MyScheduler:hourlyTask"
|
|
103
|
+
* }
|
|
104
|
+
*
|
|
105
|
+
* @Cron('0 0 * * *')
|
|
106
|
+
* @UseRedisLockOrSkipSmart() // Default 5 minutes TTL
|
|
107
|
+
* async dailyTask() {
|
|
108
|
+
* // Lock key: "MyScheduler:dailyTask"
|
|
109
|
+
* }
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
12
113
|
export declare function UseRedisLockOrSkipSmart(ttl?: number): MethodDecorator;
|