add task operation.
This commit is contained in:
parent
9820550844
commit
61858c438d
@ -1,17 +1,6 @@
|
|||||||
find_package(Boost COMPONENTS program_options json REQUIRED)
|
find_package(Boost COMPONENTS program_options json REQUIRED)
|
||||||
|
|
||||||
add_library(Database
|
add_subdirectory(Database)
|
||||||
Database.h Database.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(Database
|
|
||||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(Database
|
|
||||||
PUBLIC sqlite3
|
|
||||||
PUBLIC Universal
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(Server main.cpp
|
add_executable(Server main.cpp
|
||||||
HttpSession.h HttpSession.cpp
|
HttpSession.h HttpSession.cpp
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
#include "Database.h"
|
|
||||||
#include "BoostLog.h"
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
bool Database::open(const std::string &path) {
|
|
||||||
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::addTask(uint64_t createTime, const std::string &content, bool finished) {
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "INSERT INTO tasks (create_time,content,finished) VALUES (" << createTime << ",\"" << content << "\","
|
|
||||||
<< finished << ");";
|
|
||||||
auto sql = oss.str();
|
|
||||||
int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, NULL);
|
|
||||||
if (result != SQLITE_OK) {
|
|
||||||
LOG(error) << "add task failed: " << sqlite3_errmsg(m_sqlite3) << ", sql: " << sql;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Database::setTaskFinished(int id, bool finished, uint64_t finishedTime) {
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "UPDATE tasks SET finished = " << finished << ", finished_time = " << finishedTime << " WHERE id = " << id;
|
|
||||||
auto sql = oss.str();
|
|
||||||
int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, NULL);
|
|
||||||
if (result != SQLITE_OK) {
|
|
||||||
LOG(error) << "add task failed: " << sqlite3_errmsg(m_sqlite3) << ", sql: " << sql;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Database::initialize() {
|
|
||||||
const char *sql =
|
|
||||||
"CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY AUTOINCREMENT, create_time INTEGER NOT NULL, "
|
|
||||||
"parent_id INTEGER, content VARCHAR(512) NOT NULL, finished BOLL, finished_time INTEGER);";
|
|
||||||
int result = sqlite3_exec(m_sqlite3, sql, NULL, NULL, NULL);
|
|
||||||
if (result != SQLITE_OK) {
|
|
||||||
LOG(error) << "Failed to create table: " << sqlite3_errmsg(m_sqlite3);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Database::~Database() {
|
|
||||||
if (m_sqlite3 != nullptr) {
|
|
||||||
sqlite3_close(m_sqlite3);
|
|
||||||
m_sqlite3 = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
13
Server/Database/CMakeLists.txt
Normal file
13
Server/Database/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
add_library(Database
|
||||||
|
Database.h Database.cpp
|
||||||
|
Task.h Task.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(Database
|
||||||
|
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(Database
|
||||||
|
PUBLIC sqlite3
|
||||||
|
PUBLIC Universal
|
||||||
|
)
|
107
Server/Database/Database.cpp
Normal file
107
Server/Database/Database.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "Database.h"
|
||||||
|
#include "BoostLog.h"
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
bool Database::open(const std::string &path) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int selectTaskCallback(void *data, int argc, char **argv, char **columnName) {
|
||||||
|
auto tasks = reinterpret_cast<Tasks *>(data);
|
||||||
|
Task task;
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (argv[i] == nullptr) continue;
|
||||||
|
if (strcmp(columnName[i], "id") == 0) {
|
||||||
|
task.id = std::atol(argv[i]);
|
||||||
|
} else if (strcmp(columnName[i], "create_time") == 0) {
|
||||||
|
task.createTime = std::atol(argv[i]);
|
||||||
|
} else if (strcmp(columnName[i], "content") == 0) {
|
||||||
|
task.content = argv[i];
|
||||||
|
} else if (strcmp(columnName[i], "comment") == 0) {
|
||||||
|
task.comment = argv[i];
|
||||||
|
} else if (strcmp(columnName[i], "finished") == 0) {
|
||||||
|
task.finished = std::atol(argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks->push_back(task);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tasks Database::tasks() {
|
||||||
|
Tasks ret;
|
||||||
|
char *error = nullptr;
|
||||||
|
if (sqlite3_exec(m_sqlite3, "select * from tasks", selectTaskCallback, &ret, &error) != SQLITE_OK) {
|
||||||
|
LOG(error) << "sqlite3_exec() failed: " << error << std::endl;
|
||||||
|
sqlite3_free(error);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Database::addTask(uint64_t createTime, const std::string &content, const std::string &comment, bool finished) {
|
||||||
|
bool ret = true;
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "INSERT INTO tasks (create_time,content,comment,finished) VALUES (" << createTime << ",\"" << content
|
||||||
|
<< "\",\"" << comment << "\"," << finished << ");";
|
||||||
|
auto sql = oss.str();
|
||||||
|
char *error = nullptr;
|
||||||
|
int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error);
|
||||||
|
if (result != SQLITE_OK) {
|
||||||
|
LOG(error) << "add task failed: " << error << ", sql: " << sql;
|
||||||
|
sqlite3_free(error);
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Database::removeTask(int id) {
|
||||||
|
bool ret = true;
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "DELETE FROM tasks WHERE id = " << id << ";";
|
||||||
|
auto sql = oss.str();
|
||||||
|
char *error = nullptr;
|
||||||
|
int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error);
|
||||||
|
if (result != SQLITE_OK) {
|
||||||
|
LOG(error) << "add task failed: " << error << ", sql: " << sql;
|
||||||
|
sqlite3_free(error);
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::setTaskFinished(int id, bool finished, uint64_t finishedTime) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "UPDATE tasks SET finished = " << finished << ", finished_time = " << finishedTime << " WHERE id = " << id;
|
||||||
|
auto sql = oss.str();
|
||||||
|
int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, NULL);
|
||||||
|
if (result != SQLITE_OK) {
|
||||||
|
LOG(error) << "add task failed: " << sqlite3_errmsg(m_sqlite3) << ", sql: " << sql;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::initialize() {
|
||||||
|
const char *sql =
|
||||||
|
"CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY AUTOINCREMENT, create_time INTEGER NOT NULL, "
|
||||||
|
"parent_id INTEGER, content VARCHAR(512) NOT NULL, comment VARCHAR(512) NOT NULL, finished BOLL, finished_time "
|
||||||
|
"INTEGER);";
|
||||||
|
int result = sqlite3_exec(m_sqlite3, sql, NULL, NULL, NULL);
|
||||||
|
if (result != SQLITE_OK) {
|
||||||
|
LOG(error) << "Failed to create table: " << sqlite3_errmsg(m_sqlite3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Database::~Database() {
|
||||||
|
if (m_sqlite3 != nullptr) {
|
||||||
|
sqlite3_close(m_sqlite3);
|
||||||
|
m_sqlite3 = nullptr;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
#define __DATABASE_H__
|
#define __DATABASE_H__
|
||||||
|
|
||||||
#include "Singleton.h"
|
#include "Singleton.h"
|
||||||
|
#include "Task.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct sqlite3;
|
struct sqlite3;
|
||||||
@ -12,7 +13,10 @@ class Database {
|
|||||||
public:
|
public:
|
||||||
~Database();
|
~Database();
|
||||||
bool open(const std::string &path);
|
bool open(const std::string &path);
|
||||||
void addTask(uint64_t createTime, const std::string &content, bool finished = false);
|
Tasks tasks();
|
||||||
|
bool addTask(uint64_t createTime, const std::string &content, const std::string &comment = "",
|
||||||
|
bool finished = false);
|
||||||
|
bool removeTask(int id);
|
||||||
void setTaskFinished(int id, bool finished, uint64_t finishedTime);
|
void setTaskFinished(int id, bool finished, uint64_t finishedTime);
|
||||||
|
|
||||||
protected:
|
protected:
|
22
Server/Database/Task.cpp
Normal file
22
Server/Database/Task.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "Task.h"
|
||||||
|
#include <boost/json/array.hpp>
|
||||||
|
#include <boost/json/object.hpp>
|
||||||
|
#include <boost/json/serialize.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace json {
|
||||||
|
std::string serialize(const Tasks &tasks) {
|
||||||
|
boost::json::array ret;
|
||||||
|
for (auto &task : tasks) {
|
||||||
|
boost::json::object t;
|
||||||
|
t["id"] = task.id;
|
||||||
|
t["finished"] = task.finished;
|
||||||
|
t["createTime"] = task.createTime;
|
||||||
|
t["content"] = task.content;
|
||||||
|
t["comment"] = task.comment;
|
||||||
|
ret.push_back(std::move(t));
|
||||||
|
}
|
||||||
|
return boost::json::serialize(ret);
|
||||||
|
}
|
||||||
|
} // namespace json
|
||||||
|
} // namespace boost
|
23
Server/Database/Task.h
Normal file
23
Server/Database/Task.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef __TASK_H__
|
||||||
|
#define __TASK_H__
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Task {
|
||||||
|
public:
|
||||||
|
int id = -1;
|
||||||
|
bool finished = false;
|
||||||
|
int32_t createTime = 0;
|
||||||
|
std::string content;
|
||||||
|
std::string comment;
|
||||||
|
};
|
||||||
|
using Tasks = std::list<Task>;
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace json {
|
||||||
|
std::string serialize(const Tasks &tasks);
|
||||||
|
}
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // __TASK_H__
|
@ -3,6 +3,7 @@
|
|||||||
#include "ServiceLogic.h"
|
#include "ServiceLogic.h"
|
||||||
#include "WeChatContext/CorporationContext.h"
|
#include "WeChatContext/CorporationContext.h"
|
||||||
#include "WebsocketSession.h"
|
#include "WebsocketSession.h"
|
||||||
|
#include "Database.h"
|
||||||
|
|
||||||
SharedState::SharedState(boost::asio::io_context &ioContext, std::string doc_root)
|
SharedState::SharedState(boost::asio::io_context &ioContext, std::string doc_root)
|
||||||
: m_ioContext(ioContext), m_router{std::make_shared<boost::urls::router<Handler>>()},
|
: m_ioContext(ioContext), m_router{std::make_shared<boost::urls::router<Handler>>()},
|
||||||
@ -51,11 +52,14 @@ SharedState::SharedState(boost::asio::io_context &ioContext, std::string doc_roo
|
|||||||
|
|
||||||
m_router->insert("/api/v1/tasklist",[this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_router->insert("/api/v1/tasklist",[this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
|
auto database = Amass::Singleton<Database>::instance();
|
||||||
|
auto tasks = database->tasks();
|
||||||
|
|
||||||
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
||||||
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||||
s.set(http::field::content_type, "application/json;charset=UTF-8");
|
s.set(http::field::content_type, "application/json;charset=UTF-8");
|
||||||
s.keep_alive(request.keep_alive());
|
s.keep_alive(request.keep_alive());
|
||||||
s.body() = "[]";
|
s.body() = boost::json::serialize(tasks);
|
||||||
s.prepare_payload();
|
s.prepare_payload();
|
||||||
session.reply(std::move(s));
|
session.reply(std::move(s));
|
||||||
});
|
});
|
||||||
@ -63,10 +67,29 @@ SharedState::SharedState(boost::asio::io_context &ioContext, std::string doc_roo
|
|||||||
m_router->insert("/api/v1/task/add", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_router->insert("/api/v1/task/add", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
LOG(info) << "add task: " << request.body();
|
LOG(info) << "add task: " << request.body();
|
||||||
|
auto database = Amass::Singleton<Database>::instance();
|
||||||
|
auto root = boost::json::parse(request.body());
|
||||||
|
bool ret = database->addTask(root.at("createTime").as_int64(), std::string(root.at("content").as_string()),
|
||||||
|
std::string(root.at("comment").as_string()));
|
||||||
|
boost::json::object reply;
|
||||||
|
reply["status"] = ret ? 0 : -1;
|
||||||
|
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
||||||
|
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||||
|
s.set(http::field::content_type, "application/json;charset=UTF-8");
|
||||||
|
s.keep_alive(request.keep_alive());
|
||||||
|
s.body() = boost::json::serialize(reply);
|
||||||
|
s.prepare_payload();
|
||||||
|
session.reply(std::move(s));
|
||||||
|
});
|
||||||
|
|
||||||
|
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();
|
||||||
|
auto status = database->removeTask(std::stoi(matches.at("id")) );
|
||||||
|
|
||||||
boost::json::object reply;
|
boost::json::object reply;
|
||||||
reply["status"] = 0;
|
reply["status"] = status? 0 : -1;
|
||||||
|
|
||||||
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
||||||
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||||
s.set(http::field::content_type, "application/json;charset=UTF-8");
|
s.set(http::field::content_type, "application/json;charset=UTF-8");
|
||||||
|
@ -11,7 +11,7 @@ BOOST_AUTO_TEST_CASE(DatabaseTest) {
|
|||||||
|
|
||||||
database.addTask(1234, "Hello");
|
database.addTask(1234, "Hello");
|
||||||
|
|
||||||
database.addTask(1234, "这是一个测试", true);
|
database.addTask(1234, "这是一个测试","", true);
|
||||||
|
|
||||||
auto now = duration_cast<seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
auto now = duration_cast<seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||||
database.setTaskFinished(1, true, now);
|
database.setTaskFinished(1, true, now);
|
||||||
|
Loading…
Reference in New Issue
Block a user