208 lines
9.7 KiB
C++
208 lines
9.7 KiB
C++
#pragma once
|
|
#include <SQLiteCpp/Database.h>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <ctime>
|
|
#include <exception>
|
|
#include <filesystem>
|
|
#include <functional>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <psco/awaitable.hpp>
|
|
#include "Core/Base/JSON.h"
|
|
|
|
|
|
class Global;
|
|
|
|
struct External_Database_Row {
|
|
std::map<std::string, std::optional<std::string>> columns;
|
|
|
|
[[nodiscard]] std::optional<std::string> get(const std::string& column) const;
|
|
[[nodiscard]] Psc::JSON to_json() const;
|
|
};
|
|
|
|
struct External_Resource_Status {
|
|
std::string name;
|
|
std::size_t row_count{};
|
|
bool downloaded{};
|
|
bool imported{};
|
|
std::string message;
|
|
};
|
|
|
|
// 每个数据源模块只管理一张 SQLite 表。主键由数据源按业务含义选择:
|
|
// ICAO24、航班呼号、机场 ICAO 代码、机型代码或其他业务键。
|
|
class External_Resources {
|
|
public:
|
|
External_Resources(std::string name,
|
|
std::string cache_file_name,
|
|
std::string download_url,
|
|
std::string description,
|
|
std::uint64_t update_interval_seconds);
|
|
virtual ~External_Resources() = default;
|
|
|
|
|
|
|
|
[[nodiscard]] std::size_t row_count(SQLite::Database& db) const;
|
|
|
|
virtual void create_table(SQLite::Database& db) const = 0;
|
|
External_Resource_Status update(SQLite::Database& db,
|
|
const std::filesystem::path& cache_pos,
|
|
bool force_download,
|
|
bool only_when_empty);
|
|
External_Resource_Status import_offline(SQLite::Database& db,
|
|
const std::filesystem::path& source_file);
|
|
External_Resource_Status clear_table(SQLite::Database& db,
|
|
const std::filesystem::path& cache_pos);
|
|
[[nodiscard]] std::optional<External_Database_Row> query_one(
|
|
SQLite::Database& db,
|
|
const std::vector<std::string>& primary_key_values) const;
|
|
void init(const Psc::JSON* that_json)
|
|
{
|
|
Get_J(name)
|
|
Get_J(download_url)
|
|
Get_J(description)
|
|
Get_J(update_interval_seconds)
|
|
Get_J(last_updated_at)
|
|
}
|
|
[[nodiscard]] Psc::JSON to_json() const
|
|
{
|
|
Psc::JSON ret = Psc::JSON::object();
|
|
Ret_J(name)
|
|
Ret_J(download_url)
|
|
Ret_J(description)
|
|
Ret_J(update_interval_seconds)
|
|
Ret_J(last_updated_at)
|
|
return ret;
|
|
}
|
|
std::string name;
|
|
std::string cache_file_name;
|
|
std::string download_url;
|
|
std::string description;
|
|
std::uint64_t update_interval_seconds{};
|
|
std::time_t last_updated_at{};
|
|
protected:
|
|
[[nodiscard]] virtual std::filesystem::path source_file(
|
|
const std::filesystem::path& cache_pos) const;
|
|
virtual bool fetch(const std::filesystem::path& cache_pos,
|
|
bool force_download) const;
|
|
virtual std::size_t import_file(SQLite::Database& db,
|
|
const std::filesystem::path& source_file) const = 0;
|
|
[[nodiscard]] virtual const std::vector<std::string>& primary_key_columns() const = 0;
|
|
void mark_updated();
|
|
void clear_last_updated_at();
|
|
|
|
|
|
};
|
|
|
|
class External_Resources_Manager {
|
|
public:
|
|
using Status_Callback = std::function<void(std::exception_ptr, External_Resource_Status)>;
|
|
using Status_List_Callback = std::function<void(std::exception_ptr, std::vector<External_Resource_Status>)>;
|
|
using Row_Callback = std::function<void(std::exception_ptr, std::optional<External_Database_Row>)>;
|
|
using Row_Map_Callback = std::function<void(
|
|
std::exception_ptr,
|
|
std::map<std::string, std::shared_ptr<External_Database_Row>>)>;
|
|
|
|
External_Resources_Manager();
|
|
|
|
void init(const Psc::JSON* that_json);
|
|
[[nodiscard]] Psc::JSON to_json() const;
|
|
void server(Global* g);
|
|
void load_sqlite_db(std::string path);
|
|
std::vector<External_Resource_Status> refresh_external_databases(bool force_download = true);
|
|
External_Resource_Status refresh_external_database(const std::string& resource_name,
|
|
bool force_download = true);
|
|
External_Resource_Status import_external_database(
|
|
const std::string& resource_name,
|
|
const std::filesystem::path& source_file);
|
|
External_Resource_Status clear_external_database_table(const std::string& resource_name);
|
|
[[nodiscard]] std::optional<External_Database_Row> query_external_database(
|
|
const std::string& resource_name,
|
|
const std::vector<std::string>& primary_key_values) const;
|
|
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>>
|
|
query_aircraft_external_databases(const std::string& icao24) const;
|
|
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>>
|
|
query_callsign_external_databases(
|
|
const std::optional<std::string>& callsign) const;
|
|
[[nodiscard]] std::vector<External_Resource_Status> external_database_status() const;
|
|
|
|
void async_refresh_external_databases(bool force_download,
|
|
Status_List_Callback callback);
|
|
void async_refresh_external_database(std::string resource_name,
|
|
bool force_download,
|
|
Status_Callback callback);
|
|
void async_import_external_database(std::string resource_name,
|
|
std::filesystem::path source_file,
|
|
Status_Callback callback);
|
|
void async_clear_external_database_table(std::string resource_name,
|
|
Status_Callback callback);
|
|
void async_query_external_database(std::string resource_name,
|
|
std::vector<std::string> primary_key_values,
|
|
Row_Callback callback) const;
|
|
void async_query_aircraft_external_databases(std::string icao24,
|
|
Row_Map_Callback callback) const;
|
|
void async_query_callsign_external_databases(std::optional<std::string> callsign,
|
|
Row_Map_Callback callback) const;
|
|
void async_external_database_status(Status_List_Callback callback) const;
|
|
|
|
[[nodiscard]] psco::awaitable<std::vector<External_Resource_Status>>
|
|
refresh_external_databases_coro(bool force_download = true);
|
|
[[nodiscard]] psco::awaitable<External_Resource_Status>
|
|
refresh_external_database_coro(std::string resource_name,
|
|
bool force_download = true);
|
|
[[nodiscard]] psco::awaitable<External_Resource_Status>
|
|
import_external_database_coro(std::string resource_name,
|
|
std::filesystem::path source_file);
|
|
[[nodiscard]] psco::awaitable<External_Resource_Status>
|
|
clear_external_database_table_coro(std::string resource_name);
|
|
[[nodiscard]] psco::awaitable<std::optional<External_Database_Row>>
|
|
query_external_database_coro(std::string resource_name,
|
|
std::vector<std::string> primary_key_values) const;
|
|
[[nodiscard]] psco::awaitable<std::map<std::string, std::shared_ptr<External_Database_Row>>>
|
|
query_aircraft_external_databases_coro(std::string icao24) const;
|
|
[[nodiscard]] psco::awaitable<std::map<std::string, std::shared_ptr<External_Database_Row>>>
|
|
query_callsign_external_databases_coro(std::optional<std::string> callsign) const;
|
|
[[nodiscard]] psco::awaitable<std::vector<External_Resource_Status>>
|
|
external_database_status_coro() const;
|
|
|
|
void register_external_resource(std::unique_ptr<External_Resources> external_res);
|
|
void initialize(SQLite::Database& db, std::filesystem::path cache_pos);
|
|
std::vector<External_Resource_Status> sync_missing(SQLite::Database& db);
|
|
std::vector<External_Resource_Status> refresh_all(SQLite::Database& db,
|
|
bool force_download = true);
|
|
External_Resource_Status refresh_one(SQLite::Database& db,
|
|
const std::string& resource_name,
|
|
bool force_download = true);
|
|
External_Resource_Status import_offline(SQLite::Database& db,
|
|
const std::string& resource_name,
|
|
const std::filesystem::path& source_file);
|
|
External_Resource_Status clear_table(SQLite::Database& db,
|
|
const std::string& resource_name);
|
|
[[nodiscard]] std::optional<External_Database_Row> query_one(
|
|
SQLite::Database& db,
|
|
const std::string& resource_name,
|
|
const std::vector<std::string>& primary_key_values) const;
|
|
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>>
|
|
query_aircraft(SQLite::Database& db, const std::string& icao24) const;
|
|
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>>
|
|
query_callsign(SQLite::Database& db,
|
|
const std::optional<std::string>& callsign) const;
|
|
[[nodiscard]] std::vector<External_Resource_Status> status(SQLite::Database& db) const;
|
|
std::string ecap_sqlite_path;
|
|
|
|
std::filesystem::path cache_pos_;
|
|
private:
|
|
[[nodiscard]] SQLite::Database& require_db() const;
|
|
External_Resources& get_resource(const std::string& resource_name) const;
|
|
std::vector<External_Resource_Status> update_all(SQLite::Database& db,
|
|
bool force_download,
|
|
bool only_when_empty);
|
|
std::unique_ptr<SQLite::Database> db_;
|
|
std::vector<std::unique_ptr<External_Resources>> resources_;
|
|
mutable std::mutex mtx_;
|
|
};
|