replace happyhttp with cpp-httplib

This commit is contained in:
2024-04-17 21:38:37 +02:00
parent fba8417ddf
commit 4a2adff0c8
7 changed files with 75 additions and 1354 deletions

View File

@ -7,7 +7,7 @@ add_library(solanaceae_sdbot-webui STATIC
target_compile_features(solanaceae_sdbot-webui PUBLIC cxx_std_17)
target_link_libraries(solanaceae_sdbot-webui PUBLIC
happyhttp
httplib::httplib
solanaceae_contact
solanaceae_message3
nlohmann_json::nlohmann_json

View File

@ -8,9 +8,9 @@
#include <nlohmann/json.hpp>
#include <sodium.h>
#include <vector>
#include <fstream>
#include <filesystem>
#include <chrono>
#include <iostream>
@ -186,31 +186,29 @@ SDBot::~SDBot(void) {
}
float SDBot::iterate(void) {
if (static_cast<bool>(_con) && _con->outstanding()) {
_con->pump();
} else if (!_prompt_queue.empty()) { // dequeue new task
if (_current_task.has_value() != _curr_future.has_value()) {
std::cerr << "SDB inconsistent state\n";
if (_current_task.has_value()) {
_task_map.erase(_current_task.value());
_current_task = std::nullopt;
}
if (_current_task.has_value()) {
_curr_future.reset();
}
}
if (!_prompt_queue.empty() && !_current_task.has_value()) { // dequeue new task
const auto& [task_id, prompt] = _prompt_queue.front();
_current_task = task_id;
// TODO: reuse connection?
const std::string server_host {_conf.get_string("SDBot", "server_host").value()};
_con = std::make_unique<happyhttp::Connection>(
server_host.c_str(),
_conf.get_int("SDBot", "server_port").value()
);
_con->setcallbacks(
+[](const happyhttp::Response* r, void* ud) { static_cast<SDBot*>(ud)->onHttpBegin(r); },
+[](const happyhttp::Response* r, void* ud, const uint8_t* data, int n) { static_cast<SDBot*>(ud)->onHttpData(r, data, n); },
+[](const happyhttp::Response* r, void* ud) { static_cast<SDBot*>(ud)->onHttpComplete(r); },
this
);
static const char* headers [] {
"accept: application/json",
"Content-Type: application/json",
nullptr,
};
if (_cli == nullptr) {
const std::string server_host {_conf.get_string("SDBot", "server_host").value()};
_cli = std::make_unique<httplib::Client>(server_host, _conf.get_int("SDBot", "server_port").value());
_cli->set_read_timeout(std::chrono::minutes(5));
}
nlohmann::json j_body;
j_body["width"] = _conf.get_int("SDBot", "width").value_or(512);
@ -246,20 +244,55 @@ float SDBot::iterate(void) {
try {
const std::string url {_conf.get_string("SDBot", "url_txt2img").value()};
_con->request("POST", url.c_str(), headers, reinterpret_cast<const uint8_t*>(body.data()), body.size());
} catch (const happyhttp::Wobbly& e) {
std::cerr << "SDB http request error: " << e.what() << "\n";
_curr_future = std::async(std::launch::async, [this, url, body]() -> std::vector<uint8_t> {
// TODO: move to endpoint
auto res = _cli->Post(url, body, "application/json");
std::cout << "SDB http complete " << res->status << " " << res->reason << "\n";
if (
res.error() != httplib::Error::Success ||
res->status != 200
) {
return {};
}
return std::vector<uint8_t>(res->body.cbegin(), res->body.cend());
});
} catch (...) {
std::cerr << "SDB http request error\n";
// cleanup
_task_map.erase(_current_task.value());
_current_task = std::nullopt;
_con.reset();
_curr_future.reset();
}
_prompt_queue.pop();
}
if (_curr_future.has_value() && _curr_future.value().wait_for(std::chrono::milliseconds(1)) == std::future_status::ready) {
const auto& contact = _task_map.at(_current_task.value());
const auto data = _curr_future.value().get();
if (_endpoint->handleResponse(contact, ByteSpan{data})) {
// TODO: error handling
}
_task_map.erase(_current_task.value());
_current_task = std::nullopt;
_curr_future.reset();
}
// if active web connection, 5ms
return static_cast<bool>(_con) ? 0.005f : 1.f;
//return static_cast<bool>(_con) ? 0.005f : 1.f;
// if active web connection, 50ms
if (_curr_future.has_value() && _curr_future.value().valid()) {
return 0.05f;
} else {
return 1.f;
}
}
bool SDBot::onEvent(const Message::Events::MessageConstruct& e) {
@ -336,33 +369,3 @@ bool SDBot::onEvent(const Message::Events::MessageConstruct& e) {
return true;
}
void SDBot::onHttpBegin(const happyhttp::Response* r) {
std::cout << "SDB http begin " << r->getstatus() << " " << r->getreason() << "\n";
// TODO: handle errors
_con_data.clear();
}
void SDBot::onHttpData(const happyhttp::Response* /*r*/, const unsigned char* data, int n) {
//std::cout << "SDB http data\n";
// TODO: handle errors
for (int i = 0; i < n; i++) {
_con_data.push_back(data[i]);
}
}
void SDBot::onHttpComplete(const happyhttp::Response* r) {
std::cout << "SDB http complete " << r->getstatus() << " " << r->getreason() << "\n";
if (r->getstatus() == happyhttp::OK) {
std::cout << "SDB data\n";
const auto& contact = _task_map.at(_current_task.value());
if (_endpoint->handleResponse(contact, ByteSpan{_con_data})) {
// error?
}
_task_map.erase(_current_task.value());
_current_task = std::nullopt;
_con.reset();
}
}

View File

@ -4,14 +4,16 @@
#include <solanaceae/message3/registry_message_model.hpp>
#include <solanaceae/contact/contact_model3.hpp>
#include <happyhttp/happyhttp.h>
#include <httplib.h>
#include <map>
#include <vector>
#include <queue>
#include <string>
#include <memory>
#include <optional>
#include <random>
#include <future>
// fwd
struct ConfigModelI;
@ -29,8 +31,8 @@ class SDBot : public RegistryMessageModelEventI {
uint64_t _last_task_counter = 0;
std::optional<uint64_t> _current_task;
std::unique_ptr<happyhttp::Connection> _con;
std::vector<uint8_t> _con_data;
std::unique_ptr<httplib::Client> _cli;
std::optional<std::future<std::vector<uint8_t>>> _curr_future;
std::default_random_engine _rng;
@ -66,10 +68,5 @@ class SDBot : public RegistryMessageModelEventI {
//bool onToxEvent(const Tox_Event_Group_Message* e) override;
protected: // mm
bool onEvent(const Message::Events::MessageConstruct& e) override;
public: // http cb
void onHttpBegin(const happyhttp::Response* r);
void onHttpData(const happyhttp::Response* r, const unsigned char* data, int n);
void onHttpComplete(const happyhttp::Response* r);
};