refactor
This commit is contained in:
parent
42a9ed9b44
commit
b92b5e2e91
13
monitarr/monitarr/include/run_cmd.hpp
Normal file
13
monitarr/monitarr/include/run_cmd.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef LIBMONITARR_INCLUDE_RUN_CMD_HPP_
|
||||
#define LIBMONITARR_INCLUDE_RUN_CMD_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace monitarr {
|
||||
struct app_config;
|
||||
|
||||
[[nodiscard]] auto run_cmd(const app_config &cfg, std::string_view cfg_file)
|
||||
-> int;
|
||||
} // namespace monitarr
|
||||
|
||||
#endif // LIBMONITARR_INCLUDE_RUN_CMD_HPP_
|
@ -2,110 +2,25 @@
|
||||
#include "backward.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_BACKWARD_CPP)
|
||||
|
||||
#include <execution>
|
||||
|
||||
#include "initialize.hpp"
|
||||
|
||||
#include "actions.hpp"
|
||||
#include "args.hpp"
|
||||
#include "block_cmd.hpp"
|
||||
#include "config_cmd.hpp"
|
||||
#include "data_db.hpp"
|
||||
#include "list_cmd.hpp"
|
||||
#include "run_cmd.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "show_cmd.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/config.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/unix.hpp"
|
||||
#include "utils/windows.hpp"
|
||||
|
||||
namespace monitarr {
|
||||
static void check_server(const server_cfg &server, data_db &state_db) {
|
||||
[[nodiscard]] static auto load_config(std::string &cfg_file) -> app_config {
|
||||
MONITARR_USES_FUNCTION_NAME();
|
||||
|
||||
fmt::println("checking server|{}|{}", server.id, server.url);
|
||||
|
||||
auto cli = create_client(server);
|
||||
|
||||
std::uint16_t page{0U};
|
||||
while (++page != 0U) {
|
||||
httplib::Params params;
|
||||
params.emplace("page", std::to_string(page));
|
||||
params.emplace("pageSize", "100");
|
||||
|
||||
auto response =
|
||||
cli.Get(fmt::format("/api/{}/queue", server.api_version), params, {});
|
||||
if (response->status != httplib::StatusCode::OK_200) {
|
||||
utils::error::handle_error(
|
||||
function_name, fmt::format("check server request failed|{}|{}|{}",
|
||||
server.id, server.url, response->status));
|
||||
break;
|
||||
}
|
||||
|
||||
auto json_data = nlohmann::json::parse(response->body);
|
||||
if (json_data.at("page").get<std::uint32_t>() != page) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto now = utils::time::get_time_now();
|
||||
|
||||
for (const auto &record : json_data.at("records")) {
|
||||
auto download_id =
|
||||
fmt::format("{}/{}", server.id, record.at("id").get<std::uint64_t>());
|
||||
auto episode_id = record.contains("episodeId")
|
||||
? record["episodeId"].get<std::uint64_t>()
|
||||
: std::uint64_t{0U};
|
||||
auto movie_id = record.contains("movieId")
|
||||
? record["movieId"].get<std::uint64_t>()
|
||||
: std::uint64_t{0U};
|
||||
auto size_left = record.at("sizeleft").get<std::uint64_t>();
|
||||
auto title = record.at("title").get<std::string>();
|
||||
auto is_downloading = utils::string::contains(
|
||||
record.at("status").get<std::string>(), "downloading");
|
||||
|
||||
auto data = state_db.get(download_id);
|
||||
const auto update_entry = [&download_id, &now, &size_left, &state_db,
|
||||
&title, url = server.url]() {
|
||||
if (size_left == 0U) {
|
||||
state_db.remove(download_id);
|
||||
return;
|
||||
}
|
||||
|
||||
fmt::println("updating {}|{}|{}|{}", download_id, title, now,
|
||||
size_left);
|
||||
state_db.set(data_entry{
|
||||
download_id,
|
||||
now,
|
||||
size_left,
|
||||
});
|
||||
};
|
||||
|
||||
if (data.has_value()) {
|
||||
if (std::chrono::nanoseconds(now - data->last_check) >=
|
||||
server.timeout) {
|
||||
if (size_left == data->size_left) {
|
||||
remove_stalled(download_id, title, episode_id, movie_id, server,
|
||||
&state_db);
|
||||
} else if (size_left == 0U || not is_downloading) {
|
||||
state_db.remove(download_id);
|
||||
} else {
|
||||
update_entry();
|
||||
}
|
||||
} else if (size_left == 0U || not is_downloading) {
|
||||
state_db.remove(download_id);
|
||||
}
|
||||
} else if (is_downloading && size_left > 0U) {
|
||||
update_entry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto load_config(std::string &cfg_file) -> app_config {
|
||||
auto cfg_dir = utils::get_environment_variable("MONITARR_CFG_DIR");
|
||||
if (cfg_dir.empty()) {
|
||||
cfg_dir = utils::path::combine(".", {"config"});
|
||||
@ -119,28 +34,12 @@ static void check_server(const server_cfg &server, data_db &state_db) {
|
||||
|
||||
cfg_file = utils::path::combine(cfg_dir, {"monitarr.json"});
|
||||
|
||||
fmt::println("loading config|{}", cfg_file);
|
||||
utils::error::handle_info(function_name,
|
||||
fmt::format("loading config|{}", cfg_file));
|
||||
app_config cfg{};
|
||||
cfg.load(cfg_file);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto load_db() -> data_db {
|
||||
auto data_dir = utils::get_environment_variable("MONITARR_DATA_DIR");
|
||||
if (data_dir.empty()) {
|
||||
data_dir = utils::path::combine(".", {"data"});
|
||||
}
|
||||
|
||||
if (not utils::file::directory{data_dir}.create_directory()) {
|
||||
throw std::runtime_error(fmt::format("failed to create data dir|{}",
|
||||
data_dir,
|
||||
utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
data_db state_db{};
|
||||
state_db.open(data_dir);
|
||||
return state_db;
|
||||
}
|
||||
} // namespace monitarr
|
||||
|
||||
using namespace monitarr;
|
||||
@ -157,102 +56,39 @@ auto main(int argc, char **argv) -> int {
|
||||
}
|
||||
|
||||
auto ret{0};
|
||||
if (argc > 1) {
|
||||
try {
|
||||
std::string cfg_file;
|
||||
auto cfg{load_config(cfg_file)};
|
||||
if (has_arg("-b", argc, argv)) {
|
||||
ret = block_cmd(argc, argv, cfg);
|
||||
} else if (has_arg("-c", argc, argv)) {
|
||||
ret = config_cmd(cfg);
|
||||
} else if (has_arg("-h", argc, argv)) {
|
||||
fmt::println("usage:");
|
||||
fmt::println("monitarr -b -i <index> -id <record id>");
|
||||
fmt::println("\tblocklist and search record id at configuration index");
|
||||
fmt::println("monitarr -c");
|
||||
fmt::println("\tdisplay configuration");
|
||||
fmt::println("monitarr -l -i <index>");
|
||||
fmt::println("\tdisplay server queue at configuration index");
|
||||
fmt::println("monitarr -s -i <index> -id <record id>");
|
||||
fmt::println("\tshow record id details at configuration index");
|
||||
} else if (has_arg("-l", argc, argv)) {
|
||||
ret = list_cmd(argc, argv, cfg);
|
||||
} else if (has_arg("-s", argc, argv)) {
|
||||
ret = show_cmd(argc, argv, cfg);
|
||||
}
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
ret = 2;
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
ret = 2;
|
||||
|
||||
try {
|
||||
std::string cfg_file;
|
||||
auto cfg{load_config(cfg_file)};
|
||||
if (has_arg("-b", argc, argv)) {
|
||||
ret = block_cmd(argc, argv, cfg);
|
||||
} else if (has_arg("-c", argc, argv)) {
|
||||
ret = config_cmd(cfg);
|
||||
} else if (argc == 1 || has_arg("-h", argc, argv)) {
|
||||
fmt::println("usage:");
|
||||
fmt::println(" monitarr -b -i <index> -id <record id>");
|
||||
fmt::println(" blocklist and search record id at configuration index");
|
||||
fmt::println(" monitarr -c");
|
||||
fmt::println(" display configuration");
|
||||
fmt::println(" monitarr -l -i <index>");
|
||||
fmt::println(" display server queue at configuration index");
|
||||
fmt::println(" monitarr -r");
|
||||
fmt::println(" run monitarr server");
|
||||
fmt::println(" monitarr -s -i <index> -id <record id>");
|
||||
fmt::println(" show record id details at configuration index");
|
||||
} else if (has_arg("-l", argc, argv)) {
|
||||
ret = list_cmd(argc, argv, cfg);
|
||||
} else if (has_arg("-r", argc, argv)) {
|
||||
ret = run_cmd(cfg, cfg_file);
|
||||
} else if (has_arg("-s", argc, argv)) {
|
||||
ret = show_cmd(argc, argv, cfg);
|
||||
}
|
||||
} else {
|
||||
static std::mutex mtx;
|
||||
static std::condition_variable notify;
|
||||
static stop_type stop_requested{false};
|
||||
|
||||
static const auto quit_handler = [](int sig) {
|
||||
fmt::println("stop requested|{}", sig);
|
||||
stop_requested = true;
|
||||
|
||||
mutex_lock lock(mtx);
|
||||
notify.notify_all();
|
||||
};
|
||||
|
||||
std::signal(SIGINT, quit_handler);
|
||||
#if !defined(_WIN32)
|
||||
std::signal(SIGQUIT, quit_handler);
|
||||
#endif // !defined(_WIN32)
|
||||
std::signal(SIGTERM, quit_handler);
|
||||
|
||||
try {
|
||||
std::string cfg_file;
|
||||
auto cfg{load_config(cfg_file)};
|
||||
auto state_db{load_db()};
|
||||
|
||||
if (cfg.server_list.empty()) {
|
||||
utils::error::handle_error(function_name,
|
||||
"no servers have been configured");
|
||||
ret = 3;
|
||||
} else {
|
||||
while (not stop_requested) {
|
||||
std::for_each(std::execution::par, cfg.server_list.begin(),
|
||||
cfg.server_list.end(),
|
||||
[&state_db](const server_cfg &server) {
|
||||
if (stop_requested) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
check_server(server, state_db);
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
}
|
||||
});
|
||||
unique_mutex_lock lock(mtx);
|
||||
if (stop_requested) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fmt::println("waiting for next check|{}", cfg.check_interval);
|
||||
notify.wait_for(lock, cfg.check_interval);
|
||||
}
|
||||
}
|
||||
|
||||
cfg.save(cfg_file);
|
||||
state_db.close();
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
ret = 2;
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
ret = 2;
|
||||
}
|
||||
|
||||
fmt::println("terminating application|{}", ret);
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
ret = 2;
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
ret = 2;
|
||||
}
|
||||
|
||||
monitarr::project_cleanup();
|
||||
|
197
monitarr/monitarr/src/run_cmd.cpp
Normal file
197
monitarr/monitarr/src/run_cmd.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
#include <execution>
|
||||
|
||||
#include "run_cmd.hpp"
|
||||
|
||||
#include "actions.hpp"
|
||||
#include "data_db.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/config.hpp"
|
||||
#include "utils/error.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/unix.hpp"
|
||||
#include "utils/windows.hpp"
|
||||
|
||||
namespace {
|
||||
std::mutex mtx;
|
||||
std::condition_variable notify;
|
||||
monitarr::stop_type stop_requested{false};
|
||||
|
||||
void quit_handler(int sig) {
|
||||
MONITARR_USES_FUNCTION_NAME();
|
||||
|
||||
monitarr::utils::error::handle_info(function_name,
|
||||
fmt::format("stop requested|{}", sig));
|
||||
stop_requested = true;
|
||||
|
||||
monitarr::mutex_lock lock(mtx);
|
||||
notify.notify_all();
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace monitarr {
|
||||
static void check_server(const server_cfg &server, data_db &state_db) {
|
||||
MONITARR_USES_FUNCTION_NAME();
|
||||
|
||||
utils::error::handle_info(function_name, fmt::format("checking server|{}|{}",
|
||||
server.id, server.url));
|
||||
|
||||
auto cli = create_client(server);
|
||||
|
||||
std::uint16_t page{0U};
|
||||
while (++page != 0U) {
|
||||
httplib::Params params;
|
||||
params.emplace("page", std::to_string(page));
|
||||
params.emplace("pageSize", "100");
|
||||
|
||||
auto response =
|
||||
cli.Get(fmt::format("/api/{}/queue", server.api_version), params, {});
|
||||
if (response->status != httplib::StatusCode::OK_200) {
|
||||
utils::error::handle_error(
|
||||
function_name, fmt::format("check server request failed|{}|{}|{}",
|
||||
server.id, server.url, response->status));
|
||||
break;
|
||||
}
|
||||
|
||||
auto json_data = nlohmann::json::parse(response->body);
|
||||
if (json_data.at("page").get<std::uint32_t>() != page) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto now = utils::time::get_time_now();
|
||||
|
||||
for (const auto &record : json_data.at("records")) {
|
||||
auto download_id =
|
||||
fmt::format("{}/{}", server.id, record.at("id").get<std::uint64_t>());
|
||||
auto episode_id = record.contains("episodeId")
|
||||
? record["episodeId"].get<std::uint64_t>()
|
||||
: std::uint64_t{0U};
|
||||
auto movie_id = record.contains("movieId")
|
||||
? record["movieId"].get<std::uint64_t>()
|
||||
: std::uint64_t{0U};
|
||||
auto size_left = record.at("sizeleft").get<std::uint64_t>();
|
||||
auto title = record.at("title").get<std::string>();
|
||||
auto is_downloading = utils::string::contains(
|
||||
record.at("status").get<std::string>(), "downloading");
|
||||
|
||||
auto data = state_db.get(download_id);
|
||||
const auto update_entry = [&download_id, &now, &size_left, &state_db,
|
||||
&title, url = server.url]() {
|
||||
if (size_left == 0U) {
|
||||
state_db.remove(download_id);
|
||||
return;
|
||||
}
|
||||
|
||||
utils::error::handle_info(
|
||||
function_name, fmt::format("updating {}|{}|{}|{}", download_id,
|
||||
title, now, size_left));
|
||||
state_db.set(data_entry{
|
||||
download_id,
|
||||
now,
|
||||
size_left,
|
||||
});
|
||||
};
|
||||
|
||||
if (data.has_value()) {
|
||||
if (std::chrono::nanoseconds(now - data->last_check) >=
|
||||
server.timeout) {
|
||||
if (size_left == data->size_left) {
|
||||
remove_stalled(download_id, title, episode_id, movie_id, server,
|
||||
&state_db);
|
||||
} else if (size_left == 0U || not is_downloading) {
|
||||
state_db.remove(download_id);
|
||||
} else {
|
||||
update_entry();
|
||||
}
|
||||
} else if (size_left == 0U || not is_downloading) {
|
||||
state_db.remove(download_id);
|
||||
}
|
||||
} else if (is_downloading && size_left > 0U) {
|
||||
update_entry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto load_db() -> data_db {
|
||||
auto data_dir = utils::get_environment_variable("MONITARR_DATA_DIR");
|
||||
if (data_dir.empty()) {
|
||||
data_dir = utils::path::combine(".", {"data"});
|
||||
}
|
||||
|
||||
if (not utils::file::directory{data_dir}.create_directory()) {
|
||||
throw std::runtime_error(fmt::format("failed to create data dir|{}",
|
||||
data_dir,
|
||||
utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
data_db state_db{};
|
||||
state_db.open(data_dir);
|
||||
return state_db;
|
||||
}
|
||||
|
||||
auto run_cmd(const app_config &cfg, std::string_view cfg_file) -> int {
|
||||
MONITARR_USES_FUNCTION_NAME();
|
||||
auto ret{0};
|
||||
std::signal(SIGINT, quit_handler);
|
||||
#if !defined(_WIN32)
|
||||
std::signal(SIGQUIT, quit_handler);
|
||||
#endif // !defined(_WIN32)
|
||||
std::signal(SIGTERM, quit_handler);
|
||||
|
||||
try {
|
||||
if (cfg.server_list.empty()) {
|
||||
utils::error::handle_error(function_name,
|
||||
"no servers have been configured");
|
||||
ret = 3;
|
||||
} else {
|
||||
auto state_db{load_db()};
|
||||
|
||||
while (not stop_requested) {
|
||||
std::for_each(std::execution::par, cfg.server_list.begin(),
|
||||
cfg.server_list.end(),
|
||||
[&state_db](const server_cfg &server) {
|
||||
if (stop_requested) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
check_server(server, state_db);
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
}
|
||||
});
|
||||
unique_mutex_lock lock(mtx);
|
||||
if (stop_requested) {
|
||||
continue;
|
||||
}
|
||||
|
||||
utils::error::handle_error(
|
||||
function_name,
|
||||
fmt::format("waiting for next check|{}", cfg.check_interval));
|
||||
notify.wait_for(lock, cfg.check_interval);
|
||||
}
|
||||
|
||||
state_db.close();
|
||||
}
|
||||
|
||||
cfg.save(cfg_file);
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::handle_exception(function_name, ex);
|
||||
ret = 2;
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
ret = 2;
|
||||
}
|
||||
|
||||
utils::error::handle_info(function_name,
|
||||
fmt::format("exiting application|{}", ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // namespace monitarr
|
Loading…
x
Reference in New Issue
Block a user