From 000918844a79322f1294731243ab9eb6c2c93a41 Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Mon, 5 Feb 2024 01:42:32 -0700 Subject: [PATCH] Queue uploads --- component/video/camera.tsx | 94 ++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/component/video/camera.tsx b/component/video/camera.tsx index 3f63050..1a0e682 100644 --- a/component/video/camera.tsx +++ b/component/video/camera.tsx @@ -24,55 +24,79 @@ type Dictionary = { class StreamUploadManager { client: ApolloClient; videoId: number; - nextUploadIdToRequest: number; - highestUploadLinkObtained: number; - prefetchedUploadLinks: Dictionary; + nextUploadIdToRequest: number = 0; + highestUploadLinkObtained: number = -1; + prefetchedUploadLinks: Dictionary = {}; + uploadQueue: Array<() => Promise> = []; + isUploading: boolean = false; - constructor(client: ApolloClient, streamId: number) { + constructor(client: ApolloClient, videoId: number) { this.client = client; - this.videoId = streamId; - this.highestUploadLinkObtained = -1; - this.prefetchedUploadLinks = {}; + this.videoId = videoId; } - async uploadChunk({ filepath, index }: { filepath: string; index: number }) { - const uploadUrl = await this.getUploadLink(index); - const uploadRequest = RNFS.uploadFiles({ - toUrl: uploadUrl, - files: [{ filepath: filepath }], - method: "PUT", - headers: { - "Content-Type": "application/octet-stream", - }, - begin: (res) => { - console.log("Start upload", res); - }, - progress: (res) => { - console.log("Uploading", res); - }, - }); - console.log(JSON.stringify(uploadRequest)); - const result = await uploadRequest.promise.catch((err) => - console.log("Upload error!", err), - ); - if (response.statusCode == 200) { - console.log(`${filepath} Uploaded`); - } else { - console.log("SERVER ERROR"); + enqueueUploadTask(task: () => Promise) { + this.uploadQueue.push(task); + this.processUploadQueue(); + } + + async processUploadQueue() { + if (this.isUploading || this.uploadQueue.length === 0) { + return; + } + this.isUploading = true; + const task = this.uploadQueue.shift(); + try { + if (task) await task(); + } catch (error) { + console.error("Error processing upload task", error); + } finally { + this.isUploading = false; + this.processUploadQueue(); } } + async uploadChunk({ filepath, index }: { filepath: string; index: number }) { + this.enqueueUploadTask(async () => { + const uploadUrl = await this.getUploadLink(index); + const uploadRequest = RNFS.uploadFiles({ + toUrl: uploadUrl, + files: [{ filepath: filepath }], + method: "PUT", + headers: { + "Content-Type": "application/octet-stream", + }, + begin: (res) => { + console.log("Start upload", res); + }, + progress: (res) => { + console.log("Uploading", res); + }, + }); + console.log(JSON.stringify(uploadRequest)); + const result = await uploadRequest.promise; + if (result.statusCode === 200) { + console.log(`${filepath} Uploaded`); + } else { + console.error("SERVER ERROR"); + } + }); + } + async getUploadLink(chunkId: number): Promise { + if (this.prefetchedUploadLinks[chunkId]) { + return this.prefetchedUploadLinks[chunkId]; + } return this.requestUploadLink(chunkId); } async requestUploadLink(chunkId: number): Promise { - console.log(`Requesting ${chunkId}`); + console.log(`Requesting upload link for chunk ${chunkId}`); const result = await this.client.mutate({ mutation: gql.GetUploadLinkDocument, variables: { videoId: this.videoId, chunkIndex: chunkId }, }); - console.log(JSON.stringify(result.data)); + this.prefetchedUploadLinks[chunkId] = result.data.getUploadLink.uploadUrl; return result.data.getUploadLink.uploadUrl; } } @@ -140,8 +164,8 @@ export default function CameraScreen({ const device = useCameraDevice("back"); const format = useCameraFormat(device, [ - { videoResolution: { width: 3048, height: 2160 } }, - { fps: 60 }, + { videoResolution: { width: 1920, height: 1080 } }, + { fps: 30 }, ]); // TODO(#60): setOrientation should be called when changes are detected