Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: archive SUCCESS/FAILED notifications #354

Closed
wants to merge 15 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
perf: add transaction management
kshitij-k-osmosys committed Nov 6, 2024
commit 0b75e7bbf6a86c3768cbd55db6a6bed0a45aaeef
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
import { ArchivedNotification } from './entities/archived-notification.entity';
import { Cron, CronExpression } from '@nestjs/schedule';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { DataSource, QueryRunner } from 'typeorm';
import { Notification } from 'src/modules/notifications/entities/notification.entity';
import { NotificationsService } from '../notifications/notifications.service';
import { ConfigService } from '@nestjs/config';
@@ -12,11 +11,10 @@ export class ArchivedNotificationsService {
protected readonly logger = new Logger(ArchivedNotificationsService.name);

constructor(
@InjectRepository(ArchivedNotification)
private readonly archivedNotificationRepository: Repository<ArchivedNotification>,
@Inject(forwardRef(() => NotificationsService))
protected readonly notificationsService: NotificationsService,
private readonly configService: ConfigService,
private dataSource: DataSource,
) {}

private convertToArchivedNotifications(notifications: Notification[]): ArchivedNotification[] {
@@ -37,7 +35,7 @@ export class ArchivedNotificationsService {
archivedNotification.status = notification.status;

this.logger.debug(
`Created ArchivedNotification array using Notification ID: ${notification.id}, deliveryStatus: ${notification.deliveryStatus}`,
`Preparing ArchivedNotification entry: ${JSON.stringify(archivedNotification, null, 2)}}`,
);
return archivedNotification;
});
@@ -47,33 +45,50 @@ export class ArchivedNotificationsService {
const archiveLimit = this.configService.get<number>('ARCHIVE_LIMIT', 1000);

try {
// Step 1: Retrieve the notifications to archive
this.logger.log(`Retrieve the top ${archiveLimit} notifications to archive`);
const notificationsToArchive =
await this.notificationsService.findNotificationsToArchive(archiveLimit);
this.logger.log('Creating queryRunner and starting transaction');
const queryRunner: QueryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();

if (notificationsToArchive.length === 0) {
this.logger.log('No notifications to archive at this time.');
return;
}
try {
// Step 1: Retrieve the notifications to archive
this.logger.log(`Retrieve the top ${archiveLimit} notifications to archive`);
const notificationsToArchive =
await this.notificationsService.findNotificationsToArchive(archiveLimit);

if (notificationsToArchive.length === 0) {
this.logger.log('No notifications to archive at this time.');
return;
}
xixas marked this conversation as resolved.
Show resolved Hide resolved

// Step 2: Convert notifications to archived notifications
const archivedNotificationsArray =
this.convertToArchivedNotifications(notificationsToArchive);
// Step 2: Convert notifications to archived notifications
const archivedNotificationsArray =
this.convertToArchivedNotifications(notificationsToArchive);

// Step 3: Insert notifications into the archive table
this.logger.log(`Inserting archived notifications into the archive table`);
await this.archivedNotificationRepository.save(archivedNotificationsArray, {
transaction: true,
});
// Step 3: Insert notifications into the archive table
this.logger.log(`Inserting archived notifications into the archive table`);
await queryRunner.manager.save(ArchivedNotification, archivedNotificationsArray);

// Step 4: Delete notifications from the main table by IDs
this.logger.log(`Deleting notifications from the main table by IDs`);
await this.notificationsService.deleteArchivedNotifications(notificationsToArchive);
// Step 4: Delete notifications from the main table by IDs
this.logger.log(`Deleting notifications from the main table by IDs`);
const idsToDelete = notificationsToArchive.map((notification) => notification.id);
this.logger.log(`Notification IDs to delete: ${idsToDelete}`);

this.logger.log(`Archive notifications task completed`);
await queryRunner.manager.delete(Notification, idsToDelete);

// Commit transaction
await queryRunner.commitTransaction();
this.logger.log(`Archive notifications task completed`);
} catch (error) {
this.logger.error('Error while archiving notifications. Rolling back transaction');
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
}
} catch (error) {
this.logger.error('Failed to archive notifications:', error);
this.logger.error(`Failed to archive notifications: ${error.message}`);
throw error;
}
}

11 changes: 0 additions & 11 deletions apps/api/src/modules/notifications/notifications.service.ts
Original file line number Diff line number Diff line change
@@ -314,15 +314,4 @@ export class NotificationsService extends CoreService<Notification> {
throw error;
}
}

async deleteArchivedNotifications(notificationsToArchive: Notification[]): Promise<void> {
try {
const idsToDelete = notificationsToArchive.map((notification) => notification.id);
this.logger.debug(`Notification IDs to delete: ${idsToDelete}`);
await this.notificationRepository.delete(idsToDelete);
this.logger.log(`Archived and deleted ${notificationsToArchive.length} notifications.`);
} catch (error) {
this.logger.error('Error deleting notifications from the main table', error);
}
}
}