@nest-omni/core 4.1.3-1 → 4.1.3-10
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 -4
- package/common/boilerplate.polyfill.js +24 -100
- 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/i18n/en_US/validation.json +2 -1
- package/i18n/zh_CN/validation.json +2 -1
- 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/comprehensive-lock-cleanup.service.d.ts +94 -0
- package/redis-lock/comprehensive-lock-cleanup.service.js +253 -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.d.ts +2 -0
- package/redis-lock/index.js +8 -1
- package/redis-lock/lock-heartbeat.service.d.ts +78 -0
- package/redis-lock/lock-heartbeat.service.js +222 -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 +66 -0
- package/redis-lock/redis-lock.module.js +175 -70
- package/redis-lock/redis-lock.service.d.ts +260 -0
- package/redis-lock/redis-lock.service.js +244 -4
- 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 +227 -0
- package/setup/schedule.decorator.js +219 -6
- package/setup/worker.decorator.d.ts +86 -0
- package/setup/worker.decorator.js +88 -0
- package/shared/serviceRegistryModule.js +9 -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 +96 -0
- package/validators/custom-validate.examples.js +400 -0
- package/validators/custom-validate.validator.d.ts +134 -0
- package/validators/custom-validate.validator.js +214 -0
- package/validators/index.d.ts +2 -0
- package/validators/index.js +2 -0
- package/validators/is-exists.validator.d.ts +18 -4
- package/validators/is-exists.validator.js +67 -6
- package/validators/is-unique.validator.d.ts +32 -5
- package/validators/is-unique.validator.js +99 -17
- 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
|
@@ -0,0 +1,253 @@
|
|
|
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 ComprehensiveLockCleanupService_1;
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.ComprehensiveLockCleanupService = void 0;
|
|
23
|
+
const common_1 = require("@nestjs/common");
|
|
24
|
+
const redis_lock_service_1 = require("./redis-lock.service");
|
|
25
|
+
const lock_heartbeat_service_1 = require("./lock-heartbeat.service");
|
|
26
|
+
/**
|
|
27
|
+
* Comprehensive lock cleanup service
|
|
28
|
+
*
|
|
29
|
+
* Provides safe and comprehensive lock cleanup mechanism for distributed environments.
|
|
30
|
+
* Combines instance-based precise cleanup with heartbeat-based dead instance detection.
|
|
31
|
+
*
|
|
32
|
+
* **Cleanup Strategy:**
|
|
33
|
+
* 1. **Immediate Precise Cleanup (0s):**
|
|
34
|
+
* - Only cleans locks from the current instance
|
|
35
|
+
* - Safe during rolling updates - won't affect other running instances
|
|
36
|
+
*
|
|
37
|
+
* 2. **Delayed Conservative Cleanup (60s):**
|
|
38
|
+
* - Checks heartbeat of other instances
|
|
39
|
+
* - Only cleans locks from dead instances (no heartbeat)
|
|
40
|
+
* - Gives enough time for rolling updates to complete
|
|
41
|
+
*
|
|
42
|
+
* 3. **Graceful Shutdown Cleanup:**
|
|
43
|
+
* - On SIGTERM/SIGINT, immediately cleans own locks
|
|
44
|
+
* - Ensures locks are released before process exits
|
|
45
|
+
* - Works with PM2 reload and Kubernetes rolling updates
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // In your module
|
|
50
|
+
* @Module({
|
|
51
|
+
* providers: [
|
|
52
|
+
* RedisLockService,
|
|
53
|
+
* LockHeartbeatService,
|
|
54
|
+
* ComprehensiveLockCleanupService,
|
|
55
|
+
* ],
|
|
56
|
+
* })
|
|
57
|
+
* export class AppModule {}
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
let ComprehensiveLockCleanupService = ComprehensiveLockCleanupService_1 = class ComprehensiveLockCleanupService {
|
|
61
|
+
constructor(lockService, heartbeatService) {
|
|
62
|
+
this.lockService = lockService;
|
|
63
|
+
this.heartbeatService = heartbeatService;
|
|
64
|
+
this.logger = new common_1.Logger(ComprehensiveLockCleanupService_1.name);
|
|
65
|
+
/**
|
|
66
|
+
* Grace period before cleaning other instances' locks (milliseconds)
|
|
67
|
+
* @default 60000 (60 seconds)
|
|
68
|
+
*/
|
|
69
|
+
this.gracePeriod = 60000;
|
|
70
|
+
this.instanceId = this.getInstanceId();
|
|
71
|
+
}
|
|
72
|
+
onModuleInit() {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
this.logger.log('Starting comprehensive lock cleanup...');
|
|
75
|
+
// Step 1: Immediate precise cleanup - only clean own instance's locks
|
|
76
|
+
yield this.cleanupOwnLocks();
|
|
77
|
+
// Step 2: Delayed cleanup - clean dead instances' locks after grace period
|
|
78
|
+
setTimeout(() => {
|
|
79
|
+
this.cleanupDeadInstanceLocks().catch((error) => {
|
|
80
|
+
this.logger.error('Failed to cleanup dead instance locks:', error);
|
|
81
|
+
});
|
|
82
|
+
}, this.gracePeriod);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Clean up locks from the current instance
|
|
87
|
+
* Safe to run immediately - only affects locks created by this instance
|
|
88
|
+
*/
|
|
89
|
+
cleanupOwnLocks() {
|
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
this.logger.log(`Cleaning locks for this instance: ${this.instanceId}`);
|
|
92
|
+
try {
|
|
93
|
+
const allLocks = yield this.lockService.getActiveLocks('*', 'lock');
|
|
94
|
+
let deletedCount = 0;
|
|
95
|
+
for (const lock of allLocks) {
|
|
96
|
+
if (this.isOwnLock(lock.value)) {
|
|
97
|
+
this.logger.warn(`Found stale lock from this instance: ${lock.key}`);
|
|
98
|
+
yield this.lockService.forceRelease(lock.key);
|
|
99
|
+
deletedCount++;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.logger.log(`Cleaned up ${deletedCount} locks from this instance`);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
this.logger.error('Failed to cleanup own locks:', error);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Clean up locks from dead instances
|
|
111
|
+
* Only runs after grace period to avoid cleaning locks during rolling updates
|
|
112
|
+
*/
|
|
113
|
+
cleanupDeadInstanceLocks() {
|
|
114
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
this.logger.log('Cleaning locks from dead instances...');
|
|
116
|
+
try {
|
|
117
|
+
const allLocks = yield this.lockService.getActiveLocks('*', 'lock');
|
|
118
|
+
let deletedCount = 0;
|
|
119
|
+
for (const lock of allLocks) {
|
|
120
|
+
// Skip own instance's locks
|
|
121
|
+
if (this.isOwnLock(lock.value)) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
// Extract instance ID from lock value
|
|
125
|
+
const instanceId = this.extractInstanceId(lock.value);
|
|
126
|
+
if (!instanceId) {
|
|
127
|
+
// Cannot determine instance, skip (might be old format)
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
// Check if instance is alive via heartbeat
|
|
131
|
+
const isAlive = yield this.heartbeatService.isInstanceAlive(instanceId);
|
|
132
|
+
if (!isAlive) {
|
|
133
|
+
this.logger.warn(`Instance ${instanceId} is dead, removing lock: ${lock.key}`);
|
|
134
|
+
yield this.lockService.forceRelease(lock.key);
|
|
135
|
+
deletedCount++;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
this.logger.log(`Cleaned up ${deletedCount} locks from dead instances`);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
this.logger.error('Failed to cleanup dead instance locks:', error);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check if a lock belongs to the current instance
|
|
147
|
+
*
|
|
148
|
+
* @param lockValue - Lock value to check
|
|
149
|
+
* @returns True if lock belongs to current instance
|
|
150
|
+
*/
|
|
151
|
+
isOwnLock(lockValue) {
|
|
152
|
+
if (!lockValue) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
const instanceId = this.extractInstanceId(lockValue);
|
|
156
|
+
return instanceId === this.instanceId;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Extract instance ID from lock value
|
|
160
|
+
* Lock value format: instanceId:timestamp:random:pid
|
|
161
|
+
*
|
|
162
|
+
* @param lockValue - Lock value
|
|
163
|
+
* @returns Instance ID or null if cannot be extracted
|
|
164
|
+
*/
|
|
165
|
+
extractInstanceId(lockValue) {
|
|
166
|
+
if (!lockValue) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
// New format: instanceId:timestamp:random:pid
|
|
170
|
+
const parts = lockValue.split(':');
|
|
171
|
+
return parts.length >= 1 ? parts[0] : null;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get instance identifier
|
|
175
|
+
*/
|
|
176
|
+
getInstanceId() {
|
|
177
|
+
return (process.env.HOSTNAME ||
|
|
178
|
+
process.env.INSTANCE_ID ||
|
|
179
|
+
`instance-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Manually trigger cleanup of all stale locks
|
|
183
|
+
* Use with caution - this will clean both own and dead instance locks
|
|
184
|
+
*/
|
|
185
|
+
manualCleanup() {
|
|
186
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
187
|
+
this.logger.log('Manual cleanup triggered');
|
|
188
|
+
const ownLocksCount = yield this.cleanupOwnLocksCount();
|
|
189
|
+
const deadLocksCount = yield this.cleanupDeadInstanceLocksCount();
|
|
190
|
+
this.logger.log(`Manual cleanup completed: ${ownLocksCount} own locks, ${deadLocksCount} dead locks`);
|
|
191
|
+
return {
|
|
192
|
+
ownLocks: ownLocksCount,
|
|
193
|
+
deadLocks: deadLocksCount,
|
|
194
|
+
};
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
cleanupOwnLocksCount() {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
const allLocks = yield this.lockService.getActiveLocks('*', 'lock');
|
|
200
|
+
let deletedCount = 0;
|
|
201
|
+
for (const lock of allLocks) {
|
|
202
|
+
if (this.isOwnLock(lock.value)) {
|
|
203
|
+
yield this.lockService.forceRelease(lock.key);
|
|
204
|
+
deletedCount++;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return deletedCount;
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
cleanupDeadInstanceLocksCount() {
|
|
211
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
212
|
+
const allLocks = yield this.lockService.getActiveLocks('*', 'lock');
|
|
213
|
+
let deletedCount = 0;
|
|
214
|
+
for (const lock of allLocks) {
|
|
215
|
+
if (this.isOwnLock(lock.value)) {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
const instanceId = this.extractInstanceId(lock.value);
|
|
219
|
+
if (!instanceId) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
const isAlive = yield this.heartbeatService.isInstanceAlive(instanceId);
|
|
223
|
+
if (!isAlive) {
|
|
224
|
+
yield this.lockService.forceRelease(lock.key);
|
|
225
|
+
deletedCount++;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return deletedCount;
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Cleanup own locks on application shutdown
|
|
233
|
+
* Called when receiving SIGTERM/SIGINT (graceful shutdown)
|
|
234
|
+
*/
|
|
235
|
+
onApplicationShutdown(signal) {
|
|
236
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
237
|
+
this.logger.log(`Application shutting down (signal: ${signal}), cleaning own locks...`);
|
|
238
|
+
try {
|
|
239
|
+
const deletedCount = yield this.cleanupOwnLocksCount();
|
|
240
|
+
this.logger.log(`Graceful shutdown cleanup completed: cleaned ${deletedCount} lock(s) from this instance`);
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
this.logger.error('Failed to cleanup own locks on shutdown:', error);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
exports.ComprehensiveLockCleanupService = ComprehensiveLockCleanupService;
|
|
249
|
+
exports.ComprehensiveLockCleanupService = ComprehensiveLockCleanupService = ComprehensiveLockCleanupService_1 = __decorate([
|
|
250
|
+
(0, common_1.Injectable)(),
|
|
251
|
+
__metadata("design:paramtypes", [redis_lock_service_1.RedisLockService,
|
|
252
|
+
lock_heartbeat_service_1.LockHeartbeatService])
|
|
253
|
+
], ComprehensiveLockCleanupService);
|
|
@@ -1,9 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lock Strategy Examples
|
|
3
|
+
*
|
|
4
|
+
* This file demonstrates the different lock acquisition strategies available in Redis Lock module.
|
|
5
|
+
*/
|
|
1
6
|
import { RedisLockService } from '../index';
|
|
7
|
+
/**
|
|
8
|
+
* SKIP strategy - Skip execution if lock cannot be acquired
|
|
9
|
+
* This is the default behavior and is useful for scheduled tasks where you don't
|
|
10
|
+
* want to queue up requests if a previous execution is still running.
|
|
11
|
+
*/
|
|
2
12
|
export declare class SkipStrategyExample {
|
|
3
13
|
private readonly lockService;
|
|
4
14
|
private readonly logger;
|
|
5
15
|
constructor(lockService: RedisLockService);
|
|
16
|
+
/**
|
|
17
|
+
* Example 1: Using decorator with SKIP strategy (default)
|
|
18
|
+
*/
|
|
6
19
|
scheduledTask(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Example 2: Using service directly with SKIP strategy
|
|
22
|
+
*/
|
|
7
23
|
processWithSkip(): Promise<{
|
|
8
24
|
skipped: boolean;
|
|
9
25
|
success?: undefined;
|
|
@@ -11,6 +27,9 @@ export declare class SkipStrategyExample {
|
|
|
11
27
|
success: boolean;
|
|
12
28
|
skipped?: undefined;
|
|
13
29
|
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Example 3: SKIP with retries
|
|
32
|
+
*/
|
|
14
33
|
processWithRetries(): Promise<{
|
|
15
34
|
skipped: boolean;
|
|
16
35
|
success?: undefined;
|
|
@@ -20,14 +39,28 @@ export declare class SkipStrategyExample {
|
|
|
20
39
|
}>;
|
|
21
40
|
private simulateLongRunning;
|
|
22
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* THROW strategy - Throw an error if lock cannot be acquired
|
|
44
|
+
* Use this for critical operations that must have exclusive access.
|
|
45
|
+
* If the lock cannot be acquired, an exception will be thrown.
|
|
46
|
+
*/
|
|
23
47
|
export declare class ThrowStrategyExample {
|
|
24
48
|
private readonly lockService;
|
|
25
49
|
private readonly logger;
|
|
26
50
|
constructor(lockService: RedisLockService);
|
|
51
|
+
/**
|
|
52
|
+
* Example 1: Using decorator with THROW strategy
|
|
53
|
+
*/
|
|
27
54
|
criticalOperation(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Example 2: Using service with error handling
|
|
57
|
+
*/
|
|
28
58
|
processWithThrow(): Promise<{
|
|
29
59
|
success: boolean;
|
|
30
60
|
}>;
|
|
61
|
+
/**
|
|
62
|
+
* Example 3: Critical payment processing
|
|
63
|
+
*/
|
|
31
64
|
processPayment(orderId: string, amount: number): Promise<{
|
|
32
65
|
success: boolean;
|
|
33
66
|
}>;
|
|
@@ -35,11 +68,22 @@ export declare class ThrowStrategyExample {
|
|
|
35
68
|
private chargePayment;
|
|
36
69
|
private updateOrderStatus;
|
|
37
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* WAIT strategy - Block/wait until lock can be acquired
|
|
73
|
+
* Use this when you want to queue execution and ensure the operation eventually runs.
|
|
74
|
+
* The function will wait indefinitely (or until waitTimeout) for the lock to become available.
|
|
75
|
+
*/
|
|
38
76
|
export declare class WaitStrategyExample {
|
|
39
77
|
private readonly lockService;
|
|
40
78
|
private readonly logger;
|
|
41
79
|
constructor(lockService: RedisLockService);
|
|
80
|
+
/**
|
|
81
|
+
* Example 1: Using decorator with WAIT strategy
|
|
82
|
+
*/
|
|
42
83
|
sequentialTask(): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Example 2: WAIT with timeout
|
|
86
|
+
*/
|
|
43
87
|
processWithWaitTimeout(): Promise<{
|
|
44
88
|
timeout: boolean;
|
|
45
89
|
success?: undefined;
|
|
@@ -47,12 +91,24 @@ export declare class WaitStrategyExample {
|
|
|
47
91
|
success: boolean;
|
|
48
92
|
timeout?: undefined;
|
|
49
93
|
}>;
|
|
94
|
+
/**
|
|
95
|
+
* Example 3: Sequential data processing
|
|
96
|
+
* Perfect for operations that must be processed in order
|
|
97
|
+
*/
|
|
50
98
|
processDataSequentially(userId: string, data: any): Promise<{
|
|
51
99
|
success: boolean;
|
|
52
100
|
}>;
|
|
101
|
+
/**
|
|
102
|
+
* Example 4: Queue-like behavior
|
|
103
|
+
* Multiple requests will queue and execute one by one
|
|
104
|
+
*/
|
|
53
105
|
processQueue(queueName: string, item: any): Promise<{
|
|
54
106
|
success: boolean;
|
|
55
107
|
}>;
|
|
108
|
+
/**
|
|
109
|
+
* Example 5: Database migration with WAIT
|
|
110
|
+
* Ensures migrations run sequentially across all instances
|
|
111
|
+
*/
|
|
56
112
|
runMigration(migrationName: string): Promise<{
|
|
57
113
|
success: boolean;
|
|
58
114
|
}>;
|
|
@@ -63,11 +119,44 @@ export declare class WaitStrategyExample {
|
|
|
63
119
|
private processQueueItem;
|
|
64
120
|
private executeMigration;
|
|
65
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* USE SKIP WHEN:
|
|
124
|
+
* - Running scheduled tasks where you don't want overlapping executions
|
|
125
|
+
* - Cron jobs that should skip if previous run is still in progress
|
|
126
|
+
* - Non-critical background tasks
|
|
127
|
+
* - Operations where it's okay to skip if busy
|
|
128
|
+
*
|
|
129
|
+
* USE THROW WHEN:
|
|
130
|
+
* - Critical operations that require exclusive access
|
|
131
|
+
* - Financial transactions
|
|
132
|
+
* - Operations where failure to acquire lock is an error
|
|
133
|
+
* - When you want to alert/fail fast if resource is busy
|
|
134
|
+
*
|
|
135
|
+
* USE WAIT WHEN:
|
|
136
|
+
* - Operations that must execute eventually
|
|
137
|
+
* - Sequential processing requirements
|
|
138
|
+
* - Queue-like behavior needed
|
|
139
|
+
* - Database migrations
|
|
140
|
+
* - Operations where order matters
|
|
141
|
+
* - When you want to ensure the operation runs (with optional timeout)
|
|
142
|
+
*/
|
|
143
|
+
/**
|
|
144
|
+
* Example: Combining strategies in a single service
|
|
145
|
+
*/
|
|
66
146
|
export declare class CombinedStrategiesExample {
|
|
67
147
|
private readonly lockService;
|
|
68
148
|
private readonly logger;
|
|
69
149
|
constructor(lockService: RedisLockService);
|
|
150
|
+
/**
|
|
151
|
+
* Background cleanup - SKIP if already running
|
|
152
|
+
*/
|
|
70
153
|
cleanupOldData(): Promise<void>;
|
|
154
|
+
/**
|
|
155
|
+
* Payment processing - THROW if cannot get exclusive access
|
|
156
|
+
*/
|
|
71
157
|
processPayment(orderId: string): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Report generation - WAIT to ensure it runs eventually
|
|
160
|
+
*/
|
|
72
161
|
generateReport(reportId: string): Promise<void>;
|
|
73
162
|
}
|