diff --git a/src/bootstrap.ts b/src/bootstrap.ts index b304466..411f5de 100644 --- a/src/bootstrap.ts +++ b/src/bootstrap.ts @@ -21,6 +21,11 @@ export async function bootstrap(version: string): Promise { const cluster = new Cluster(config.clusterSecret, version, tokenManager) await cluster.init() + const storageReady = await cluster.storage.check() + if (!storageReady) { + throw new Error('存储异常') + } + const configuration = await cluster.getConfiguration() const files = await cluster.getFileList() logger.info(`${files.files.length} files`) diff --git a/src/cluster.ts b/src/cluster.ts index c80c12f..07364fc 100644 --- a/src/cluster.ts +++ b/src/cluster.ts @@ -40,7 +40,7 @@ interface ICounters { bytes: number } -const whiteListDomain = ['localhost', 'bangbang93.com'] +const whiteListDomain = ['localhost', 'bangbang93.com', '192.168'] // eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = dirname(fileURLToPath(import.meta.url)) @@ -158,6 +158,10 @@ export class Cluster { } public async syncFiles(fileList: IFileList, syncConfig: OpenbmclapiAgentConfiguration['sync']): Promise { + const storageReady = await this.storage.check() + if (!storageReady) { + throw new Error('存储异常') + } const missingFiles = await this.storage.getMissingFiles(fileList.files) if (missingFiles.length === 0) { return diff --git a/src/storage/base.storage.ts b/src/storage/base.storage.ts index cb692a2..32b4bbb 100644 --- a/src/storage/base.storage.ts +++ b/src/storage/base.storage.ts @@ -8,6 +8,9 @@ import {FileStorage} from './file.storage.js' export interface IStorage { init?(): Promise + + check(): Promise + writeFile(path: string, content: Buffer, fileInfo: IFileInfo): Promise exists(path: string): Promise diff --git a/src/storage/file.storage.ts b/src/storage/file.storage.ts index c627611..b45c69f 100644 --- a/src/storage/file.storage.ts +++ b/src/storage/file.storage.ts @@ -2,7 +2,7 @@ import Bluebird from 'bluebird' import colors from 'colors/safe.js' import type {Request, Response} from 'express' import fse from 'fs-extra' -import {readdir, stat, unlink} from 'fs/promises' +import {access, readdir, rm, stat, unlink, writeFile} from 'fs/promises' import {min} from 'lodash-es' import {join, sep} from 'path' import {logger} from '../logger.js' @@ -13,12 +13,25 @@ import type {IStorage} from './base.storage.js' export class FileStorage implements IStorage { constructor(public readonly cacheDir: string) {} + public async check(): Promise { + try { + await access(this.cacheDir) + await writeFile(join(this.cacheDir, '.check'), '') + return true + } catch (e) { + logger.error(e, '存储检查异常') + return false + } finally { + await rm(join(this.cacheDir, '.check'), {recursive: true, force: true}) + } + } + public async writeFile(path: string, content: Buffer): Promise { await fse.outputFile(join(this.cacheDir, path), content) } public async exists(path: string): Promise { - return fse.pathExists(join(this.cacheDir, path)) + return await fse.pathExists(join(this.cacheDir, path)) } public getAbsolutePath(path: string): string { @@ -26,7 +39,7 @@ export class FileStorage implements IStorage { } public async getMissingFiles(files: IFileInfo[]): Promise { - return Bluebird.filter( + return await Bluebird.filter( files, async (file) => { const st = await stat(join(this.cacheDir, hashToFilename(file.hash))).catch(() => null) @@ -70,7 +83,7 @@ export class FileStorage implements IStorage { res.attachment(name) } const path = this.getAbsolutePath(hashPath) - return new Promise((resolve, reject) => { + return await new Promise((resolve, reject) => { res.sendFile(path, {maxAge: '30d'}, (err) => { let bytes = res.socket?.bytesWritten ?? 0 if (!err || err?.message === 'Request aborted' || err?.message === 'write EPIPE') { diff --git a/src/storage/webdav.storage.ts b/src/storage/webdav.storage.ts index 8b82de4..5be5cbe 100644 --- a/src/storage/webdav.storage.ts +++ b/src/storage/webdav.storage.ts @@ -50,6 +50,18 @@ export class WebdavStorage implements IStorage { } } + public async check(): Promise { + try { + await this.client.putFileContents(join(this.basePath, '.check'), Buffer.from(Date.now().toString())) + return true + } catch (e) { + logger.error(e, '存储检查异常') + return false + } finally { + await this.client.deleteFile(join(this.basePath, '.check')) + } + } + public async writeFile(path: string, content: Buffer, fileInfo: IFileInfo): Promise { if (content.length === 0) { this.emptyFiles.add(path)