This commit is contained in:
parent
1df434efba
commit
889faa4404
@ -1,7 +1,6 @@
|
||||
find_package(Wt REQUIRED Dbo)
|
||||
|
||||
add_library(Database
|
||||
Database.h Database.cpp
|
||||
Session.h Session.cpp
|
||||
Task.h
|
||||
User.h
|
||||
|
@ -1,234 +0,0 @@
|
||||
#include "Database.h"
|
||||
#include "BoostLog.h"
|
||||
#include "Session.h"
|
||||
#include <Wt/Dbo/FixedSqlConnectionPool.h>
|
||||
#include <Wt/Dbo/SqlConnectionPool.h>
|
||||
#include <Wt/Dbo/backend/Sqlite3.h>
|
||||
#include <sqlite3.h>
|
||||
#include <sstream>
|
||||
|
||||
std::unique_ptr<Session> Database::session() {
|
||||
if (!m_sqlConnectionPool) return {};
|
||||
return std::make_unique<Session>(*m_sqlConnectionPool);
|
||||
}
|
||||
|
||||
bool Database::open(const std::string &path) {
|
||||
try {
|
||||
auto connection = std::make_unique<Wt::Dbo::backend::Sqlite3>(path);
|
||||
connection->setProperty("show-queries", "true");
|
||||
connection->setDateTimeStorage(Wt::Dbo::SqlDateTimeType::DateTime,
|
||||
Wt::Dbo::backend::DateTimeStorage::PseudoISO8601AsText);
|
||||
m_sqlConnectionPool = std::make_unique<Wt::Dbo::FixedSqlConnectionPool>(std::move(connection), 10);
|
||||
session()->createTables();
|
||||
} catch (const Wt::Dbo::Exception &e) {
|
||||
LOG(error) << e.code() << ": " << e.what();
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
int result = sqlite3_open(path.c_str(), &m_sqlite3);
|
||||
if (result != SQLITE_OK) {
|
||||
ret = false;
|
||||
LOG(error) << "open database failed.";
|
||||
}
|
||||
initialize();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Database::updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent,
|
||||
int64_t time) {
|
||||
sqlite3_stmt *stmt;
|
||||
auto strippedUrl = url;
|
||||
if (strippedUrl.size() > 1 && strippedUrl.back() == '/') {
|
||||
strippedUrl.pop_back();
|
||||
}
|
||||
const char *query = "SELECT id, page_view_count FROM visit_analysis WHERE url = ? AND visitor_uuid = ?";
|
||||
if (sqlite3_prepare_v2(m_sqlite3, query, -1, &stmt, 0) != SQLITE_OK) {
|
||||
LOG(error) << "Failed to prepare statement: " << sqlite3_errmsg(m_sqlite3);
|
||||
}
|
||||
sqlite3_bind_text(stmt, 1, strippedUrl.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC);
|
||||
int id = -1;
|
||||
int page_view_count = 0;
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
id = sqlite3_column_int(stmt, 0);
|
||||
page_view_count = sqlite3_column_int(stmt, 1);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
if (id != -1) { // 更新记录
|
||||
const char *updateQuery =
|
||||
"UPDATE visit_analysis SET last_user_agent = ?, last_view_time = ?, page_view_count = ? WHERE id = ?";
|
||||
if (sqlite3_prepare_v2(m_sqlite3, updateQuery, -1, &stmt, 0) != SQLITE_OK) {
|
||||
LOG(error) << "Failed to prepare update statement: " << sqlite3_errmsg(m_sqlite3);
|
||||
}
|
||||
sqlite3_bind_text(stmt, 1, userAgent.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_int64(stmt, 2, time);
|
||||
sqlite3_bind_int(stmt, 3, page_view_count + 1);
|
||||
sqlite3_bind_int(stmt, 4, id);
|
||||
if (sqlite3_step(stmt) != SQLITE_DONE) {
|
||||
LOG(error) << "Failed to update record: " << sqlite3_errmsg(m_sqlite3);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
} else { // 插入新记录
|
||||
const char *insertQuery = "INSERT INTO visit_analysis (url, visitor_uuid, last_user_agent, last_view_time, "
|
||||
"page_view_count) VALUES (?, ?, ?, ?, 1)";
|
||||
if (sqlite3_prepare_v2(m_sqlite3, insertQuery, -1, &stmt, 0) != SQLITE_OK) {
|
||||
LOG(error) << "Failed to prepare insert statement: " << sqlite3_errmsg(m_sqlite3);
|
||||
}
|
||||
sqlite3_bind_text(stmt, 1, strippedUrl.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 3, userAgent.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_int64(stmt, 4, time);
|
||||
if (sqlite3_step(stmt) != SQLITE_DONE) {
|
||||
LOG(error) << "Failed to insert record: " << sqlite3_errmsg(m_sqlite3) << std::endl;
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
void Database::clearVisitRecord() {
|
||||
char *message = nullptr;
|
||||
constexpr auto sql = "DELETE FROM visit_analysis";
|
||||
int rc = sqlite3_exec(m_sqlite3, sql, nullptr, nullptr, &message);
|
||||
if (rc != SQLITE_OK) {
|
||||
LOG(error) << "SQL error: " << message;
|
||||
sqlite3_free(message);
|
||||
}
|
||||
}
|
||||
|
||||
VisitAnalysis Database::siteVisitAnalysisData() {
|
||||
VisitAnalysis ret;
|
||||
sqlite3_stmt *stmt = nullptr;
|
||||
const char *sql = "SELECT COUNT(DISTINCT visitor_uuid) as unique_visitors, SUM(page_view_count) as "
|
||||
"total_page_views FROM visit_analysis";
|
||||
if (sqlite3_prepare_v2(m_sqlite3, sql, -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG(error) << "Failed to prepare statement: " << sqlite3_errmsg(m_sqlite3);
|
||||
return ret;
|
||||
}
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
ret.uniqueVisitorCount = sqlite3_column_int(stmt, 0);
|
||||
ret.pageViewCount = sqlite3_column_int(stmt, 1);
|
||||
} else {
|
||||
LOG(error) << "Failed to execute query: " << sqlite3_errmsg(m_sqlite3);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::vector<std::string> urlFilter = {
|
||||
"/",
|
||||
"/search",
|
||||
"/LoginPage",
|
||||
"/MessageBoard",
|
||||
"/我的笔记",
|
||||
"/我的博客",
|
||||
};
|
||||
|
||||
std::list<VisitAnalysis> Database::mostViewedUrls(int size) {
|
||||
const char *sql = "SELECT url, SUM(page_view_count) AS total_page_view_count "
|
||||
"FROM visit_analysis "
|
||||
"GROUP BY url "
|
||||
"ORDER BY total_page_view_count DESC "
|
||||
"LIMIT ?";
|
||||
sqlite3_stmt *stmt = nullptr;
|
||||
std::list<VisitAnalysis> ret;
|
||||
auto rc = sqlite3_prepare_v2(m_sqlite3, sql, -1, &stmt, nullptr);
|
||||
if (rc != SQLITE_OK) {
|
||||
LOG(error) << "Failed to prepare statement: " << sqlite3_errmsg(m_sqlite3);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sqlite3_bind_int(stmt, 1, size + urlFilter.size());
|
||||
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
|
||||
VisitAnalysis pv;
|
||||
pv.url = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0));
|
||||
if (std::find(urlFilter.cbegin(), urlFilter.cend(), pv.url) != urlFilter.cend()) continue;
|
||||
pv.pageViewCount = sqlite3_column_int(stmt, 1);
|
||||
if (ret.size() < size) {
|
||||
ret.push_back(pv);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != SQLITE_DONE) {
|
||||
LOG(error) << "Failed to execute statement: " << sqlite3_errmsg(m_sqlite3);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::list<VisitAnalysis> Database::latestViewedUrls(int size) {
|
||||
std::list<VisitAnalysis> ret;
|
||||
sqlite3_stmt *stmt;
|
||||
const char *sql = R"(
|
||||
SELECT url, MAX(last_view_time) as last_view_time
|
||||
FROM visit_analysis
|
||||
GROUP BY url
|
||||
ORDER BY last_view_time DESC
|
||||
LIMIT ?
|
||||
)";
|
||||
|
||||
if (sqlite3_prepare_v2(m_sqlite3, sql, -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG(error) << "Failed to prepare statement: " << sqlite3_errmsg(m_sqlite3);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sqlite3_bind_int(stmt, 1, size + urlFilter.size()) != SQLITE_OK) {
|
||||
LOG(error) << "Failed to bind parameter: " << sqlite3_errmsg(m_sqlite3);
|
||||
sqlite3_finalize(stmt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
VisitAnalysis visit;
|
||||
visit.url = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0));
|
||||
if (std::find(urlFilter.cbegin(), urlFilter.cend(), visit.url) != urlFilter.cend()) continue;
|
||||
visit.lastViewTime = sqlite3_column_int64(stmt, 1);
|
||||
if (ret.size() < size) {
|
||||
ret.push_back(visit);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
VisitAnalysis Database::visitAnalysisData(const std::string &url) {
|
||||
VisitAnalysis ret;
|
||||
sqlite3_stmt *stmt;
|
||||
std::string query =
|
||||
"SELECT SUM(page_view_count), COUNT(DISTINCT visitor_uuid) FROM visit_analysis WHERE url = '" + url + "';";
|
||||
if (sqlite3_prepare_v2(m_sqlite3, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) {
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
ret.pageViewCount = sqlite3_column_int(stmt, 0);
|
||||
ret.uniqueVisitorCount = sqlite3_column_int(stmt, 1);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
} else {
|
||||
LOG(error) << "Failed to execute query: " << sqlite3_errmsg(m_sqlite3);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Database::initialize() {
|
||||
char *message = nullptr;
|
||||
auto sql = R"(
|
||||
CREATE TABLE IF NOT EXISTS visit_analysis (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
url TEXT NOT NULL,
|
||||
visitor_uuid TEXT NOT NULL,
|
||||
last_user_agent TEXT NOT NULL,
|
||||
last_view_time INTEGER NOT NULL,
|
||||
page_view_count INTEGER NOT NULL
|
||||
);
|
||||
)";
|
||||
int result = sqlite3_exec(m_sqlite3, sql, 0, 0, &message);
|
||||
if (result != SQLITE_OK) {
|
||||
LOG(error) << "Failed to create table: " << message << std::endl;
|
||||
sqlite3_free(message);
|
||||
}
|
||||
}
|
||||
|
||||
Database::~Database() {
|
||||
if (m_sqlite3 != nullptr) {
|
||||
sqlite3_close(m_sqlite3);
|
||||
m_sqlite3 = nullptr;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
#ifndef __DATABASE_H__
|
||||
#define __DATABASE_H__
|
||||
|
||||
#include "HomeBox.h"
|
||||
#include "Singleton.h"
|
||||
#include "Task.h"
|
||||
#include <string>
|
||||
|
||||
namespace Wt {
|
||||
namespace Dbo {
|
||||
class SqlConnectionPool;
|
||||
}
|
||||
} // namespace Wt
|
||||
|
||||
class VisitAnalysis {
|
||||
public:
|
||||
std::string url;
|
||||
int pageViewCount = 0;
|
||||
int uniqueVisitorCount = 0;
|
||||
int lastViewTime = 0;
|
||||
};
|
||||
|
||||
struct sqlite3;
|
||||
class Session;
|
||||
|
||||
class Database {
|
||||
friend class Amass::Singleton<Database>;
|
||||
|
||||
public:
|
||||
~Database();
|
||||
std::unique_ptr<Session> session();
|
||||
bool open(const std::string &path);
|
||||
|
||||
void updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent, int64_t time);
|
||||
void clearVisitRecord();
|
||||
VisitAnalysis visitAnalysisData(const std::string &url);
|
||||
VisitAnalysis siteVisitAnalysisData();
|
||||
std::list<VisitAnalysis> mostViewedUrls(int size);
|
||||
std::list<VisitAnalysis> latestViewedUrls(int size);
|
||||
|
||||
protected:
|
||||
void initialize();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Wt::Dbo::SqlConnectionPool> m_sqlConnectionPool;
|
||||
sqlite3 *m_sqlite3 = nullptr;
|
||||
};
|
||||
|
||||
#endif // __DATABASE_H__
|
@ -1,6 +1,32 @@
|
||||
#include "Session.h"
|
||||
#include "BoostLog.h"
|
||||
#include <Wt/Auth/Dbo/UserDatabase.h>
|
||||
#include <Wt/Dbo/WtJsonSqlTraits.h>
|
||||
#include <Wt/Dbo/backend/Sqlite3.h>
|
||||
#include <Wt/Dbo/FixedSqlConnectionPool.h>
|
||||
#include <Wt/Dbo/SqlConnectionPool.h>
|
||||
|
||||
namespace Database {
|
||||
std::unique_ptr<Wt::Dbo::SqlConnectionPool> sqlConnectionPool;
|
||||
bool initialize(const std::string &path) {
|
||||
try {
|
||||
auto connection = std::make_unique<Wt::Dbo::backend::Sqlite3>(path);
|
||||
connection->setProperty("show-queries", "true");
|
||||
connection->setDateTimeStorage(Wt::Dbo::SqlDateTimeType::DateTime,
|
||||
Wt::Dbo::backend::DateTimeStorage::PseudoISO8601AsText);
|
||||
sqlConnectionPool = std::make_unique<Wt::Dbo::FixedSqlConnectionPool>(std::move(connection), 10);
|
||||
session()->createTables();
|
||||
} catch (const Wt::Dbo::Exception &e) {
|
||||
LOG(error) << e.code() << ": " << e.what();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Session> session() {
|
||||
if (!sqlConnectionPool) return {};
|
||||
return std::make_unique<Session>(*sqlConnectionPool);
|
||||
}
|
||||
} // namespace Database
|
||||
|
||||
Session::Session(Wt::Dbo::SqlConnectionPool &connectionPool) {
|
||||
setConnectionPool(connectionPool);
|
||||
|
@ -4,9 +4,9 @@
|
||||
#include "HomeBox.h"
|
||||
#include "Task.h"
|
||||
#include "User.h"
|
||||
#include "VisitorRecord.h"
|
||||
#include <Wt/Auth/Login.h>
|
||||
#include <Wt/Dbo/Session.h>
|
||||
#include "VisitorRecord.h"
|
||||
|
||||
using UserDatabase = Wt::Auth::Dbo::UserDatabase<AuthInfo>;
|
||||
|
||||
@ -23,4 +23,9 @@ private:
|
||||
Wt::Auth::Login m_login;
|
||||
};
|
||||
|
||||
namespace Database {
|
||||
bool initialize(const std::string &path);
|
||||
std::unique_ptr<Session> session();
|
||||
} // namespace Database
|
||||
|
||||
#endif // __SESSION_H__
|
@ -1,5 +1,4 @@
|
||||
#include "Application.h"
|
||||
#include "Database/Database.h"
|
||||
#include "Database/Session.h"
|
||||
#include "DateTime.h"
|
||||
#include "HttpSession.h"
|
||||
@ -62,7 +61,7 @@ Application::Application(const std::string &path)
|
||||
|
||||
m_router->insert("/api/v1/tasklist", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||
using namespace boost::beast;
|
||||
auto database = Amass::Singleton<Database>::instance()->session();
|
||||
auto database = Database::session();
|
||||
Tasks tasks = database->find<Task>();
|
||||
std::ostringstream oss;
|
||||
Wt::Dbo::jsonSerialize(tasks, oss);
|
||||
@ -87,7 +86,7 @@ Application::Application(const std::string &path)
|
||||
if (root.contains("content")) {
|
||||
content = root.at("content").as_string();
|
||||
}
|
||||
auto database = Amass::Singleton<Database>::instance()->session();
|
||||
auto database = Database::session();;
|
||||
auto task = std::make_unique<Task>();
|
||||
task->createTime = system_clock::time_point(seconds(root.at("createTime").as_int64()));
|
||||
task->content = content;
|
||||
@ -111,7 +110,7 @@ Application::Application(const std::string &path)
|
||||
m_router->insert("/api/v1/task/delete/{id}", [this](HttpSession &session, const Request &request,const boost::urls::matches &matches) {
|
||||
using namespace boost::beast;
|
||||
LOG(info) << "delete task: " << matches.at("id");
|
||||
auto database = Amass::Singleton<Database>::instance()->session();
|
||||
auto database = Database::session();;
|
||||
Wt::Dbo::ptr<Task> joe = database->find<Task>().where("id = ?").bind(std::stoi(matches.at("id")));
|
||||
int status = -1;
|
||||
if (joe) {
|
||||
@ -140,7 +139,7 @@ Application::Application(const std::string &path)
|
||||
session.reply(
|
||||
ServiceLogic::make_200<boost::beast::http::string_body>(request, "notify successed.\n", "text/html"));
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
m_router->insert("/api/v1/visit_analysis", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||
using namespace boost::beast;
|
||||
auto rootJson = boost::json::parse(request.body());
|
||||
@ -149,28 +148,27 @@ Application::Application(const std::string &path)
|
||||
if (root.contains("url")) {
|
||||
url = root["url"].as_string();
|
||||
}
|
||||
auto database = Amass::Singleton<Database>::instance();
|
||||
auto database = Database::session();
|
||||
if (std::filesystem::exists("amass_blog" + url) && url.find("/我的博客/page") != 0) {
|
||||
std::string visitorUuid;
|
||||
Wt::Dbo::Transaction transaction(*database);
|
||||
auto record = std::make_unique<VisitorRecord>();
|
||||
record->time = std::chrono::system_clock::now();
|
||||
record->url = url;
|
||||
if (root.contains("visitor_uuid")) {
|
||||
visitorUuid = root["visitor_uuid"].as_string();
|
||||
record->visitorUuid = root["visitor_uuid"].as_string();
|
||||
}
|
||||
std::string userAgent;
|
||||
if (root.contains("user_agent")) {
|
||||
userAgent = root["user_agent"].as_string();
|
||||
record->userAgent = root["user_agent"].as_string();
|
||||
}
|
||||
auto now = std::chrono::system_clock::now();
|
||||
std::time_t now_time = std::chrono::system_clock::to_time_t(now);
|
||||
database->updateVisitCount(url, visitorUuid, userAgent, now_time);
|
||||
database->add(std::move(record));
|
||||
}
|
||||
auto data = database->visitAnalysisData(std::string(url));
|
||||
auto total = database->siteVisitAnalysisData();
|
||||
|
||||
boost::json::object reply;
|
||||
reply["page_view_count"] = data.pageViewCount;
|
||||
reply["unique_visitor_count"] = data.uniqueVisitorCount;
|
||||
reply["site_page_view_count"] = total.pageViewCount;
|
||||
reply["site_unique_visitor_count"] = total.uniqueVisitorCount;
|
||||
reply["page_view_count"] = database->query<int>("SELECT COUNT(*) FROM visitor_record WHERE url = ?").bind(std::string(url));
|
||||
reply["unique_visitor_count"] = database->query<int>("SELECT COUNT(DISTINCT visitor_uuid) FROM visitor_record WHERE url = ?").bind(std::string(url));
|
||||
reply["site_page_view_count"] = database->query<int>("SELECT COUNT(*) FROM visitor_record");
|
||||
reply["site_unique_visitor_count"] = database->query<int>("SELECT COUNT(DISTINCT visitor_uuid) FROM visitor_record");
|
||||
|
||||
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
||||
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
@ -196,13 +194,13 @@ Application::Application(const std::string &path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto data = Amass::Singleton<Database>::instance()->mostViewedUrls(size);
|
||||
auto database = Database::session();
|
||||
Wt::Dbo::collection<std::tuple<std::string, int>> query = database->query<std::tuple<std::string, int>>("SELECT url, COUNT(*) as count FROM visitor_record GROUP BY url ORDER BY count DESC LIMIT ?").bind(size);
|
||||
boost::json::array reply;
|
||||
for (auto &d : data) {
|
||||
for (auto &[url, count] : query) {
|
||||
boost::json::object object;
|
||||
object["url"] = d.url;
|
||||
object["count"] = d.pageViewCount;
|
||||
object["url"] = url;
|
||||
object["count"] = count;
|
||||
reply.push_back(std::move(object));
|
||||
}
|
||||
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
||||
@ -216,6 +214,7 @@ Application::Application(const std::string &path)
|
||||
|
||||
m_router->insert("/api/v1/latest_viewed_urls", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||
using namespace boost::beast;
|
||||
using namespace std::chrono;
|
||||
int size = 5;
|
||||
std::error_code error;
|
||||
if (!request.body().empty()) {
|
||||
@ -229,13 +228,14 @@ Application::Application(const std::string &path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto data = Amass::Singleton<Database>::instance()->latestViewedUrls(size);
|
||||
auto database = Database::session();
|
||||
using Reslut = std::tuple<std::string, system_clock::time_point>;
|
||||
Wt::Dbo::collection<Reslut> query = database->query<Reslut>("SELECT url, MAX(time) FROM visitor_record GROUP BY url ORDER BY MAX(time) DESC LIMIT ?").bind(size);
|
||||
boost::json::array reply;
|
||||
for (auto &d : data) {
|
||||
for (auto &[url, time] : query) {
|
||||
boost::json::object object;
|
||||
object["url"] = d.url;
|
||||
object["time"] = d.lastViewTime;
|
||||
object["url"] = url;
|
||||
object["time"] = duration_cast<seconds>(time.time_since_epoch()).count();
|
||||
reply.push_back(std::move(object));
|
||||
}
|
||||
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
||||
@ -246,7 +246,7 @@ Application::Application(const std::string &path)
|
||||
s.prepare_payload();
|
||||
session.reply(std::move(s));
|
||||
});
|
||||
|
||||
// clang-format on
|
||||
m_ioContext = Amass::Singleton<IoContext>::instance<Amass::Construct>(getThreads());
|
||||
m_timer = std::make_shared<boost::asio::system_timer>(*m_ioContext->ioContext());
|
||||
|
||||
@ -303,7 +303,7 @@ void Application::alarmTask() {
|
||||
LOG(error) << error.message();
|
||||
return;
|
||||
}
|
||||
auto session = Amass::Singleton<Database>::instance()->session();
|
||||
auto session = Database::session();
|
||||
Tasks tasks = session->find<Task>();
|
||||
bool founded = false;
|
||||
std::string content;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "Application.h"
|
||||
#include "BoostLog.h"
|
||||
#include "Database/Database.h"
|
||||
#include "Database/Session.h"
|
||||
#include "IoContext.h"
|
||||
#include "Listener.h"
|
||||
#include "Live2dBackend.h"
|
||||
@ -11,7 +11,6 @@
|
||||
#include "WeChatContext/CorporationContext.h"
|
||||
#include "WeChatContext/WeChatContext.h"
|
||||
#include "WebApplication.h"
|
||||
#include <Wt/Dbo/SqlConnectionPool.h>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
@ -60,15 +59,12 @@ int main(int argc, char const *argv[]) {
|
||||
}
|
||||
|
||||
auto application = Singleton<Application>::instance<Construct>("settings.ini");
|
||||
|
||||
auto database = Singleton<Database>::instance<Construct>();
|
||||
|
||||
if (!std::filesystem::exists(application->getDocumentRoot())) {
|
||||
LOG(fatal) << "document root: " << application->getDocumentRoot() << " is not exists...";
|
||||
std::exit(102);
|
||||
}
|
||||
BOOST_ASSERT_MSG(!application->getServer().empty(), "server.empty() == true");
|
||||
database->open(std::format("{}/database.sqlite", application->getDocumentRoot()));
|
||||
Database::initialize(std::format("{}/database.sqlite", application->getDocumentRoot()));
|
||||
auto address = boost::asio::ip::make_address(application->getServer());
|
||||
auto listener =
|
||||
std::make_shared<Listener>(application->ioContext(), boost::asio::ip::tcp::endpoint{address, application->getPort()});
|
||||
|
@ -9,6 +9,7 @@ add_executable(UnitTest main.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(UnitTest
|
||||
PRIVATE BOOST_TEST_NO_MAIN
|
||||
PUBLIC LOG_FILTER_LEVEL=1
|
||||
)
|
||||
|
||||
|
@ -1,22 +1,13 @@
|
||||
#include "Database/Database.h"
|
||||
#include "BoostLog.h"
|
||||
#include "Database/Session.h"
|
||||
#include <Wt/Dbo/SqlConnectionPool.h>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
static constexpr auto path = "build/database.sqlite";
|
||||
using namespace std::chrono;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DatabaseTest) {
|
||||
if (std::filesystem::exists(path)) {
|
||||
std::filesystem::remove(path);
|
||||
}
|
||||
Database database;
|
||||
database.open(path);
|
||||
// BOOST_TEST(database.open(path));
|
||||
|
||||
auto session = database.session();
|
||||
BOOST_AUTO_TEST_CASE(DatabaseTest) {
|
||||
auto session = Database::session();
|
||||
|
||||
Wt::Dbo ::Transaction transaction(*session);
|
||||
|
||||
@ -70,12 +61,23 @@ BOOST_AUTO_TEST_CASE(DatabaseTest) {
|
||||
|
||||
auto d = session->add(std::move(item));
|
||||
}
|
||||
|
||||
auto now = std::chrono::system_clock::now();
|
||||
std::time_t now_time = std::chrono::system_clock::to_time_t(now);
|
||||
|
||||
database.updateVisitCount("/note", "uuid_123", "chrome", now_time);
|
||||
database.updateVisitCount("/note/1", "uuid_1232", "chrome", now_time);
|
||||
database.updateVisitCount("/note", "uuid_123", "chrome", now_time);
|
||||
database.updateVisitCount("/note", "uuid_1234", "chrome", now_time);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(VisitorRecordTest) {
|
||||
// database.updateVisitCount("/note", "uuid_123", "chrome", now_time);
|
||||
// database.updateVisitCount("/note/1", "uuid_1232", "chrome", now_time);
|
||||
// database.updateVisitCount("/note", "uuid_123", "chrome", now_time);
|
||||
// database.updateVisitCount("/note", "uuid_1234", "chrome", now_time);
|
||||
auto session = Database::session();
|
||||
{
|
||||
Wt::Dbo ::Transaction transaction(*session);
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto record = std::make_unique<VisitorRecord>();
|
||||
record->time = now;
|
||||
record->url = "/note";
|
||||
record->userAgent = "chrome";
|
||||
record->visitorUuid = "uuid_123";
|
||||
|
||||
auto d = session->add(std::move(record));
|
||||
}
|
||||
}
|
@ -1,2 +1,16 @@
|
||||
#define BOOST_TEST_MODULE OlderTest
|
||||
#include "boost/test/included/unit_test.hpp"
|
||||
#include <filesystem>
|
||||
#include "Database/Session.h"
|
||||
|
||||
constexpr auto databasePath = "build/database.sqlite";
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (std::filesystem::exists(databasePath)) {
|
||||
std::filesystem::remove(databasePath);
|
||||
}
|
||||
Database::initialize(databasePath);
|
||||
extern ::boost::unit_test::test_suite *init_unit_test_suite(int argc, char *argv[]);
|
||||
boost::unit_test::init_unit_test_func init_func = &init_unit_test_suite;
|
||||
return ::boost::unit_test::unit_test_main(init_func, argc, argv);
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
#include "Hello.h"
|
||||
#include "BoostLog.h"
|
||||
#include "Database/Database.h"
|
||||
#include "Database/Session.h"
|
||||
#include "Dialog.h"
|
||||
#include "LoginWidget.h"
|
||||
@ -19,7 +18,7 @@ Hello::Hello(const Wt::WEnvironment &env, bool embedded) : Wt::WApplication(env)
|
||||
messageResourceBundle().use(appRoot() + "auth_css_theme");
|
||||
useStyleSheet("/resources/app.css");
|
||||
LOG(info) << "app root: " << appRoot();
|
||||
m_session = Amass::Singleton<Database>::instance()->session();
|
||||
m_session = Database::session();
|
||||
m_session->login().changed().connect(this, &Hello::authEvent);
|
||||
setTitle("Hello world");
|
||||
if (!embedded) {
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "Restful.h"
|
||||
#include "Database/Database.h"
|
||||
#include "Database/Session.h"
|
||||
#include <Wt/Dbo/Impl.h>
|
||||
#include <Wt/Dbo/Json.h>
|
||||
@ -11,7 +10,7 @@ DBO_INSTANTIATE_TEMPLATES(MyMessage)
|
||||
DbStruct *m_dbStruct;
|
||||
|
||||
void AuthenticationResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) {
|
||||
auto session = Amass::Singleton<Database>::instance()->session();
|
||||
auto session = Database::session();
|
||||
response.setMimeType("application/json");
|
||||
response.addHeader("Server", "Wt");
|
||||
|
||||
|
@ -144,8 +144,3 @@ function main() {
|
||||
}
|
||||
|
||||
main $@
|
||||
|
||||
# curl -k --insecure https://127.0.0.1/lua
|
||||
# openresty -p Server
|
||||
# sudo openresty -p Server -s reload
|
||||
# export LD_LIBRARY_PATH=/opt/Libraries/boost_1_85_0/lib:$LD_LIBRARY_PATH
|
Loading…
Reference in New Issue
Block a user