Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support the music cache limit #129

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion src/main/api/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ class Cache {
/**
* @param {string} path cache directory path
* @param {string} configPath config directory path
* @param {number} cacheLimitcache size limit in bytes. 0 means unlimited
*/
constructor(path, configPath) {
constructor(path, configPath, cacheLimit) {
if (typeof path === 'string') {
if (!fs.existsSync(path)) {
fs.mkdirSync(path);
Expand All @@ -34,6 +35,7 @@ class Cache {
} else {
throw new Error('Cache path unvalid');
}
this.cacheLimit = cacheLimit;
}

attachExternalCache(fileName, filePath) {
Expand All @@ -56,7 +58,35 @@ class Cache {
return path.join(this.path, String(fileName));
}

async setCacheLimit(newSize) {
this.cacheLimit = newSize;
this.spareSpace();
}

/**
* delete cache until cache size <= limit
*/
spareSpace() {
if (this.cacheLimit === 0) return;

const stats = fs.readdirSync(this.path)
.map(f => ({name: f, attr: fs.statSync(path.join(this.path, f))}))
.filter(f => f.attr.isFile());
let diskUsage = stats.reduce((x, y)=> x + y.attr.size, 0);
if (diskUsage <= this.cacheLimit)
return;
stats.sort((a, b)=> a.attr.atime < b.attr.atime);
for (const st of stats) {
const size = st.attr.size;
diskUsage -= size;
fs.unlinkSync(path.join(this.path, st.name));
if (diskUsage <= this.cacheLimit)
break;
}
}

writeStream(fileName) {
this.spareSpace();
return fs.createWriteStream(this.internalPath(fileName));
}

Expand Down
18 changes: 17 additions & 1 deletion src/main/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const CachePath = {
all: dataPath,
music: path.join(dataPath, 'musicCache')
};
const musicCache = new Cache(CachePath.music, dataPath);
const musicCache = new Cache(CachePath.music, dataPath, Settings.getSync().musicCacheLimit*1024*1024);
migrate();

const musicServer = new MusicServer(musicCache);
Expand Down Expand Up @@ -530,6 +530,22 @@ export async function clearCache(type) {
return { ok: true };
}

/**
* @param {Types.CacheType} size cache limit in bytes
* @returns {Promise<{ok: boolean; msg?: string}>}
*/
export async function setMusicCacheLimit(size) {
try {
await musicServer.cache.setCacheLimit(size);
} catch (e) {
return {
ok: false,
msg: e.stack
};
}
return { ok: true };
}

/**
* @returns {Promise<string>}
*/
Expand Down
2 changes: 1 addition & 1 deletion src/main/api/musicServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class MusicServer {
d('Got URL for music id=%d', id);
const musicRes = await this.cache.fetch(music.url.replace(/^http:/, 'https:'));
// TODO: write file only md5 matches
musicRes.body.pipe(fs.createWriteStream(this.cache.internalPath(fileName)));
musicRes.body.pipe(this.cache.writeStream(fileName));

const range = MusicServer.getRange(req, +musicRes.headers.get('content-length'));
res.writeHead(206, MusicServer.buildHeaders(range));
Expand Down
32 changes: 31 additions & 1 deletion src/main/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export const defaultSettings = {
themePrimaryColor: '#7e57c2',
themeSecondaryColor: '#ff4081',
themeVariety: 'auto',
autoReplacePlaylist: false
autoReplacePlaylist: false,
musicCacheLimit: 512,
};

/**
Expand All @@ -44,10 +45,18 @@ function writeFile(target) {
return fsp.writeFile(configPath, JSON.stringify(target, null, 4), 'utf8');
}

function writeFileSync(target) {
return fs.writeFileSync(configPath, JSON.stringify(target, null, 4), 'utf8');
}

function readFile() {
return fsp.readFile(configPath, 'utf8');
}

function readFileSync() {
return fs.readFileSync(configPath, 'utf8');
}

export async function set(target) {
try {
await fsp.access(configDir);
Expand All @@ -57,6 +66,15 @@ export async function set(target) {
return writeFile(target);
}

export function setSync(target) {
try {
fs.accessSync(configDir);
} catch (e) {
fs.mkdirSync(configDir);
}
return writeFileSync(target);
}

export async function get() {
let settings = defaultSettings;
try {
Expand All @@ -68,3 +86,15 @@ export async function get() {
}
return settings;
}

export function getSync() {
let settings = defaultSettings;
try {
fs.accessAsync(configPath);
const json = JSON.parse(readFileSync());
settings = trimSettings(json);
} catch (e) {
setSync(defaultSettings);
}
return settings;
}
7 changes: 7 additions & 0 deletions src/renderer/page/Settings/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ export default {
Api.getDataSize('all').then(s => this.dataSize = humanSize(s.size));
Api.getDataSize('music').then(s => this.musicSize = humanSize(s.size));
},
setMusicCacheLimit(size) {
Api.setMusicCacheLimit(size);
Api.getDataSize('music').then(s => this.musicSize = humanSize(s.size));
},
initData() {
this.refreshSize();
Api.getVersionName().then(v => this.versionName = v);
Expand Down Expand Up @@ -201,6 +205,9 @@ export default {
this.$toast.message('实际下载码率取决于歌曲最高码率和帐号最高可播放码率');
}
break;
case 'musicCacheLimit':
this.setMusicCacheLimit(val*1024*1024);
break;
}
}
});
Expand Down
12 changes: 12 additions & 0 deletions src/renderer/page/Settings/entries.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,18 @@ export const Entries = [
data: 'musicSize',
handler: 'promptClearMusicCache'
},
{
type: 'select',
title: '歌曲缓存空间限制',
prop: 'musicCacheLimit',
options: [
{ label: '无限制', value: 0 },
{ label: '128 MiB', value: 128 },
{ label: '256 MiB', value: 256 },
{ label: '512 MiB', value: 512 },
{ label: '1 GiB', value: 1024 },
]
},
{
type: 'plain',
title: '所有应用数据',
Expand Down