address most problems

This commit is contained in:
Xuan Son Nguyen 2025-11-20 18:34:22 +01:00
parent 216140867e
commit 5369aaa1d6
2 changed files with 34 additions and 13 deletions

View File

@ -10,6 +10,8 @@
#include <mutex> #include <mutex>
#include <condition_variable> #include <condition_variable>
#include <cstring> #include <cstring>
#include <atomic>
#include <chrono>
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
@ -60,7 +62,10 @@ static std::filesystem::path get_server_exec_path() {
#else #else
char path[FILENAME_MAX]; char path[FILENAME_MAX];
ssize_t count = readlink("/proc/self/exe", path, FILENAME_MAX); ssize_t count = readlink("/proc/self/exe", path, FILENAME_MAX);
return std::filesystem::path(std::string(path, (count > 0) ? count: 0)); if (count <= 0) {
throw std::runtime_error("failed to resolve /proc/self/exe");
}
return std::filesystem::path(std::string(path, count));
#endif #endif
} }
@ -203,22 +208,27 @@ std::vector<server_model_meta> server_models::get_all_meta() {
} }
void server_models::load(const std::string & name) { void server_models::load(const std::string & name) {
auto meta = get_meta(name); std::lock_guard<std::mutex> lk(mutex);
if (!meta.has_value()) { if (mapping.find(name) == mapping.end()) {
throw std::runtime_error("model name=" + name + " is not found"); throw std::runtime_error("model name=" + name + " is not found");
} }
std::lock_guard<std::mutex> lk(mutex); auto meta = mapping[name].meta;
if (meta->status != SERVER_MODEL_STATUS_FAILED && meta->status != SERVER_MODEL_STATUS_UNLOADED) { if (meta.status != SERVER_MODEL_STATUS_FAILED && meta.status != SERVER_MODEL_STATUS_UNLOADED) {
SRV_INF("model %s is not ready\n", name.c_str()); SRV_INF("model %s is not ready\n", name.c_str());
return; return;
} }
// prepare new instance info
instance_t inst; instance_t inst;
inst.meta = meta.value(); inst.meta = meta;
inst.meta.port = get_free_port(); inst.meta.port = get_free_port();
inst.meta.status = SERVER_MODEL_STATUS_LOADING; inst.meta.status = SERVER_MODEL_STATUS_LOADING;
if (inst.meta.port <= 0) {
throw std::runtime_error("failed to get a port number");
}
inst.subproc = std::make_shared<subprocess_s>(); inst.subproc = std::make_shared<subprocess_s>();
{ {
std::string exec_path = get_server_exec_path().string(); std::string exec_path = get_server_exec_path().string();
@ -354,17 +364,25 @@ void server_models::wait_until_loaded(const std::string & name) {
}); });
} }
void server_models::ensure_model_loaded(const std::string & name) { bool server_models::ensure_model_loaded(const std::string & name) {
auto meta = get_meta(name); auto meta = get_meta(name);
if (!meta.has_value()) { if (!meta.has_value()) {
throw std::runtime_error("model name=" + name + " is not found"); throw std::runtime_error("model name=" + name + " is not found");
} }
if (meta->is_active()) { if (meta->is_active()) {
return; // already loaded return false; // already loaded
} }
SRV_INF("model name=%s is not loaded, loading...\n", name.c_str()); SRV_INF("model name=%s is not loaded, loading...\n", name.c_str());
load(name); load(name);
wait_until_loaded(name); wait_until_loaded(name);
{
// check final status
meta = get_meta(name);
if (!meta.has_value() || meta->status == SERVER_MODEL_STATUS_FAILED) {
throw std::runtime_error("model name=" + name + " failed to load");
}
}
return true;
} }
server_http_res_ptr server_models::proxy_request(const server_http_req & req, const std::string & method, const std::string & name) { server_http_res_ptr server_models::proxy_request(const server_http_req & req, const std::string & method, const std::string & name) {
@ -372,7 +390,9 @@ server_http_res_ptr server_models::proxy_request(const server_http_req & req, co
if (!meta.has_value()) { if (!meta.has_value()) {
throw std::runtime_error("model name=" + name + " is not found"); throw std::runtime_error("model name=" + name + " is not found");
} }
ensure_model_loaded(name); // TODO: handle failure case if (ensure_model_loaded(name)) {
meta = get_meta(name); // refresh meta
}
SRV_INF("proxying request to model %s on port %d\n", name.c_str(), meta->port); SRV_INF("proxying request to model %s on port %d\n", name.c_str(), meta->port);
auto proxy = std::make_unique<server_http_proxy>( auto proxy = std::make_unique<server_http_proxy>(
method, method,
@ -439,11 +459,11 @@ struct pipe_t {
std::atomic<bool> writer_closed{false}; std::atomic<bool> writer_closed{false};
std::atomic<bool> reader_closed{false}; std::atomic<bool> reader_closed{false};
void close_write() { void close_write() {
writer_closed.store(true); writer_closed.store(true, std::memory_order_relaxed);
cv.notify_all(); cv.notify_all();
} }
void close_read() { void close_read() {
reader_closed.store(true); reader_closed.store(true, std::memory_order_relaxed);
cv.notify_all(); cv.notify_all();
} }
bool read(T & output, const std::function<bool()> & should_stop) { bool read(T & output, const std::function<bool()> & should_stop) {

View File

@ -13,7 +13,7 @@
/** /**
* state diagram: * state diagram:
* *
* UNLOADED LOADING LOADED * UNLOADED LOADING LOADED
* *
* *
@ -105,7 +105,8 @@ public:
void wait_until_loaded(const std::string & name); void wait_until_loaded(const std::string & name);
// load the model if not loaded, otherwise do nothing // load the model if not loaded, otherwise do nothing
void ensure_model_loaded(const std::string & name); // return false if model is already loaded; return true otherwise (meta may need to be refreshed)
bool ensure_model_loaded(const std::string & name);
// proxy an HTTP request to the model instance // proxy an HTTP request to the model instance
server_http_res_ptr proxy_request(const server_http_req & req, const std::string & method, const std::string & name); server_http_res_ptr proxy_request(const server_http_req & req, const std::string & method, const std::string & name);