aboutsummaryrefslogtreecommitdiff
path: root/src/services
diff options
context:
space:
mode:
authorMax Isom <[email protected]>2023-05-13 18:34:29 -0700
committerGitHub <[email protected]>2023-05-13 20:34:29 -0500
commitdd140b50fb79fd66c65aa8c22e0ebbb6109075f0 (patch)
treea968912dd9cbbcb33e2979ae5349f90c9c0633e3 /src/services
parentf54d7caa723b53a6a44a067977ed858cc753f7a5 (diff)
downloadmuse-dd140b50fb79fd66c65aa8c22e0ebbb6109075f0.tar.xz
muse-dd140b50fb79fd66c65aa8c22e0ebbb6109075f0.zip
Fix caching (#941)
Diffstat (limited to 'src/services')
-rw-r--r--src/services/file-cache.ts30
-rw-r--r--src/services/player.ts38
2 files changed, 29 insertions, 39 deletions
diff --git a/src/services/file-cache.ts b/src/services/file-cache.ts
index 98a079c..3906772 100644
--- a/src/services/file-cache.ts
+++ b/src/services/file-cache.ts
@@ -18,11 +18,11 @@ export default class FileCacheProvider {
}
/**
- * Returns path to cached file if it exists, otherwise throws an error.
+ * Returns path to cached file if it exists, otherwise returns null.
* Updates the `accessedAt` property of the cached file.
* @param hash lookup key
*/
- async getPathFor(hash: string): Promise<string> {
+ async getPathFor(hash: string): Promise<string | null> {
const model = await prisma.fileCache.findUnique({
where: {
hash,
@@ -30,7 +30,7 @@ export default class FileCacheProvider {
});
if (!model) {
- throw new Error('File is not cached');
+ return null;
}
const resolvedPath = path.join(this.config.CACHE_DIR, hash);
@@ -44,7 +44,7 @@ export default class FileCacheProvider {
},
});
- throw new Error('File is not cached');
+ return null;
}
await prisma.fileCache.update({
@@ -76,19 +76,15 @@ export default class FileCacheProvider {
const stats = await fs.stat(tmpPath);
if (stats.size !== 0) {
- try {
- await fs.rename(tmpPath, finalPath);
-
- await prisma.fileCache.create({
- data: {
- hash,
- accessedAt: new Date(),
- bytes: stats.size,
- },
- });
- } catch (error) {
- debug('Errored when moving a finished cache file:', error);
- }
+ await fs.rename(tmpPath, finalPath);
+
+ await prisma.fileCache.create({
+ data: {
+ hash,
+ accessedAt: new Date(),
+ bytes: stats.size,
+ },
+ });
}
await this.evictOldestIfNecessary();
diff --git a/src/services/player.ts b/src/services/player.ts
index 239953d..c888896 100644
--- a/src/services/player.ts
+++ b/src/services/player.ts
@@ -410,26 +410,18 @@ export default class {
private async getStream(song: QueuedSong, options: {seek?: number; to?: number} = {}): Promise<Readable> {
if (song.source === MediaSource.HLS) {
- return this.createReadStream(song.url);
+ return this.createReadStream({url: song.url, cacheKey: song.url});
}
- let ffmpegInput = '';
+ let ffmpegInput: string | null;
const ffmpegInputOptions: string[] = [];
let shouldCacheVideo = false;
let format: YTDLVideoFormat | undefined;
- try {
- ffmpegInput = await this.fileCache.getPathFor(this.getHashForCache(song.url));
-
- if (options.seek) {
- ffmpegInputOptions.push('-ss', options.seek.toString());
- }
+ ffmpegInput = await this.fileCache.getPathFor(this.getHashForCache(song.url));
- if (options.to) {
- ffmpegInputOptions.push('-to', options.to.toString());
- }
- } catch {
+ if (!ffmpegInput) {
// Not yet cached, must download
const info = await ytdl.getInfo(song.url);
@@ -485,17 +477,19 @@ export default class {
'-reconnect_delay_max',
'5',
]);
+ }
- if (options.seek) {
- ffmpegInputOptions.push('-ss', options.seek.toString());
- }
+ if (options.seek) {
+ ffmpegInputOptions.push('-ss', options.seek.toString());
+ }
- if (options.to) {
- ffmpegInputOptions.push('-to', options.to.toString());
- }
+ if (options.to) {
+ ffmpegInputOptions.push('-to', options.to.toString());
}
- return this.createReadStream(ffmpegInput, {
+ return this.createReadStream({
+ url: ffmpegInput,
+ cacheKey: song.url,
ffmpegInputOptions,
cache: shouldCacheVideo,
volumeAdjustment: format?.loudnessDb ? `${-format.loudnessDb}dB` : undefined,
@@ -556,19 +550,19 @@ export default class {
}
}
- private async createReadStream(url: string, options: {ffmpegInputOptions?: string[]; cache?: boolean; volumeAdjustment?: string} = {}): Promise<Readable> {
+ private async createReadStream(options: {url: string; cacheKey: string; ffmpegInputOptions?: string[]; cache?: boolean; volumeAdjustment?: string}): Promise<Readable> {
return new Promise((resolve, reject) => {
const capacitor = new WriteStream();
if (options?.cache) {
- const cacheStream = this.fileCache.createWriteStream(this.getHashForCache(url));
+ const cacheStream = this.fileCache.createWriteStream(this.getHashForCache(options.cacheKey));
capacitor.createReadStream().pipe(cacheStream);
}
const returnedStream = capacitor.createReadStream();
let hasReturnedStreamClosed = false;
- const stream = ffmpeg(url)
+ const stream = ffmpeg(options.url)
.inputOptions(options?.ffmpegInputOptions ?? ['-re'])
.noVideo()
.audioCodec('libopus')