feat: new config service with lowdb and mutex

This commit is contained in:
Ravinou 2025-04-05 11:35:26 +02:00
commit 201f5b41a1
No known key found for this signature in database
GPG key ID: EEEE670C40F6A4D7
2 changed files with 109 additions and 0 deletions

View file

@ -0,0 +1,73 @@
// dbHelper.ts
import { Low } from 'lowdb';
import { JSONFile } from 'lowdb/node';
import path from 'path';
import { Mutex } from 'async-mutex';
import { BorgWarehouseUser, Repository } from '~/types/domain/config.types';
import repoHistory from './history.service';
const jsonDirectory = path.join(process.cwd(), '/config');
const usersDbPath = path.join(jsonDirectory, 'users.json');
const repoDbPath = path.join(jsonDirectory, 'repo.json');
// Lowdb config
const usersAdapter = new JSONFile<BorgWarehouseUser[]>(usersDbPath);
const usersDb = new Low(usersAdapter, []);
const repoAdapter = new JSONFile<Repository[]>(repoDbPath);
const repoDb = new Low(repoAdapter, []);
// Mutexes for concurrent access
const usersMutex = new Mutex();
const repoMutex = new Mutex();
// User management
export const getUsersList = async (): Promise<BorgWarehouseUser[]> => {
try {
await usersMutex.runExclusive(async () => {
await usersDb.read();
});
return usersDb.data;
} catch (error) {
console.log('Error reading users.json:', error);
return [];
}
};
export const updateUsersList = async (usersList: BorgWarehouseUser[]): Promise<void> => {
try {
await usersMutex.runExclusive(async () => {
usersDb.data = usersList;
await usersDb.write();
});
} catch (error) {
console.log('Error writing users.json:', error);
}
};
// Repository management
export const getRepoList = async (): Promise<Repository[]> => {
try {
await repoMutex.runExclusive(async () => {
await repoDb.read();
});
return repoDb.data;
} catch (error) {
console.log('Error reading repo.json:', error);
return [];
}
};
export const updateRepoList = async (repoList: Repository[], history = false): Promise<void> => {
try {
await repoMutex.runExclusive(async () => {
if (history) {
await repoHistory(repoList);
}
repoDb.data = repoList;
await repoDb.write();
});
} catch (error) {
console.log('Error writing repo.json:', error);
}
};

View file

@ -0,0 +1,36 @@
import { promises as fs } from 'fs';
import path from 'path';
import { Repository } from '~/types/domain/config.types';
export default async function repoHistory(repoList: Repository[]) {
try {
const repoHistoryDir = path.join(process.cwd(), '/config/versions');
const maxBackupCount = parseInt(process.env.MAX_REPO_BACKUP_COUNT ?? '8', 10);
const timestamp = new Date().toISOString();
const backupDate = timestamp.split('T')[0];
//Create the directory if it does not exist
await fs.mkdir(repoHistoryDir, { recursive: true });
const existingBackups = await fs.readdir(repoHistoryDir);
if (existingBackups.length >= maxBackupCount) {
existingBackups.sort();
const backupsToDelete = existingBackups.slice(0, existingBackups.length - maxBackupCount + 1);
for (const backupToDelete of backupsToDelete) {
const backupFilePathToDelete = path.join(repoHistoryDir, backupToDelete);
await fs.unlink(backupFilePathToDelete);
}
}
const backupFileName = `${backupDate}.log`;
const backupFilePath = path.join(repoHistoryDir, backupFileName);
const jsonData = JSON.stringify(repoList, null, 2);
const logData = `\n>>>> History of file repo.json at "${timestamp}" <<<<\n${jsonData}\n`;
await fs.appendFile(backupFilePath, logData);
} catch (error) {
console.log('An error occurred while saving the repo history :', error);
}
}