chore: types

This commit is contained in:
Eli Bosley
2025-07-11 20:39:40 -04:00
parent e7066c0e09
commit a406fdc5fe
6 changed files with 67 additions and 33 deletions

View File

@@ -94,7 +94,7 @@
"command-exists": "1.2.9",
"convert": "5.12.0",
"cookie": "1.0.2",
"cron": "4.3.1",
"cron": "4.3.0",
"cross-fetch": "4.1.0",
"diff": "8.0.2",
"dockerode": "4.0.7",
@@ -192,6 +192,7 @@
"@types/wtfnode": "0.7.3",
"@vitest/coverage-v8": "3.2.4",
"@vitest/ui": "3.2.4",
"commit-and-tag-version": "9.6.0",
"cz-conventional-changelog": "3.3.0",
"eslint": "9.30.1",
"eslint-plugin-import": "2.32.0",
@@ -203,7 +204,6 @@
"nodemon": "3.1.10",
"prettier": "3.6.2",
"rollup-plugin-node-externals": "8.0.1",
"commit-and-tag-version": "9.6.0",
"tsx": "4.20.3",
"type-fest": "4.41.0",
"typescript": "5.8.3",
@@ -225,7 +225,8 @@
"nest-authz": {
"@nestjs/common": "$@nestjs/common",
"@nestjs/core": "$@nestjs/core"
}
},
"cron": "4.3.1"
},
"private": true,
"packageManager": "pnpm@10.13.1"

View File

@@ -13,6 +13,7 @@ import {
CreateBackupJobConfigInput,
UpdateBackupJobConfigInput,
} from '@app/unraid-api/graph/resolvers/backup/backup.model.js';
import { getBackupJobGroupId } from '@app/unraid-api/graph/resolvers/backup/backup.utils.js';
import {
DestinationConfigInput,
DestinationType,
@@ -520,7 +521,7 @@ export class BackupConfigService implements OnModuleInit {
'UTC'
);
this.schedulerRegistry.addCronJob(`${JOB_GROUP_PREFIX}${config.id}`, job);
this.schedulerRegistry.addCronJob(getBackupJobGroupId(config.id), job);
job.start();
this.logger.log(`Scheduled backup job: ${config.name} with schedule: ${config.schedule}`);
} catch (error) {
@@ -530,7 +531,7 @@ export class BackupConfigService implements OnModuleInit {
private unscheduleJob(id: string): void {
try {
const jobName = `${JOB_GROUP_PREFIX}${id}`;
const jobName = getBackupJobGroupId(id);
if (this.schedulerRegistry.doesExist('cron', jobName)) {
this.schedulerRegistry.deleteCronJob(jobName);
this.logger.log(`Unscheduled backup job: ${id}`);

View File

@@ -81,8 +81,7 @@ export class BackupOrchestrationService {
sourceProcessor,
destinationProcessor,
jobConfig,
internalJobId,
configId // Pass configId for handleJobCompletion
internalJobId
);
} else {
await this.executeRegularBackup(
@@ -201,7 +200,7 @@ export class BackupOrchestrationService {
this.emitJobStatus(internalJobId, { status: BackupJobStatus.FAILED, error: errorMsg });
// Call handleJobCompletion before throwing
await this.backupConfigService.handleJobCompletion(
configId,
jobConfig.id,
BackupJobStatus.FAILED,
internalJobId
);
@@ -218,7 +217,7 @@ export class BackupOrchestrationService {
});
// Call handleJobCompletion on success
await this.backupConfigService.handleJobCompletion(
configId,
jobConfig.id,
BackupJobStatus.COMPLETED,
internalJobId
);
@@ -251,7 +250,7 @@ export class BackupOrchestrationService {
});
// Call handleJobCompletion on failure
await this.backupConfigService.handleJobCompletion(
configId,
jobConfig.id,
BackupJobStatus.FAILED,
internalJobId
);

View File

@@ -11,6 +11,11 @@ import got, { HTTPError } from 'got';
import pRetry from 'p-retry';
import { sanitizeParams } from '@app/core/log.js';
import {
getConfigIdFromGroupId,
isBackupJobGroup,
} from '@app/unraid-api/graph/resolvers/backup/backup.utils.js';
import { BackupJobStatus } from '@app/unraid-api/graph/resolvers/backup/orchestration/backup-job-status.model.js';
import { RCloneStatusService } from '@app/unraid-api/graph/resolvers/rclone/rclone-status.service.js';
import {
CreateRCloneRemoteDto,
@@ -72,7 +77,7 @@ interface JobOperationResult {
@Injectable()
export class RCloneApiService implements OnModuleInit, OnModuleDestroy {
private isInitialized: boolean = false;
private initialized: boolean = false;
private readonly logger = new Logger(RCloneApiService.name);
private rcloneSocketPath: string = '';
private rcloneBaseUrl: string = '';
@@ -86,12 +91,51 @@ export class RCloneApiService implements OnModuleInit, OnModuleDestroy {
constructor(private readonly statusService: RCloneStatusService) {}
get isInitialized(): boolean {
return this.initialized;
}
async onModuleInit(): Promise<void> {
try {
await this.initializeRCloneService();
} catch (error: unknown) {
this.logger.error(`Error initializing RCloneApiService: ${error}`);
this.isInitialized = false;
// Check if rclone binary is available first
const isBinaryAvailable = await this.checkRcloneBinaryExists();
if (!isBinaryAvailable) {
this.logger.warn('RClone binary not found on system, skipping initialization');
this.initialized = false;
return;
}
const { getters } = await import('@app/store/index.js');
// Check if Rclone Socket is running, if not, start it.
this.rcloneSocketPath = getters.paths()['rclone-socket'];
const logFilePath = join(getters.paths()['log-base'], 'rclone-unraid-api.log');
this.logger.log(`RClone socket path: ${this.rcloneSocketPath}`);
this.logger.log(`RClone log file path: ${logFilePath}`);
// Format the base URL for Unix socket
this.rcloneBaseUrl = `http://unix:${this.rcloneSocketPath}:`;
// Check if the RClone socket exists, if not, create it.
const socketExists = await this.checkRcloneSocketExists(this.rcloneSocketPath);
if (socketExists) {
const isRunning = await this.checkRcloneSocketRunning();
if (isRunning) {
this.initialized = true;
return;
} else {
this.logger.warn(
'RClone socket is not running but socket exists, removing socket before starting...'
);
await rm(this.rcloneSocketPath, { force: true });
}
this.logger.warn('RClone socket is not running, starting it...');
this.initialized = await this.startRcloneSocket(this.rcloneSocketPath, logFilePath);
return;
} else {
this.logger.warn('RClone socket does not exist, creating it...');
this.initialized = await this.startRcloneSocket(this.rcloneSocketPath, logFilePath);
return;
}
}
@@ -114,7 +158,7 @@ export class RCloneApiService implements OnModuleInit, OnModuleDestroy {
await this.stopRcloneSocket();
this.logger.warn('Proceeding to start new RClone socket...');
this.isInitialized = await this.startRcloneSocket(this.rcloneSocketPath, logFilePath);
this.initialized = await this.startRcloneSocket(this.rcloneSocketPath, logFilePath);
}
private async startRcloneSocket(socketPath: string, logFilePath: string): Promise<boolean> {
@@ -200,7 +244,7 @@ export class RCloneApiService implements OnModuleInit, OnModuleDestroy {
private cleanupFailedProcess(): void {
this.rcloneProcess = null;
this.isInitialized = false;
this.initialized = false;
}
private async waitForSocketReady(): Promise<void> {
@@ -349,9 +393,7 @@ export class RCloneApiService implements OnModuleInit, OnModuleDestroy {
this.logger.log(`Starting backup: ${input.srcPath}${input.dstPath}`);
const group = input.configId
? getBackupJobGroupId(input.configId)
: BACKUP_JOB_GROUP_PREFIX + 'manual';
const group = input.configId ? getConfigIdFromGroupId(input.configId) : 'manual';
const params = {
srcFs: input.srcPath,

View File

@@ -48,7 +48,7 @@ export class RCloneService {
*/
async onModuleInit(): Promise<void> {
try {
if (!this.rcloneApiService.initialized) {
if (!this.rcloneApiService.isInitialized) {
this.logger.warn(
'RClone API service is not initialized, skipping provider info loading'
);

13
pnpm-lock.yaml generated
View File

@@ -157,8 +157,8 @@ importers:
specifier: 1.0.2
version: 1.0.2
cron:
specifier: 4.3.1
version: 4.3.1
specifier: 4.3.0
version: 4.3.0
cross-fetch:
specifier: 4.1.0
version: 4.1.0
@@ -6509,10 +6509,6 @@ packages:
resolution: {integrity: sha512-ciiYNLfSlF9MrDqnbMdRWFiA6oizSF7kA1osPP9lRzNu0Uu+AWog1UKy7SkckiDY2irrNjeO6qLyKnXC8oxmrw==}
engines: {node: '>=18.x'}
cron@4.3.1:
resolution: {integrity: sha512-7x7DoEOxV11t3OPWWMjj1xrL1PGkTV5RV+/54IJTZD7gStiaMploY43EkeBSkDZTLRbUwk+OISbQ0TR133oXyA==}
engines: {node: '>=18.x'}
croner@4.1.97:
resolution: {integrity: sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==}
@@ -19428,11 +19424,6 @@ snapshots:
'@types/luxon': 3.6.2
luxon: 3.6.1
cron@4.3.1:
dependencies:
'@types/luxon': 3.6.2
luxon: 3.6.1
croner@4.1.97: {}
croner@9.1.0: {}