mirror of
https://github.com/BluemediaDev/muse.git
synced 2025-05-11 20:31:35 +02:00
Setup and migrate to Prisma (#456)
This commit is contained in:
parent
129d121364
commit
51d378e4cb
30 changed files with 605 additions and 273 deletions
|
@ -1,4 +1,5 @@
|
|||
import dotenv from 'dotenv';
|
||||
import 'reflect-metadata';
|
||||
import {injectable} from 'inversify';
|
||||
import path from 'path';
|
||||
import xbytes from 'xbytes';
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import {promises as fs, createWriteStream} from 'fs';
|
||||
import path from 'path';
|
||||
import {inject, injectable} from 'inversify';
|
||||
import sequelize from 'sequelize';
|
||||
import {FileCache} from '../models/index.js';
|
||||
import {TYPES} from '../types.js';
|
||||
import Config from './config.js';
|
||||
import PQueue from 'p-queue';
|
||||
import debug from '../utils/debug.js';
|
||||
import {prisma} from '../utils/db.js';
|
||||
import {FileCache} from '@prisma/client';
|
||||
|
||||
@injectable()
|
||||
export default class FileCacheProvider {
|
||||
|
@ -23,7 +23,11 @@ export default class FileCacheProvider {
|
|||
* @param hash lookup key
|
||||
*/
|
||||
async getPathFor(hash: string): Promise<string> {
|
||||
const model = await FileCache.findByPk(hash);
|
||||
const model = await prisma.fileCache.findUnique({
|
||||
where: {
|
||||
hash,
|
||||
},
|
||||
});
|
||||
|
||||
if (!model) {
|
||||
throw new Error('File is not cached');
|
||||
|
@ -34,12 +38,23 @@ export default class FileCacheProvider {
|
|||
try {
|
||||
await fs.access(resolvedPath);
|
||||
} catch (_: unknown) {
|
||||
await FileCache.destroy({where: {hash}});
|
||||
await prisma.fileCache.delete({
|
||||
where: {
|
||||
hash,
|
||||
},
|
||||
});
|
||||
|
||||
throw new Error('File is not cached');
|
||||
}
|
||||
|
||||
await model.update({accessedAt: new Date()});
|
||||
await prisma.fileCache.update({
|
||||
where: {
|
||||
hash,
|
||||
},
|
||||
data: {
|
||||
accessedAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
return resolvedPath;
|
||||
}
|
||||
|
@ -64,7 +79,13 @@ export default class FileCacheProvider {
|
|||
try {
|
||||
await fs.rename(tmpPath, finalPath);
|
||||
|
||||
await FileCache.create({hash, bytes: stats.size, accessedAt: new Date()});
|
||||
await prisma.fileCache.create({
|
||||
data: {
|
||||
hash,
|
||||
accessedAt: new Date(),
|
||||
bytes: stats.size,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
debug('Errored when moving a finished cache file:', error);
|
||||
}
|
||||
|
@ -100,14 +121,19 @@ export default class FileCacheProvider {
|
|||
// Continue to evict until we're under the limit
|
||||
/* eslint-disable no-await-in-loop */
|
||||
while (totalSizeBytes > this.config.CACHE_LIMIT_IN_BYTES) {
|
||||
const oldest = await FileCache.findOne({
|
||||
order: [
|
||||
['accessedAt', 'ASC'],
|
||||
],
|
||||
const oldest = await prisma.fileCache.findFirst({
|
||||
orderBy: {
|
||||
accessedAt: 'asc',
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
if (oldest) {
|
||||
await oldest.destroy();
|
||||
await prisma.fileCache.delete({
|
||||
where: {
|
||||
hash: oldest.hash,
|
||||
},
|
||||
});
|
||||
await fs.unlink(path.join(this.config.CACHE_DIR, oldest.hash));
|
||||
debug(`${oldest.hash} has been evicted`);
|
||||
numOfEvictedFiles++;
|
||||
|
@ -128,7 +154,11 @@ export default class FileCacheProvider {
|
|||
// Check filesystem direction (do files exist on the disk but not in the database?)
|
||||
for await (const dirent of await fs.opendir(this.config.CACHE_DIR)) {
|
||||
if (dirent.isFile()) {
|
||||
const model = await FileCache.findByPk(dirent.name);
|
||||
const model = await prisma.fileCache.findUnique({
|
||||
where: {
|
||||
hash: dirent.name,
|
||||
},
|
||||
});
|
||||
|
||||
if (!model) {
|
||||
debug(`${dirent.name} was present on disk but was not in the database. Removing from disk.`);
|
||||
|
@ -145,7 +175,11 @@ export default class FileCacheProvider {
|
|||
await fs.access(filePath);
|
||||
} catch {
|
||||
debug(`${model.hash} was present in database but was not on disk. Removing from database.`);
|
||||
await model.destroy();
|
||||
await prisma.fileCache.delete({
|
||||
where: {
|
||||
hash: model.hash,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,11 +190,12 @@ export default class FileCacheProvider {
|
|||
* @returns the total size of the cache in bytes
|
||||
*/
|
||||
private async getDiskUsageInBytes() {
|
||||
const [{dataValues: {totalSizeBytes}}] = await FileCache.findAll({
|
||||
attributes: [
|
||||
[sequelize.fn('sum', sequelize.col('bytes')), 'totalSizeBytes'],
|
||||
],
|
||||
}) as unknown as [{dataValues: {totalSizeBytes: number}}];
|
||||
const data = await prisma.fileCache.aggregate({
|
||||
_sum: {
|
||||
bytes: true,
|
||||
},
|
||||
});
|
||||
const totalSizeBytes = data._sum.bytes ?? 0;
|
||||
|
||||
return totalSizeBytes;
|
||||
}
|
||||
|
@ -176,24 +211,26 @@ export default class FileCacheProvider {
|
|||
let models: FileCache[] = [];
|
||||
|
||||
const fetchNextBatch = async () => {
|
||||
let where = {};
|
||||
let where;
|
||||
|
||||
if (previousCreatedAt) {
|
||||
where = {
|
||||
createdAt: {
|
||||
[sequelize.Op.gt]: previousCreatedAt,
|
||||
gt: previousCreatedAt,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
models = await FileCache.findAll({
|
||||
models = await prisma.fileCache.findMany({
|
||||
where,
|
||||
limit,
|
||||
order: ['createdAt'],
|
||||
orderBy: {
|
||||
createdAt: 'asc',
|
||||
},
|
||||
take: limit,
|
||||
});
|
||||
|
||||
if (models.length > 0) {
|
||||
previousCreatedAt = models[models.length - 1].createdAt as Date;
|
||||
previousCreatedAt = models[models.length - 1].createdAt;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {injectable} from 'inversify';
|
||||
import {KeyValueCache} from '../models/index.js';
|
||||
import {prisma} from '../utils/db.js';
|
||||
import debug from '../utils/debug.js';
|
||||
|
||||
type Seconds = number;
|
||||
|
@ -29,7 +29,11 @@ export default class KeyValueCacheProvider {
|
|||
throw new Error(`Cache key ${key} is too short.`);
|
||||
}
|
||||
|
||||
const cachedResult = await KeyValueCache.findByPk(key);
|
||||
const cachedResult = await prisma.keyValueCache.findUnique({
|
||||
where: {
|
||||
key,
|
||||
},
|
||||
});
|
||||
|
||||
if (cachedResult) {
|
||||
if (new Date() < cachedResult.expiresAt) {
|
||||
|
@ -37,7 +41,11 @@ export default class KeyValueCacheProvider {
|
|||
return JSON.parse(cachedResult.value) as F;
|
||||
}
|
||||
|
||||
await cachedResult.destroy();
|
||||
await prisma.keyValueCache.delete({
|
||||
where: {
|
||||
key,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
debug(`Cache miss: ${key}`);
|
||||
|
@ -45,10 +53,21 @@ export default class KeyValueCacheProvider {
|
|||
const result = await func(...options as any[]);
|
||||
|
||||
// Save result
|
||||
await KeyValueCache.upsert({
|
||||
key,
|
||||
value: JSON.stringify(result),
|
||||
expiresAt: futureTimeToDate(expiresIn),
|
||||
const value = JSON.stringify(result);
|
||||
const expiresAt = futureTimeToDate(expiresIn);
|
||||
await prisma.keyValueCache.upsert({
|
||||
where: {
|
||||
key,
|
||||
},
|
||||
update: {
|
||||
value,
|
||||
expiresAt,
|
||||
},
|
||||
create: {
|
||||
key,
|
||||
value,
|
||||
expiresAt,
|
||||
},
|
||||
});
|
||||
|
||||
return result;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue