Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.

Commit 1db9cad

Browse files
committed
feat: replace result api instead of throwing exception
1 parent 77414c6 commit 1db9cad

File tree

6 files changed

+6020
-99
lines changed

6 files changed

+6020
-99
lines changed

engine/exceptions/failed_curl_exception.h

Lines changed: 0 additions & 10 deletions
This file was deleted.

engine/exceptions/failed_init_curl_exception.h

Lines changed: 0 additions & 10 deletions
This file was deleted.

engine/exceptions/failed_open_file_exception.h

Lines changed: 0 additions & 10 deletions
This file was deleted.

engine/services/download_service.cc

Lines changed: 70 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44
#include <stdio.h>
55
#include <trantor/utils/Logger.h>
66
#include <filesystem>
7+
#include <optional>
78
#include <ostream>
89
#include <thread>
9-
#include "exceptions/failed_curl_exception.h"
10-
#include "exceptions/failed_init_curl_exception.h"
11-
#include "exceptions/failed_open_file_exception.h"
10+
#include "download_service.h"
1211
#include "utils/format_utils.h"
1312
#include "utils/logging_utils.h"
1413

@@ -32,42 +31,52 @@ void DownloadService::AddDownloadTask(
3231
CLI_LOG("Validating download items, please wait..");
3332
// preprocess to check if all the item are valid
3433
auto total_download_size{0};
34+
std::optional<std::string> err_msg = std::nullopt;
3535
for (auto& item : task.items) {
36-
try {
37-
auto size = GetFileSize(item.downloadUrl);
38-
item.bytes = size;
39-
total_download_size += size;
40-
} catch (const FailedCurlException& e) {
41-
CTL_ERR("Found invalid download item: " << item.downloadUrl << " - "
42-
<< e.what());
43-
throw;
36+
auto file_size = GetFileSize(item.downloadUrl);
37+
if (file_size.has_error()) {
38+
err_msg = file_size.error();
39+
break;
4440
}
41+
42+
item.bytes = file_size.value();
43+
total_download_size += file_size.value();
44+
}
45+
46+
if (err_msg.has_value()) {
47+
CTL_ERR(err_msg.value());
48+
return;
4549
}
4650

4751
// all items are valid, start downloading
48-
bool download_successfully = true;
52+
// if any item from the task failed to download, the whole task will be
53+
// considered failed
54+
std::optional<std::string> dl_err_msg = std::nullopt;
4955
for (const auto& item : task.items) {
5056
CLI_LOG("Start downloading: " + item.localPath.filename().string());
51-
try {
52-
Download(task.id, item, true);
53-
} catch (const std::runtime_error& e) {
54-
CTL_ERR("Failed to download: " << item.downloadUrl << " - " << e.what());
55-
download_successfully = false;
57+
auto result = Download(task.id, item, true);
58+
if (result.has_error()) {
59+
dl_err_msg = result.error();
5660
break;
5761
}
5862
}
63+
if (dl_err_msg.has_value()) {
64+
CTL_ERR(dl_err_msg.value());
65+
return;
66+
}
5967

60-
if (download_successfully && callback.has_value()) {
68+
if (callback.has_value()) {
6169
callback.value()(task);
6270
}
6371
}
6472

65-
uint64_t DownloadService::GetFileSize(const std::string& url) const {
73+
cpp::result<uint64_t, std::string> DownloadService::GetFileSize(
74+
const std::string& url) const noexcept {
6675
CURL* curl;
6776
curl = curl_easy_init();
6877

6978
if (!curl) {
70-
throw FailedInitCurlException();
79+
return cpp::fail(static_cast<std::string>("Failed to init CURL"));
7180
}
7281

7382
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
@@ -76,9 +85,8 @@ uint64_t DownloadService::GetFileSize(const std::string& url) const {
7685
CURLcode res = curl_easy_perform(curl);
7786

7887
if (res != CURLE_OK) {
79-
// if we have a failed here. it meant the url is invalid
80-
throw FailedCurlException("CURL failed: " +
81-
std::string(curl_easy_strerror(res)));
88+
return cpp::fail(static_cast<std::string>(
89+
"CURL failed: " + std::string(curl_easy_strerror(res))));
8290
}
8391

8492
curl_off_t content_length = 0;
@@ -90,19 +98,17 @@ uint64_t DownloadService::GetFileSize(const std::string& url) const {
9098
void DownloadService::AddAsyncDownloadTask(
9199
const DownloadTask& task,
92100
std::optional<OnDownloadTaskSuccessfully> callback) {
93-
101+
// just start one thread and handle all the download items
94102
for (const auto& item : task.items) {
95103
std::thread([this, task, &callback, item]() {
96104
this->Download(task.id, item, false);
97105
}).detach();
98106
}
99-
100-
// TODO: how to call the callback when all the download has finished?
101107
}
102108

103-
void DownloadService::Download(const std::string& download_id,
104-
const DownloadItem& download_item,
105-
bool allow_resume) {
109+
cpp::result<void, std::string> DownloadService::Download(
110+
const std::string& download_id, const DownloadItem& download_item,
111+
bool allow_resume) noexcept {
106112
CTL_INF("Absolute file output: " << download_item.localPath.string());
107113

108114
CURL* curl;
@@ -111,7 +117,7 @@ void DownloadService::Download(const std::string& download_id,
111117

112118
curl = curl_easy_init();
113119
if (!curl) {
114-
throw FailedInitCurlException();
120+
return cpp::fail(static_cast<std::string>("Failed to init CURL"));
115121
}
116122

117123
std::string mode = "wb";
@@ -121,45 +127,44 @@ void DownloadService::Download(const std::string& download_id,
121127
if (existing_file_size == -1) {
122128
CLI_LOG("Cannot get file size: " << download_item.localPath.string()
123129
<< " . Start download over!");
124-
return;
125-
}
126-
CTL_INF("Existing file size: " << download_item.downloadUrl << " - "
127-
<< download_item.localPath.string() << " - "
128-
<< existing_file_size);
129-
auto missing_bytes = download_item.bytes.value() - existing_file_size;
130-
if (missing_bytes > 0) {
131-
CLI_LOG("Found unfinished download! Additional "
132-
<< format_utils::BytesToHumanReadable(missing_bytes)
133-
<< " need to be downloaded.");
134-
std::cout << "Continue download [Y/n]: " << std::flush;
135-
std::string answer{""};
136-
std::getline(std::cin, answer);
137-
if (answer == "Y" || answer == "y" || answer.empty()) {
138-
mode = "ab";
139-
CLI_LOG("Resuming download..");
140-
} else {
141-
CLI_LOG("Start over..");
142-
}
143130
} else {
144-
CLI_LOG(download_item.localPath.filename().string()
145-
<< " is already downloaded!");
146-
std::cout << "Re-download? [Y/n]: " << std::flush;
147-
148-
std::string answer = "";
149-
std::getline(std::cin, answer);
150-
if (answer == "Y" || answer == "y" || answer.empty()) {
151-
CLI_LOG("Re-downloading..");
131+
CTL_INF("Existing file size: " << download_item.downloadUrl << " - "
132+
<< download_item.localPath.string()
133+
<< " - " << existing_file_size);
134+
auto missing_bytes = download_item.bytes.value() - existing_file_size;
135+
if (missing_bytes > 0) {
136+
CLI_LOG("Found unfinished download! Additional "
137+
<< format_utils::BytesToHumanReadable(missing_bytes)
138+
<< " need to be downloaded.");
139+
std::cout << "Continue download [Y/n]: " << std::flush;
140+
std::string answer{""};
141+
std::getline(std::cin, answer);
142+
if (answer == "Y" || answer == "y" || answer.empty()) {
143+
mode = "ab";
144+
CLI_LOG("Resuming download..");
145+
} else {
146+
CLI_LOG("Start over..");
147+
}
152148
} else {
153-
return;
149+
CLI_LOG(download_item.localPath.filename().string()
150+
<< " is already downloaded!");
151+
std::cout << "Re-download? [Y/n]: " << std::flush;
152+
153+
std::string answer = "";
154+
std::getline(std::cin, answer);
155+
if (answer == "Y" || answer == "y" || answer.empty()) {
156+
CLI_LOG("Re-downloading..");
157+
} else {
158+
return {};
159+
}
154160
}
155161
}
156162
}
157163

158164
file = fopen(download_item.localPath.string().c_str(), mode.c_str());
159165
if (!file) {
160-
auto err_msg{"Failed to open output file " +
161-
download_item.localPath.string()};
162-
throw FailedOpenFileException(err_msg);
166+
return cpp::fail("Failed to open output file " +
167+
download_item.localPath.string());
163168
}
164169

165170
curl_easy_setopt(curl, CURLOPT_URL, download_item.downloadUrl.c_str());
@@ -181,14 +186,13 @@ void DownloadService::Download(const std::string& download_id,
181186
res = curl_easy_perform(curl);
182187

183188
if (res != CURLE_OK) {
184-
fprintf(stderr, "curl_easy_perform() failed: %s\n",
185-
curl_easy_strerror(res));
186-
throw std::runtime_error("Failed to download file " +
187-
download_item.localPath.filename().string());
189+
return cpp::fail("Download failed! Error: " +
190+
static_cast<std::string>(curl_easy_strerror(res)));
188191
}
189192

190193
fclose(file);
191194
curl_easy_cleanup(curl);
195+
return {};
192196
}
193197

194198
curl_off_t DownloadService::GetLocalFileSize(
@@ -205,4 +209,4 @@ curl_off_t DownloadService::GetLocalFileSize(
205209
curl_off_t file_size = ftell64(file);
206210
fclose(file);
207211
return file_size;
208-
}
212+
}

engine/services/download_service.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <optional>
77
#include <sstream>
88
#include <vector>
9+
#include "utils/result.hpp"
910

1011
enum class DownloadType { Model, Engine, Miscellaneous, CudaToolkit, Cortex };
1112

@@ -69,11 +70,13 @@ class DownloadService {
6970
*
7071
* @param url - url to get file size
7172
*/
72-
uint64_t GetFileSize(const std::string& url) const;
73+
cpp::result<uint64_t, std::string> GetFileSize(
74+
const std::string& url) const noexcept;
7375

7476
private:
75-
void Download(const std::string& download_id,
76-
const DownloadItem& download_item, bool allow_resume);
77+
cpp::result<void, std::string> Download(const std::string& download_id,
78+
const DownloadItem& download_item,
79+
bool allow_resume) noexcept;
7780

7881
curl_off_t GetLocalFileSize(const std::filesystem::path& path) const;
7982
};

0 commit comments

Comments
 (0)