Skip to content

Commit

Permalink
Fix - Multipart Resources (#336)
Browse files Browse the repository at this point in the history
* Update model methods to run background task when creating the endpoint and creating score endpoint for runpod to use

* Handle error from Runpod, URL inference from yaml file

* Update backend/app/api/endpoints/base/score.py

Co-authored-by: Rafael Mosquera <[email protected]>

* Rename method

* rename endpoint

* Print background tasks and correct typo

* Correct typos and correct schemas

* model uid

* remove c

* ad ta to metada (facepalm)

* add update publish status to make change the publish state of the models

* change order of background tasks

* print instead of raising error for the second background task to run

* limit the upload batch to 100 so the browser doesn't experience insufficient resources error

---------

Co-authored-by: Rafael Mosquera <[email protected]>
  • Loading branch information
shincap8 and remg1997 authored Feb 10, 2025
1 parent 5f33b10 commit 53c68d1
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 50 deletions.
7 changes: 4 additions & 3 deletions frontends/web/src/new_front/pages/SubmitModel/SubmitModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const SubmitModel = () => {
configYaml.evaluation?.type === "heavy" &&
modelData.file.size > THRESHOLD
) {
const chunkSize = 1 * 1024 * 1024 * 10; // 10MB
const chunkSize = 1 * 1024 * 1024 * 100; // 100MB
const partsCount = Math.ceil(modelData.file.size / chunkSize); //10MB
const data = {
model_name: modelData.modelName,
Expand All @@ -72,9 +72,10 @@ const SubmitModel = () => {
parts_count: partsCount,
};
getSignedURLS(formData, modelData.file, data, chunkSize).then(
(data) => {
(succeed) => {
setLoading({ loading: true, text: "Done" });
if (data) {
console.log("fin", succeed);
if (succeed) {
Swal.fire({
title: "Good job!",
text: "Your model will be uploaded and soon you will be able to see the results in the dynaboard (you will receive an email!)",
Expand Down
104 changes: 57 additions & 47 deletions frontends/web/src/new_front/pages/SubmitModel/useUploadHeavyFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const useUploadHeavyFile = () => {
chunkSize: number,
) => {
const localParts: partObject[] = [];
const promises: Promise<void>[] = [];
const BATCH_SIZE = 100;
const abortParams = {
upload_id: uploadId,
model_name: formData.get("model_name"),
Expand All @@ -60,53 +60,60 @@ const useUploadHeavyFile = () => {
task_code: formData.get("task_code"),
};
let uploadFailed = false;

const uploadProgresschunk = 1 / urls.length;
for (let i = 0; i < urls.length; i++) {
if (uploadFailed) {
break;
}
const start = i * chunkSize;
const chunk = file?.slice(start, start + chunkSize);
const promise = axios
.request({
method: "put",
url: urls[i],
data: chunk,
headers: {
"Content-Type": file.type,
},
})
.then((response) => {
localParts.push({
ETag: response.headers.etag,
PartNumber: i + 1,
});
setProgress((prevState) => prevState + uploadProgresschunk);
})
.catch((err) => {
console.error(`Failed to upload part ${i + 1}: ${err.message}`);
uploadFailed = true;
});

promises.push(promise);
}

return Promise.all(promises)
.then(() => {
function processBatch(batchIndex: number): Promise<boolean> {
if (batchIndex >= urls.length || uploadFailed) {
if (uploadFailed) {
console.error(
"Aborting multipart upload due to part upload failure.",
);
abortUpload(abortParams);
return false;
return abortUpload(abortParams).then(() => false);
}
return completeUpload(formData, uploadId, localParts, abortParams);
})
.catch((err) => {
console.error("An error occurred during the upload:", err);
return false;
})
return completeUpload(formData, uploadId, localParts, abortParams).then(
() => true,
);
}

const batch = urls.slice(batchIndex, batchIndex + BATCH_SIZE);
const promises = [];

for (let i = 0; i < batch.length; i++) {
const globalIndex = batchIndex + i;
const start = globalIndex * chunkSize;
const chunk = file?.slice(start, start + chunkSize);
const promise = axios
.request({
method: "put",
url: urls[globalIndex],
data: chunk,
headers: {
"Content-Type": file.type,
},
})
.then((response) => {
localParts.push({
ETag: response.headers.etag,
PartNumber: globalIndex + 1,
});
setProgress((prevState) => prevState + uploadProgresschunk);
return false;
})
.catch((err) => {
console.error(`Failed to upload part ${i + 1}: ${err.message}`);
uploadFailed = true;
return false;
});

promises.push(promise);
}

return Promise.all(promises).then(() =>
processBatch(batchIndex + BATCH_SIZE),
);
}

return processBatch(0);
};

const completeUpload = (
Expand Down Expand Up @@ -141,19 +148,22 @@ const useUploadHeavyFile = () => {
});
};

const abortUpload = (params: any) => {
const abortUpload = (params: any): Promise<void> => {
const url = `${baseURL}/model/abort-mutipart-upload`;
setProgress(0);
axios
.post(url, params)
return axios
.request({
method: "post",
url: url,
data: params,
})
.then(() => {
console.log("Multipart upload aborted successfully.");
return false;
})
.catch((err) => {
console.error("Failed to abort multipart upload:", err.message);
return false;
});
})
.then(() => Promise.resolve());
};

return { bigProgress, getSignedURLS };
Expand Down

0 comments on commit 53c68d1

Please sign in to comment.