Skip to content

Commit 9e1fb15

Browse files
authored
Add timeout to model pulling (#3277)
Due to limitations in libgit2 we are not able to use it simultaneously with https proxy: libgit2/libgit2#7072 * Fix env leaking tests Ticket:CVS-166568 * Timeout for Windows does not work either
1 parent 5cba29a commit 9e1fb15

13 files changed

+365
-201
lines changed

WORKSPACE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,8 @@ load("@//third_party/llm_engine:llm_engine.bzl", "llm_engine")
487487
llm_engine()
488488

489489
### Libgit2
490-
load("@//third_party/libgt2:libgt2_engine.bzl", "libgt2_engine")
491-
libgt2_engine()
490+
load("@//third_party/libgit2:libgit2_engine.bzl", "libgit2_engine")
491+
libgit2_engine()
492492

493493
load("@//third_party/drogon:drogon.bzl", "drogon_cpp")
494494
drogon_cpp()

src/BUILD

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ cc_library(
700700
"//:ovms_dependencies", # TODO dispose or replace
701701
"//src/kfserving_api:kfserving_api_cpp",
702702
"capimodule",
703-
"//src/libgt2:hf_pull_model_module",
703+
"//src/pull_module:hf_pull_model_module",
704704
"predict_request_validation_utils", # to be removed when capi has its own lib and added there @atobisze
705705
"kfs_backend_impl",
706706
"tfs_backend_impl",
@@ -3076,9 +3076,10 @@ cc_library(
30763076
linkopts = [],
30773077
deps = [
30783078
":test_utils",
3079-
"//src/libgt2:libgt2",
3080-
"//src/libgt2:hf_pull_model_module",
3079+
"//src/pull_module:libgit2",
3080+
"//src/pull_module:hf_pull_model_module",
30813081
"//src:ovms_lib",
3082+
"libovmsstring_utils",
30823083
"@com_google_googletest//:gtest",
30833084
],
30843085
local_defines = COMMON_LOCAL_DEFINES,

src/libgt2/hf_pull_model_module.cpp

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

src/libgt2/BUILD renamed to src/pull_module/BUILD

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,18 @@ LINKOPTS_ADJUSTED = COMMON_STATIC_LIBS_LINKOPTS + select({
2828
})
2929

3030
cc_library(
31-
name = "libgt2",
32-
srcs = ["libgt2.cpp"],
33-
hdrs = ["libgt2.hpp"],
31+
name = "libgit2",
32+
srcs = ["libgit2.cpp"],
33+
hdrs = ["libgit2.hpp"],
3434
deps = [
35-
"@libgt2_engine//:libgt2_engine",
35+
"@libgit2_engine//:libgit2_engine",
3636
"@ovms//src:libovmslogging",
3737
"@ovms//src:libovmsstatus",
3838
"@ovms//src:libovmsstring_utils",
3939
],
4040
visibility = ["//visibility:public"],
4141
copts = COPTS_ADJUSTED,
4242
linkopts = LINKOPTS_ADJUSTED,
43-
alwayslink = 1,
4443
local_defines = COMMON_LOCAL_DEFINES,
4544
)
4645

@@ -49,7 +48,7 @@ cc_library(
4948
srcs = ["hf_pull_model_module.cpp"],
5049
hdrs = ["hf_pull_model_module.hpp"],
5150
deps = [
52-
":libgt2",
51+
":libgit2",
5352
"@ovms//src/graph_export:graph_export",
5453
"@ovms//src:cpp_headers",
5554
"@ovms//src:libovmsstring_utils",
@@ -60,6 +59,5 @@ cc_library(
6059
visibility = ["//visibility:public"],
6160
copts = COPTS_ADJUSTED,
6261
linkopts = LINKOPTS_ADJUSTED,
63-
alwayslink = 1,
6462
local_defines = COMMON_LOCAL_DEFINES,
65-
)
63+
)
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
//***************************************************************************
2+
// Copyright 2025 Intel Corporation
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//*****************************************************************************
16+
#include "hf_pull_model_module.hpp"
17+
18+
#include <string>
19+
#include <utility>
20+
#include <variant>
21+
22+
#include "../config.hpp"
23+
#include "libgit2.hpp"
24+
#include "../graph_export/graph_export.hpp"
25+
#include "../logging.hpp"
26+
#include "../module_names.hpp"
27+
#include "../status.hpp"
28+
#include "../stringutils.hpp"
29+
30+
namespace ovms {
31+
const std::string DEFAULT_EMPTY_ENV_VALUE{""};
32+
33+
const std::string HfPullModelModule::GIT_SERVER_CONNECT_TIMEOUT_ENV{"GIT_SERVER_CONNECT_TIMEOUT_MS"};
34+
const std::string HfPullModelModule::GIT_SERVER_TIMEOUT_ENV{"GIT_SERVER_TIMEOUT_MS"};
35+
// GIT_OPT_SET_SERVER_TIMEOUT
36+
37+
static std::string getEnvReturnOrDefaultIfNotSet(const std::string& envName, const std::string& defaultValue = DEFAULT_EMPTY_ENV_VALUE) {
38+
std::string value = defaultValue;
39+
const char* envValue = std::getenv(envName.c_str());
40+
if (envValue) {
41+
value = std::string(envValue);
42+
SPDLOG_DEBUG("{} environment variable set. Using value: {};", envName, value);
43+
} else {
44+
SPDLOG_DEBUG("{} environment variable not set. Using default value: {};", envName, defaultValue);
45+
}
46+
return value;
47+
}
48+
49+
HfPullModelModule::HfPullModelModule() {}
50+
51+
#define RETURN_IF_ERROR(StatusOr) \
52+
do { \
53+
if (std::holds_alternative<Status>(StatusOr)) { \
54+
return std::get<Status>(StatusOr); \
55+
} \
56+
} while (0)
57+
58+
static std::variant<ovms::Status, Libgit2Options> prepareLibgit2Opts() {
59+
Libgit2Options opts;
60+
std::string timeoutString = getEnvReturnOrDefaultIfNotSet(HfPullModelModule::GIT_SERVER_CONNECT_TIMEOUT_ENV, "1000");
61+
auto timeoutOpt = ovms::stoi32(timeoutString);
62+
if (!timeoutOpt.has_value()) {
63+
SPDLOG_ERROR("Set invalid value for libgit2 server connection timeout:{}", timeoutString);
64+
return StatusCode::HF_FAILED_TO_INIT_LIBGIT2;
65+
}
66+
bool isHttpsProxyUsed = !getEnvReturnOrDefaultIfNotSet("https_proxy").empty();
67+
if (isHttpsProxyUsed) {
68+
if (timeoutOpt.value() != 0)
69+
SPDLOG_WARN("We are not able to set connection timeout when proxy is used");
70+
} else {
71+
opts.serverConnectTimeoutMs = timeoutOpt.value();
72+
}
73+
timeoutString = getEnvReturnOrDefaultIfNotSet(HfPullModelModule::GIT_SERVER_TIMEOUT_ENV, "0");
74+
timeoutOpt = ovms::stoi32(timeoutString);
75+
if (!timeoutOpt.has_value()) {
76+
SPDLOG_ERROR("Set invalid value for libgit2 server timeout:{}", timeoutString);
77+
return StatusCode::HF_FAILED_TO_INIT_LIBGIT2;
78+
}
79+
opts.serverTimeoutMs = timeoutOpt.value();
80+
return opts;
81+
}
82+
83+
std::variant<ovms::Status, std::unique_ptr<Libgt2InitGuard>> createGuard() {
84+
auto optsOrError = prepareLibgit2Opts();
85+
RETURN_IF_ERROR(optsOrError);
86+
auto initGuard = std::make_unique<Libgt2InitGuard>(std::get<Libgit2Options>(optsOrError));
87+
if (initGuard->status < 0) {
88+
SPDLOG_ERROR("Failed to init libgit2: {}", initGuard->errMsg.c_str());
89+
return StatusCode::HF_FAILED_TO_INIT_LIBGIT2;
90+
}
91+
return std::move(initGuard);
92+
}
93+
94+
Status HfPullModelModule::start(const ovms::Config& config) {
95+
state = ModuleState::STARTED_INITIALIZE;
96+
SPDLOG_INFO("{} starting", HF_MODEL_PULL_MODULE_NAME);
97+
auto guardOrError = createGuard();
98+
RETURN_IF_ERROR(guardOrError);
99+
this->hfSettings = config.getServerSettings().hfSettings;
100+
state = ModuleState::INITIALIZED;
101+
SPDLOG_INFO("{} started", HF_MODEL_PULL_MODULE_NAME);
102+
return StatusCode::OK;
103+
}
104+
105+
Status HfPullModelModule::clone() const {
106+
auto guardOrError = createGuard();
107+
if (std::holds_alternative<Status>(guardOrError)) {
108+
return std::get<Status>(guardOrError);
109+
}
110+
HfDownloader hfDownloader(this->hfSettings.sourceModel, this->hfSettings.downloadPath, this->GetHfEndpoint(), this->GetHfToken(), this->GetProxy());
111+
auto status = hfDownloader.cloneRepository();
112+
if (!status.ok()) {
113+
return status;
114+
}
115+
GraphExport graphExporter;
116+
status = graphExporter.createGraphFile(this->hfSettings.downloadPath, this->hfSettings.graphSettings);
117+
if (!status.ok()) {
118+
return status;
119+
}
120+
return StatusCode::OK;
121+
}
122+
123+
const std::string HfPullModelModule::GetProxy() const {
124+
return getEnvReturnOrDefaultIfNotSet("https_proxy");
125+
}
126+
127+
const std::string HfPullModelModule::GetHfToken() const {
128+
return getEnvReturnOrDefaultIfNotSet("HF_TOKEN");
129+
}
130+
131+
const std::string HfPullModelModule::GetHfEndpoint() const {
132+
std::string hfEndpoint = getEnvReturnOrDefaultIfNotSet("HF_ENDPOINT", "huggingface.co");
133+
if (!endsWith(hfEndpoint, "/")) {
134+
hfEndpoint.append("/");
135+
}
136+
return hfEndpoint;
137+
}
138+
139+
void HfPullModelModule::shutdown() {
140+
if (state == ModuleState::SHUTDOWN)
141+
return;
142+
state = ModuleState::STARTED_SHUTDOWN;
143+
SPDLOG_INFO("{} shutting down", HF_MODEL_PULL_MODULE_NAME);
144+
state = ModuleState::SHUTDOWN;
145+
SPDLOG_INFO("{} shutdown", HF_MODEL_PULL_MODULE_NAME);
146+
}
147+
148+
HfPullModelModule::~HfPullModelModule() {
149+
this->shutdown();
150+
}
151+
152+
} // namespace ovms

src/libgt2/hf_pull_model_module.hpp renamed to src/pull_module/hf_pull_model_module.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,7 @@ class HfPullModelModule : public Module {
3636
void shutdown() override;
3737

3838
Status clone() const;
39+
static const std::string GIT_SERVER_CONNECT_TIMEOUT_ENV;
40+
static const std::string GIT_SERVER_TIMEOUT_ENV;
3941
};
4042
} // namespace ovms

0 commit comments

Comments
 (0)