@russ-b/nestjs-common-tools
Version:
NestJS utility tools
91 lines • 4.07 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var BaseWorker_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseWorker = void 0;
const common_1 = require("@nestjs/common");
const services_1 = require("../services");
let BaseWorker = BaseWorker_1 = class BaseWorker {
constructor(outboxService) {
this.outboxService = outboxService;
this.logger = new common_1.Logger(BaseWorker_1.name);
}
async work() {
if (this.locked) {
this.logger.warn('The resource is locked because it is still in process');
return;
}
this.locked = true;
try {
const policy = this.outboxService.getOperationalPolicy();
if (policy.resetStaleProcessingEvents) {
const resetCount = await this.outboxService.resetStaleProcessingEvents(policy.staleProcessingMinutes);
if (resetCount > 0) {
this.logger.warn(`Reset ${resetCount} stale processing events`);
}
}
// Claim events (fetches + marks as PROCESSING in one transaction)
const events = await this.getEvents();
if (events.length > 0) {
this.logger.debug(`Got ${events.length} pending events`);
}
await this.processEvents(events, policy);
}
catch (e) {
this.logger.error('Worker cycle failed', e);
}
finally {
this.locked = false;
}
}
async processEvents(events, policy) {
if (!policy.maxConcurrentEvents) {
await Promise.allSettled(events.map((event) => this.processEvent(event, policy.maxRetries)));
return;
}
for (let i = 0; i < events.length; i += policy.maxConcurrentEvents) {
const batch = events.slice(i, i + policy.maxConcurrentEvents);
await Promise.allSettled(batch.map((event) => this.processEvent(event, policy.maxRetries)));
}
}
async processEvent(event, maxRetries) {
try {
await this.handle(event);
const markedAsProcessed = await this.outboxService.markAsProcessed(event.id, event.processingStartedAt);
if (markedAsProcessed) {
this.logger.log(`Successfully processed event ${event.id}`);
}
else {
this.logger.warn(`Event ${event.id} was processed but not marked as processed because the claim expired`);
}
}
catch (e) {
this.logger.error(`Failed to process event ${event.id}`, e);
const errorMessage = this.getErrorMessage(e);
const retryUpdated = await this.outboxService.incrementRetry(event.id, errorMessage, maxRetries, event.processingStartedAt);
if (!retryUpdated) {
this.logger.warn(`Event ${event.id} retry was not updated because the claim expired`);
}
}
}
getErrorMessage(e) {
if (e instanceof Error) {
return e.message;
}
return String(e);
}
};
exports.BaseWorker = BaseWorker;
exports.BaseWorker = BaseWorker = BaseWorker_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [services_1.OutboxService])
], BaseWorker);
//# sourceMappingURL=base-worker.js.map