fix(file-cache): add queue to handle eviction of old files

This commit also removes the `await` from every stream creation. The eviction will be handled totally assyncronously. The only drawback is the possibility of  exceeding the cache limit for a moment, until the next execution of `evictOldest`.
This will only be a problem if the cache is set too close to the remaining disk space, which I wouldn't recomend.

I also removed the recursion.
This commit is contained in:
Hellyson Rodrigo Parteka 2021-12-03 01:01:35 -03:00
parent 3b2aa47e95
commit af82be13f9
No known key found for this signature in database
GPG key ID: 3055745CA21934C7

View file

@ -5,9 +5,11 @@ import sequelize from 'sequelize';
import {FileCache} from '../models/index.js'; import {FileCache} from '../models/index.js';
import {TYPES} from '../types.js'; import {TYPES} from '../types.js';
import Config from './config.js'; import Config from './config.js';
import PQueue from 'p-queue';
@injectable() @injectable()
export default class FileCacheProvider { export default class FileCacheProvider {
private static readonly evictionQueue = new PQueue({concurrency: 1});
private readonly config: Config; private readonly config: Config;
constructor(@inject(TYPES.Config) config: Config) { constructor(@inject(TYPES.Config) config: Config) {
@ -67,7 +69,7 @@ export default class FileCacheProvider {
} }
} }
await this.evictOldestIfNecessary(); this.evictOldestIfNecessary();
}); });
return stream; return stream;
@ -80,10 +82,16 @@ export default class FileCacheProvider {
*/ */
async cleanup() { async cleanup() {
await this.removeOrphans(); await this.removeOrphans();
await this.evictOldestIfNecessary(); this.evictOldestIfNecessary();
} }
private async evictOldestIfNecessary() { private evictOldestIfNecessary() {
if (FileCacheProvider.evictionQueue.size === 0 && FileCacheProvider.evictionQueue.pending === 0) {
void FileCacheProvider.evictionQueue.add(this.evictOldest.bind(this));
}
}
private async evictOldest() {
const [{dataValues: {totalSizeBytes}}] = await FileCache.findAll({ const [{dataValues: {totalSizeBytes}}] = await FileCache.findAll({
attributes: [ attributes: [
[sequelize.fn('sum', sequelize.col('bytes')), 'totalSizeBytes'], [sequelize.fn('sum', sequelize.col('bytes')), 'totalSizeBytes'],
@ -103,7 +111,7 @@ export default class FileCacheProvider {
} }
// Continue to evict until we're under the limit // Continue to evict until we're under the limit
await this.evictOldestIfNecessary(); void FileCacheProvider.evictionQueue.add(this.evictOldest.bind(this));
} }
} }