This commit is contained in:
Manav Rathi 2024-04-20 21:49:22 +05:30
parent 2b945dc169
commit 30fe91efb9
No known key found for this signature in database
2 changed files with 109 additions and 111 deletions

View file

@ -1,110 +0,0 @@
import { convertBytesToHumanReadable } from "@/next/file";
import log from "@/next/log";
import { ComlinkWorker } from "@/next/worker/comlink-worker";
import { CustomError } from "@ente/shared/error";
import { retryAsyncFunction } from "@ente/shared/utils";
import QueueProcessor from "@ente/shared/utils/queueProcessor";
import { getDedicatedConvertWorker } from "utils/comlink/ComlinkConvertWorker";
import { DedicatedConvertWorker } from "worker/convert.worker";
const WORKER_POOL_SIZE = 2;
const WAIT_TIME_BEFORE_NEXT_ATTEMPT_IN_MICROSECONDS = [100, 100];
const WAIT_TIME_IN_MICROSECONDS = 30 * 1000;
const BREATH_TIME_IN_MICROSECONDS = 1000;
class HEICConverter {
private convertProcessor = new QueueProcessor<Blob>();
private workerPool: ComlinkWorker<typeof DedicatedConvertWorker>[] = [];
private ready: Promise<void>;
constructor() {
this.ready = this.init();
}
private async init() {
this.workerPool = [];
for (let i = 0; i < WORKER_POOL_SIZE; i++) {
this.workerPool.push(getDedicatedConvertWorker());
}
}
async convert(fileBlob: Blob): Promise<Blob> {
await this.ready;
const response = this.convertProcessor.queueUpRequest(() =>
retryAsyncFunction<Blob>(async () => {
const convertWorker = this.workerPool.shift();
const worker = await convertWorker.remote;
try {
const convertedHEIC = await new Promise<Blob>(
(resolve, reject) => {
const main = async () => {
try {
const timeout = setTimeout(() => {
reject(Error("wait time exceeded"));
}, WAIT_TIME_IN_MICROSECONDS);
const startTime = Date.now();
const convertedHEIC =
await worker.convertHEICToJPEG(
fileBlob,
);
log.info(
`originalFileSize:${convertBytesToHumanReadable(
fileBlob?.size,
)},convertedFileSize:${convertBytesToHumanReadable(
convertedHEIC?.size,
)}, heic conversion time: ${
Date.now() - startTime
}ms `,
);
clearTimeout(timeout);
resolve(convertedHEIC);
} catch (e) {
reject(e);
}
};
main();
},
);
if (!convertedHEIC || convertedHEIC?.size === 0) {
log.error(
`converted heic fileSize is Zero - ${JSON.stringify(
{
originalFileSize:
convertBytesToHumanReadable(
fileBlob?.size ?? 0,
),
convertedFileSize:
convertBytesToHumanReadable(
convertedHEIC?.size ?? 0,
),
},
)}`,
);
}
await new Promise((resolve) => {
setTimeout(
() => resolve(null),
BREATH_TIME_IN_MICROSECONDS,
);
});
this.workerPool.push(convertWorker);
return convertedHEIC;
} catch (e) {
log.error("heic conversion failed", e);
convertWorker.terminate();
this.workerPool.push(getDedicatedConvertWorker());
throw e;
}
}, WAIT_TIME_BEFORE_NEXT_ATTEMPT_IN_MICROSECONDS),
);
try {
return await response.promise;
} catch (e) {
if (e.message === CustomError.REQUEST_CANCELLED) {
// ignore
return null;
}
throw e;
}
}
}
export default new HEICConverter();

View file

@ -1,5 +1,11 @@
import { convertBytesToHumanReadable } from "@/next/file";
import log from "@/next/log"; import log from "@/next/log";
import WasmHEICConverterService from "./heic-convert/service"; import { ComlinkWorker } from "@/next/worker/comlink-worker";
import { CustomError } from "@ente/shared/error";
import { retryAsyncFunction } from "@ente/shared/utils";
import QueueProcessor from "@ente/shared/utils/queueProcessor";
import { getDedicatedConvertWorker } from "utils/comlink/ComlinkConvertWorker";
import { DedicatedConvertWorker } from "worker/convert.worker";
class HeicConversionService { class HeicConversionService {
async convert(heicFileData: Blob): Promise<Blob> { async convert(heicFileData: Blob): Promise<Blob> {
@ -11,4 +17,106 @@ class HeicConversionService {
} }
} }
} }
const WORKER_POOL_SIZE = 2;
const WAIT_TIME_BEFORE_NEXT_ATTEMPT_IN_MICROSECONDS = [100, 100];
const WAIT_TIME_IN_MICROSECONDS = 30 * 1000;
const BREATH_TIME_IN_MICROSECONDS = 1000;
class HEICConverter {
private convertProcessor = new QueueProcessor<Blob>();
private workerPool: ComlinkWorker<typeof DedicatedConvertWorker>[] = [];
private ready: Promise<void>;
constructor() {
this.ready = this.init();
}
private async init() {
this.workerPool = [];
for (let i = 0; i < WORKER_POOL_SIZE; i++) {
this.workerPool.push(getDedicatedConvertWorker());
}
}
async convert(fileBlob: Blob): Promise<Blob> {
await this.ready;
const response = this.convertProcessor.queueUpRequest(() =>
retryAsyncFunction<Blob>(async () => {
const convertWorker = this.workerPool.shift();
const worker = await convertWorker.remote;
try {
const convertedHEIC = await new Promise<Blob>(
(resolve, reject) => {
const main = async () => {
try {
const timeout = setTimeout(() => {
reject(Error("wait time exceeded"));
}, WAIT_TIME_IN_MICROSECONDS);
const startTime = Date.now();
const convertedHEIC =
await worker.convertHEICToJPEG(
fileBlob,
);
log.info(
`originalFileSize:${convertBytesToHumanReadable(
fileBlob?.size,
)},convertedFileSize:${convertBytesToHumanReadable(
convertedHEIC?.size,
)}, heic conversion time: ${
Date.now() - startTime
}ms `,
);
clearTimeout(timeout);
resolve(convertedHEIC);
} catch (e) {
reject(e);
}
};
main();
},
);
if (!convertedHEIC || convertedHEIC?.size === 0) {
log.error(
`converted heic fileSize is Zero - ${JSON.stringify(
{
originalFileSize:
convertBytesToHumanReadable(
fileBlob?.size ?? 0,
),
convertedFileSize:
convertBytesToHumanReadable(
convertedHEIC?.size ?? 0,
),
},
)}`,
);
}
await new Promise((resolve) => {
setTimeout(
() => resolve(null),
BREATH_TIME_IN_MICROSECONDS,
);
});
this.workerPool.push(convertWorker);
return convertedHEIC;
} catch (e) {
log.error("heic conversion failed", e);
convertWorker.terminate();
this.workerPool.push(getDedicatedConvertWorker());
throw e;
}
}, WAIT_TIME_BEFORE_NEXT_ATTEMPT_IN_MICROSECONDS),
);
try {
return await response.promise;
} catch (e) {
if (e.message === CustomError.REQUEST_CANCELLED) {
// ignore
return null;
}
throw e;
}
}
}
const WasmHEICConverterService = new HEICConverter();
export default new HeicConversionService(); export default new HeicConversionService();