Rename and shuffle

This commit is contained in:
Manav Rathi
2024-07-02 18:57:19 +05:30
parent f757c996e7
commit f60ff6d8df
3 changed files with 88 additions and 23 deletions

View File

@@ -1,6 +1,6 @@
import DownloadManager from "@/new/photos/services/download";
import { clearFeatureFlagSessionState } from "@/new/photos/services/feature-flags";
import { terminateFaceWorker } from "@/new/photos/services/ml";
import { terminateMLWorker } from "@/new/photos/services/ml";
import { clearFaceData } from "@/new/photos/services/ml/db";
import mlWorkManager from "@/new/photos/services/ml/mlWorkManager";
import log from "@/next/log";
@@ -19,11 +19,23 @@ export const photosLogout = async () => {
const ignoreError = (label: string, e: unknown) =>
log.error(`Ignoring error during logout (${label})`, e);
// - Workers
// Terminate any workers before clearing persistent state.
// See: [Note: Caching IDB instances in separate execution contexts].
try {
terminateMLWorker();
} catch (e) {
ignoreError("face", e);
}
// - Remote logout and clear state
await accountLogout();
// - Photos specific logout
try {
clearFeatureFlagSessionState();
} catch (e) {
@@ -42,11 +54,7 @@ export const photosLogout = async () => {
ignoreError("CLIP", e);
}
try {
terminateFaceWorker();
} catch (e) {
ignoreError("face", e);
}
// - Desktop
const electron = globalThis.electron;
if (electron) {
@@ -69,7 +77,7 @@ export const photosLogout = async () => {
}
try {
await electron?.logout();
await electron.logout();
} catch (e) {
ignoreError("electron", e);
}

View File

@@ -1,31 +1,31 @@
/**
* @file Main thread interface to {@link FaceWorker}.
* @file Main thread interface to {@link MLWorker}.
*/
import { ComlinkWorker } from "@/next/worker/comlink-worker";
import { FaceWorker } from "./worker";
import { MLWorker } from "./worker";
/** Cached instance of the {@link ComlinkWorker} that wraps our web worker. */
let _comlinkWorker: ComlinkWorker<typeof FaceWorker> | undefined;
let _comlinkWorker: ComlinkWorker<typeof MLWorker> | undefined;
/** Lazily created, cached, instance of {@link FaceWorker}. */
export const faceWorker = async () =>
/** Lazily created, cached, instance of {@link MLWorker}. */
export const worker = async () =>
(_comlinkWorker ??= createComlinkWorker()).remote;
const createComlinkWorker = () =>
new ComlinkWorker<typeof FaceWorker>(
"face",
new ComlinkWorker<typeof MLWorker>(
"ml",
new Worker(new URL("worker.ts", import.meta.url)),
);
/**
* Terminate {@link faceWorker} (if any).
* Terminate {@link worker} (if any).
*
* This is useful during logout to immediately stop any background face related
* operations that are in-flight for the current user. After the user logs in
* again, a new {@link faceWorker} will be created on demand.
* This is useful during logout to immediately stop any background ML operations
* that are in-flight for the current user. After the user logs in again, a new
* {@link worker} will be created on demand for subsequent usage.
*/
export const terminateFaceWorker = () => {
export const terminateMLWorker = () => {
if (_comlinkWorker) {
_comlinkWorker.terminate();
_comlinkWorker = undefined;

View File

@@ -1,14 +1,20 @@
import { markIndexingFailed, saveFaceIndex } from "@/new/photos/services/ml/db";
import type { FaceIndex } from "@/new/photos/services/ml/types";
import type { EnteFile } from "@/new/photos/types/file";
import log from "@/next/log";
import { expose } from "comlink";
import { pullFaceEmbeddings } from "./embedding";
import { fileLogID } from "../../utils/file";
import { pullFaceEmbeddings, putFaceIndex } from "./embedding";
import { indexFaces } from "./f-index";
/**
* Run operations related to face indexing and search in a Web Worker.
* Run operations related to machine learning (e.g. indexing) in a Web Worker.
*
* This is a normal class that is however exposed (via comlink) as a proxy
* running inside a Web Worker. This way, we do not bother the main thread with
* tasks that might degrade interactivity.
*/
export class FaceWorker {
export class MLWorker {
private isSyncing = false;
/**
@@ -22,4 +28,55 @@ export class FaceWorker {
}
}
expose(FaceWorker);
expose(MLWorker);
/**
* Index faces in a file, save the persist the results locally, and put them
* on remote.
*
* @param enteFile The {@link EnteFile} to index.
*
* @param file If the file is one which is being uploaded from the current
* client, then we will also have access to the file's content. In such
* cases, pass a web {@link File} object to use that its data directly for
* face indexing. If this is not provided, then the file's contents will be
* downloaded and decrypted from remote.
*
* @param userAgent The UA of the client that is doing the indexing (us).
*/
export const index = async (
enteFile: EnteFile,
file: File | undefined,
userAgent: string,
) => {
const f = fileLogID(enteFile);
const startTime = Date.now();
let faceIndex: FaceIndex;
try {
faceIndex = await indexFaces(enteFile, file, userAgent);
} catch (e) {
// Mark indexing as having failed only if the indexing itself
// failed, not if there were subsequent failures (like when trying
// to put the result to remote or save it to the local face DB).
log.error(`Failed to index faces in ${f}`, e);
await markIndexingFailed(enteFile.id);
throw e;
}
try {
await putFaceIndex(enteFile, faceIndex);
await saveFaceIndex(faceIndex);
} catch (e) {
log.error(`Failed to put/save face index for ${f}`, e);
throw e;
}
log.debug(() => {
const nf = faceIndex.faceEmbedding.faces.length;
const ms = Date.now() - startTime;
return `Indexed ${nf} faces in ${f} (${ms} ms)`;
});
return faceIndex;
};