This commit is contained in:
Manav Rathi 2024-04-13 06:47:43 +05:30
parent 5ff01c40d8
commit 3499e47c88
No known key found for this signature in database
4 changed files with 41 additions and 58 deletions

View file

@ -13,7 +13,6 @@ import {
generateStreamFromArrayBuffer,
getRenderableFileURL,
} from "utils/file";
import { isInternalUser } from "utils/user";
import { PhotosDownloadClient } from "./clients/photos";
import { PublicAlbumsDownloadClient } from "./clients/publicAlbums";
@ -56,9 +55,15 @@ export interface DownloadClient {
class DownloadManagerImpl {
private ready: boolean = false;
private downloadClient: DownloadClient;
/** Local cache for thumbnails. Might not be available. */
private thumbnailCache?: EnteCache;
/**
* Local cache for the files themselves.
*
* Only available when we're running in the desktop app.
*/
// disk cache is only available on electron
private diskFileCache?: EnteCache;
private fileCache?: EnteCache;
private cryptoWorker: Remote<DedicatedCryptoWorker>;
private fileObjectURLPromises = new Map<number, Promise<SourceURLs>>();
@ -74,21 +79,27 @@ class DownloadManagerImpl {
tokens?: { token: string; passwordToken?: string } | { token: string },
timeout?: number,
) {
try {
if (this.ready) {
log.info("DownloadManager already initialized");
return;
}
this.downloadClient = createDownloadClient(app, tokens, timeout);
this.thumbnailCache = await openThumbnailCache();
this.diskFileCache = isElectron() && (await openDiskFileCache());
this.cryptoWorker = await ComlinkCryptoWorker.getInstance();
this.ready = true;
eventBus.on(Events.LOGOUT, this.logoutHandler.bind(this), this);
} catch (e) {
log.error("DownloadManager init failed", e);
throw e;
if (this.ready) {
log.info("DownloadManager already initialized");
return;
}
this.downloadClient = createDownloadClient(app, tokens, timeout);
try {
this.thumbnailCache = await openCache("thumbs");
} catch (e) {
log.error(
"Failed to open thumbnail cache, will continue without it",
e,
);
}
try {
if (isElectron()) this.fileCache = await openCache("files");
} catch (e) {
log.error("Failed to open file cache, will continue without it", e);
}
this.cryptoWorker = await ComlinkCryptoWorker.getInstance();
this.ready = true;
eventBus.on(Events.LOGOUT, this.logoutHandler.bind(this), this);
}
private async logoutHandler() {
@ -139,11 +150,11 @@ class DownloadManagerImpl {
}
}
private async getCachedFile(file: EnteFile): Promise<Response> {
const fileCache = this.fileCache;
if (!fileCache) return null;
try {
if (!this.diskFileCache) {
return null;
}
const cacheResp: Response = await this.diskFileCache?.match(
const cacheResp: Response = await fileCache.match(
file.id.toString(),
);
return cacheResp?.clone();
@ -312,8 +323,8 @@ class DownloadManagerImpl {
onDownloadProgress,
),
);
if (this.diskFileCache) {
this.diskFileCache
if (this.fileCache) {
this.fileCache
.put(file.id.toString(), encrypted.clone())
.catch((e) => {
log.error("file cache put failed", e);
@ -345,8 +356,8 @@ class DownloadManagerImpl {
let resp: Response = await this.getCachedFile(file);
if (!resp) {
resp = await this.downloadClient.downloadFileStream(file);
if (this.diskFileCache) {
this.diskFileCache
if (this.fileCache) {
this.fileCache
.put(file.id.toString(), resp.clone())
.catch((e) => {
log.error("file cache put failed", e);
@ -511,35 +522,6 @@ const DownloadManager = new DownloadManagerImpl();
export default DownloadManager;
async function openThumbnailCache() {
try {
return await openCache("thumbs");
} catch (e) {
log.error("Failed to open thumbnail cache", e);
if (isInternalUser()) {
throw e;
} else {
return null;
}
}
}
async function openDiskFileCache() {
try {
if (!isElectron()) {
throw Error(CustomError.NOT_AVAILABLE_ON_WEB);
}
return await openCache("files");
} catch (e) {
log.error("Failed to open file cache", e);
if (isInternalUser()) {
throw e;
} else {
return null;
}
}
}
function createDownloadClient(
app: APPS,
tokens?: { token: string; passwordToken?: string } | { token: string },

View file

@ -440,7 +440,7 @@ export async function getRenderableImage(fileName: string, imageBlob: Blob) {
}
if (!isElectron()) {
throw Error(CustomError.NOT_AVAILABLE_ON_WEB);
throw new Error("not available on web");
}
log.info(
`RawConverter called for ${fileName}-${convertBytesToHumanReadable(

View file

@ -1,3 +1,5 @@
import isElectron from "is-electron";
const cacheNames = [
"thumbs",
"face-crops",
@ -77,7 +79,7 @@ export interface EnteCache {
* across namespaces.
*/
export const openCache = async (name: CacheName) =>
globalThis.electron ? openOPFSCacheWeb(name) : openWebCache(name);
isElectron() ? openOPFSCacheWeb(name) : openWebCache(name);
/** An implementation of {@link EnteCache} using Web Cache APIs */
const openWebCache = async (name: CacheName) => {
@ -103,7 +105,7 @@ const openOPFSCacheWeb = async (name: CacheName) => {
// this code will only run in our Electron app (which'll use Chromium as the
// renderer).
//
// So for our purpose, this can serve as the docs for what's available:
// So for our purpose, these can serve as the doc for what's available:
// https://web.dev/articles/origin-private-file-system
const cache = await caches.open(name);
@ -175,7 +177,7 @@ export async function cached(
* Meant for use during logout, to reset the state of the user's account.
*/
export const clearCaches = async () =>
globalThis.electron ? clearOPFSCaches() : clearWebCaches();
isElectron() ? clearOPFSCaches() : clearWebCaches();
export const clearWebCaches = async () => {
await Promise.all(cacheNames.map((name) => caches.delete(name)));

View file

@ -74,7 +74,6 @@ export const CustomError = {
EXIF_DATA_NOT_FOUND: "exif data not found",
SELECT_FOLDER_ABORTED: "select folder aborted",
NON_MEDIA_FILE: "non media file",
NOT_AVAILABLE_ON_WEB: "not available on web",
UNSUPPORTED_RAW_FORMAT: "unsupported raw format",
NON_PREVIEWABLE_FILE: "non previewable file",
PROCESSING_FAILED: "processing failed",