add exit command.
This commit is contained in:
parent
b6171695e7
commit
83b0ff4369
@ -50,9 +50,10 @@ jobs:
|
|||||||
script: |
|
script: |
|
||||||
cd /root/Server
|
cd /root/Server
|
||||||
source /etc/profile
|
source /etc/profile
|
||||||
echo "这里需要先停止原来的HttpServer, 然后再将/tmp/HttpServer拷贝至/root/Server"
|
/root/Server/HttpServer --exit
|
||||||
# pgrep -f HttpServer | xargs -r kill -s 9
|
sleep 10
|
||||||
# nohup /root/Server/HttpServer > /dev/null 2>&1 &
|
cp /tmp/HttpServer /root/Server/HttpServer
|
||||||
|
/root/Server/HttpServer &
|
||||||
exit 0
|
exit 0
|
||||||
- name: Notify-End
|
- name: Notify-End
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
|
@ -16,12 +16,18 @@ set(WT_INCLUDE_DIR ${WT_ROOT}/include)
|
|||||||
set(WT_LIBRARY_DIRS ${WT_ROOT}/lib)
|
set(WT_LIBRARY_DIRS ${WT_ROOT}/lib)
|
||||||
set(WT_LIBRARIES wt wttest wthttp wtdbo wtdbosqlite3)
|
set(WT_LIBRARIES wt wttest wthttp wtdbo wtdbosqlite3)
|
||||||
|
|
||||||
|
set(NNG_ROOT ${Libraries_ROOT}/nng-1.9.0)
|
||||||
|
set(NNG_INCLUDE_DIR ${NNG_ROOT}/include)
|
||||||
|
set(NNG_LIBRARY_DIRS ${NNG_ROOT}/lib)
|
||||||
|
|
||||||
set(OPENSSL_LIBRARIES ssl crypto)
|
set(OPENSSL_LIBRARIES ssl crypto)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
FetchContent_Declare(Kylin
|
FetchContent_Declare(Kylin
|
||||||
GIT_REPOSITORY https://amass.fun/gitea/amass/Kylin.git
|
GIT_REPOSITORY https://amass.fun/gitea/amass/Kylin.git
|
||||||
)
|
)
|
||||||
|
set(KYLIN_WITH_NNG ON)
|
||||||
|
# add_subdirectory(/mnt/e/Projects/Kylin Kylin)
|
||||||
FetchContent_MakeAvailable(Kylin)
|
FetchContent_MakeAvailable(Kylin)
|
||||||
|
|
||||||
add_subdirectory(MediaServer)
|
add_subdirectory(MediaServer)
|
||||||
|
@ -3,12 +3,17 @@
|
|||||||
#include "DateTime.h"
|
#include "DateTime.h"
|
||||||
#include "HttpSession.h"
|
#include "HttpSession.h"
|
||||||
#include "IoContext.h"
|
#include "IoContext.h"
|
||||||
|
#include "Nng/SocketAisoWrapper.h"
|
||||||
#include "ServiceLogic.h"
|
#include "ServiceLogic.h"
|
||||||
#include "ServiceManager.h"
|
#include "ServiceManager.h"
|
||||||
#include "SystemUsage.h"
|
#include "SystemUsage.h"
|
||||||
#include "WeChatContext/CorporationContext.h"
|
#include "WeChatContext/CorporationContext.h"
|
||||||
|
#include <boost/json/object.hpp>
|
||||||
|
#include <boost/json/serialize.hpp>
|
||||||
#include <boost/stacktrace.hpp>
|
#include <boost/stacktrace.hpp>
|
||||||
|
|
||||||
|
constexpr auto IpcUrl = "ipc:///tmp/nng_ipc_server";
|
||||||
|
|
||||||
Application::Application(const std::string &path)
|
Application::Application(const std::string &path)
|
||||||
: ApplicationSettings(path), m_router{std::make_shared<boost::urls::router<RequestHandler>>()} {
|
: ApplicationSettings(path), m_router{std::make_shared<boost::urls::router<RequestHandler>>()} {
|
||||||
|
|
||||||
@ -232,6 +237,9 @@ Application::Application(const std::string &path)
|
|||||||
m_ioContext = Amass::Singleton<IoContext>::instance<Amass::Construct>(getThreads());
|
m_ioContext = Amass::Singleton<IoContext>::instance<Amass::Construct>(getThreads());
|
||||||
m_timer = std::make_shared<boost::asio::system_timer>(*m_ioContext->ioContext());
|
m_timer = std::make_shared<boost::asio::system_timer>(*m_ioContext->ioContext());
|
||||||
|
|
||||||
|
m_replyer = std::make_shared<Nng::Asio::Socket>(*m_ioContext->ioContext(), Nng::Reply);
|
||||||
|
m_replyer->listen(IpcUrl);
|
||||||
|
|
||||||
m_systemUsage = std::make_shared<SystemUsage>(*m_ioContext->ioContext(), getHomeAssistantAccessToken());
|
m_systemUsage = std::make_shared<SystemUsage>(*m_ioContext->ioContext(), getHomeAssistantAccessToken());
|
||||||
m_systemUsage->start();
|
m_systemUsage->start();
|
||||||
|
|
||||||
@ -259,9 +267,10 @@ void Application::insertUrl(std::string_view url, RequestHandler &&handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Application::exec() {
|
int Application::exec() {
|
||||||
|
startAcceptRequest();
|
||||||
LOG(info) << "application start successful ...";
|
LOG(info) << "application start successful ...";
|
||||||
startCheckInterval(*m_ioContext->ioContext(), 2);
|
startCheckInterval(*m_ioContext->ioContext(), 2);
|
||||||
m_ioContext->run<IoContext::Mode::Synchronous>();
|
m_ioContext->run();
|
||||||
LOG(info) << "application exit successful ...";
|
LOG(info) << "application exit successful ...";
|
||||||
return m_status;
|
return m_status;
|
||||||
}
|
}
|
||||||
@ -313,3 +322,39 @@ void Application::alarmTask() {
|
|||||||
alarmTask();
|
alarmTask();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::startAcceptRequest() {
|
||||||
|
m_replyer->asyncReceive([ptr{weak_from_this()}](const boost::system::error_code &error, const Nng::Buffer &buffer) {
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
}
|
||||||
|
LOG(info) << buffer.data();
|
||||||
|
if (ptr.expired()) return;
|
||||||
|
auto self = ptr.lock();
|
||||||
|
auto value = boost::json::parse(buffer.data());
|
||||||
|
auto &request = value.as_object();
|
||||||
|
if (request.at("command").as_string() == "exit") {
|
||||||
|
boost::json::object reply;
|
||||||
|
reply["status"] = 0;
|
||||||
|
reply["message"] = "will exit.";
|
||||||
|
auto txt = boost::json::serialize(reply);
|
||||||
|
self->m_replyer->send(txt.data(), txt.size());
|
||||||
|
std::raise(SIGUSR1); // 发送自定义信号
|
||||||
|
}
|
||||||
|
self->startAcceptRequest();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::requetExit() {
|
||||||
|
nng_log_set_logger(nng_stderr_logger);
|
||||||
|
LOG(info) << "send exit request to program.";
|
||||||
|
Nng::Socket request(Nng::Request);
|
||||||
|
request.dial(IpcUrl);
|
||||||
|
|
||||||
|
boost::json::object object;
|
||||||
|
object["command"] = "exit";
|
||||||
|
auto text = boost::json::serialize(object);
|
||||||
|
request.send(text.data(), text.size());
|
||||||
|
auto buffer = request.recv();
|
||||||
|
LOG(info) << buffer.data<char>();
|
||||||
|
}
|
@ -13,6 +13,12 @@ class ChatRoom;
|
|||||||
class SystemUsage;
|
class SystemUsage;
|
||||||
class IoContext;
|
class IoContext;
|
||||||
|
|
||||||
|
namespace Nng {
|
||||||
|
namespace Asio {
|
||||||
|
class Socket;
|
||||||
|
}
|
||||||
|
} // namespace Nng
|
||||||
|
|
||||||
class Application : public ApplicationSettings<Application>, public std::enable_shared_from_this<Application> {
|
class Application : public ApplicationSettings<Application>, public std::enable_shared_from_this<Application> {
|
||||||
public:
|
public:
|
||||||
using Pointer = std::shared_ptr<Application>;
|
using Pointer = std::shared_ptr<Application>;
|
||||||
@ -35,9 +41,11 @@ public:
|
|||||||
const RequestHandler *find(boost::urls::segments_encoded_view path,
|
const RequestHandler *find(boost::urls::segments_encoded_view path,
|
||||||
boost::urls::matches_base &matches) const noexcept;
|
boost::urls::matches_base &matches) const noexcept;
|
||||||
void insertUrl(std::string_view url, RequestHandler &&handler);
|
void insertUrl(std::string_view url, RequestHandler &&handler);
|
||||||
|
static void requetExit();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void alarmTask();
|
void alarmTask();
|
||||||
|
void startAcceptRequest();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_status = 0;
|
int m_status = 0;
|
||||||
@ -46,6 +54,7 @@ private:
|
|||||||
std::shared_ptr<boost::asio::system_timer> m_timer;
|
std::shared_ptr<boost::asio::system_timer> m_timer;
|
||||||
std::shared_ptr<ChatRoom> m_charRoom;
|
std::shared_ptr<ChatRoom> m_charRoom;
|
||||||
std::shared_ptr<SystemUsage> m_systemUsage;
|
std::shared_ptr<SystemUsage> m_systemUsage;
|
||||||
|
std::shared_ptr<Nng::Asio::Socket> m_replyer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __SETTINGS_H__
|
#endif // __SETTINGS_H__
|
@ -24,6 +24,7 @@ target_link_libraries(Server
|
|||||||
PRIVATE Database
|
PRIVATE Database
|
||||||
PRIVATE MediaServer
|
PRIVATE MediaServer
|
||||||
PRIVATE WebApplication
|
PRIVATE WebApplication
|
||||||
|
PRIVATE Nng
|
||||||
PRIVATE ${Boost_LIBRARIES}
|
PRIVATE ${Boost_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
CorporationContext::CorporationContext(boost::asio::io_context &ioContext)
|
CorporationContext::CorporationContext(boost::asio::io_context &ioContext)
|
||||||
: m_ioContext(ioContext), m_timer(ioContext) {
|
: m_ioContext(ioContext), m_timer(ioContext) {
|
||||||
boost::asio::defer([this]() { updateAccessToken(); });
|
|
||||||
|
|
||||||
auto manager = Amass::Singleton<ServiceManager>::instance();
|
auto manager = Amass::Singleton<ServiceManager>::instance();
|
||||||
if (manager)
|
if (manager)
|
||||||
@ -47,6 +46,17 @@ void CorporationContext::sendMessage(MessageType type, const std::string &messag
|
|||||||
LOG(info) << response;
|
LOG(info) << response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CorporationContext::start() {
|
||||||
|
boost::asio::defer(m_ioContext, [ptr{weak_from_this()}]() {
|
||||||
|
if (ptr.expired()) {
|
||||||
|
LOG(error) << "CorporationContext instance was expired";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto self = ptr.lock();
|
||||||
|
self->updateAccessToken();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void CorporationContext::notify(const RequestType &request) {
|
void CorporationContext::notify(const RequestType &request) {
|
||||||
boost::system::error_code error;
|
boost::system::error_code error;
|
||||||
auto json = boost::json::parse(request.body(), error);
|
auto json = boost::json::parse(request.body(), error);
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
#ifndef __CORPORATIONCONTEXT_H__
|
#ifndef __CORPORATIONCONTEXT_H__
|
||||||
#define __CORPORATIONCONTEXT_H__
|
#define __CORPORATIONCONTEXT_H__
|
||||||
|
|
||||||
|
#include "Singleton.h"
|
||||||
#include <boost/asio/steady_timer.hpp>
|
#include <boost/asio/steady_timer.hpp>
|
||||||
#include <boost/beast/http/string_body.hpp>
|
#include <boost/beast/http/string_body.hpp>
|
||||||
|
|
||||||
class CorporationContext {
|
class CorporationContext : public std::enable_shared_from_this<CorporationContext> {
|
||||||
|
friend class Amass::Singleton<CorporationContext>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum MessageType {
|
enum MessageType {
|
||||||
Text,
|
Text,
|
||||||
@ -12,8 +15,8 @@ public:
|
|||||||
};
|
};
|
||||||
using RequestType = boost::beast::http::request<boost::beast::http::string_body>;
|
using RequestType = boost::beast::http::request<boost::beast::http::string_body>;
|
||||||
|
|
||||||
CorporationContext(boost::asio::io_context &ioContext);
|
|
||||||
void sendMessage(MessageType type, const std::string &message);
|
void sendMessage(MessageType type, const std::string &message);
|
||||||
|
void start();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
@ -25,6 +28,7 @@ public:
|
|||||||
void notify(const RequestType &request);
|
void notify(const RequestType &request);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
CorporationContext(boost::asio::io_context &ioContext);
|
||||||
void updateAccessToken();
|
void updateAccessToken();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -60,8 +60,7 @@ std::string WeChatContext::reply(const std::string &body) {
|
|||||||
|
|
||||||
WeChatContext::WeChatContext(boost::asio::io_context &ioContext)
|
WeChatContext::WeChatContext(boost::asio::io_context &ioContext)
|
||||||
: m_ioContext(ioContext), m_timer(ioContext), m_sessionsExpireTimer(ioContext) {
|
: m_ioContext(ioContext), m_timer(ioContext), m_sessionsExpireTimer(ioContext) {
|
||||||
|
boost::asio::defer(m_ioContext, [this]() { updateAccessToken(); });
|
||||||
boost::asio::defer([this]() { updateAccessToken(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WeChatContext::updateAccessToken() {
|
void WeChatContext::updateAccessToken() {
|
||||||
|
@ -25,6 +25,7 @@ int main(int argc, char const *argv[]) {
|
|||||||
// clang-format off
|
// clang-format off
|
||||||
description.add_options()
|
description.add_options()
|
||||||
("help,h", "produce help message.")
|
("help,h", "produce help message.")
|
||||||
|
("exit,e", "signal program to exit.")
|
||||||
("prefix", boost::program_options::value<std::string>(),"set prefix path (default: ${pwd} )");
|
("prefix", boost::program_options::value<std::string>(),"set prefix path (default: ${pwd} )");
|
||||||
// clang-format on
|
// clang-format on
|
||||||
boost::program_options::variables_map values;
|
boost::program_options::variables_map values;
|
||||||
@ -39,6 +40,9 @@ int main(int argc, char const *argv[]) {
|
|||||||
if (values.count("help")) {
|
if (values.count("help")) {
|
||||||
std::cout << description << std::endl;
|
std::cout << description << std::endl;
|
||||||
std::exit(0);
|
std::exit(0);
|
||||||
|
} else if (values.count("exit")) {
|
||||||
|
Application::requetExit();
|
||||||
|
std::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::error_code error;
|
std::error_code error;
|
||||||
@ -76,6 +80,7 @@ int main(int argc, char const *argv[]) {
|
|||||||
|
|
||||||
auto wechatContext = Singleton<WeChatContext>::instance<Construct>(application->ioContext());
|
auto wechatContext = Singleton<WeChatContext>::instance<Construct>(application->ioContext());
|
||||||
auto corpContext = Singleton<CorporationContext>::instance<Construct>(application->ioContext());
|
auto corpContext = Singleton<CorporationContext>::instance<Construct>(application->ioContext());
|
||||||
|
corpContext->start();
|
||||||
auto live2d = std::make_shared<Live2dBackend>();
|
auto live2d = std::make_shared<Live2dBackend>();
|
||||||
|
|
||||||
LOG(info) << "hardware_concurrency: " << std::thread::hardware_concurrency()
|
LOG(info) << "hardware_concurrency: " << std::thread::hardware_concurrency()
|
||||||
@ -90,6 +95,7 @@ int main(int argc, char const *argv[]) {
|
|||||||
#else
|
#else
|
||||||
boost::asio::signal_set signals(application->ioContext(), SIGINT, SIGTERM);
|
boost::asio::signal_set signals(application->ioContext(), SIGINT, SIGTERM);
|
||||||
#endif
|
#endif
|
||||||
|
signals.add(SIGUSR1);
|
||||||
signals.async_wait([&application](boost::system::error_code const &, int signal) {
|
signals.async_wait([&application](boost::system::error_code const &, int signal) {
|
||||||
// Stop the io_context. This will cause run()
|
// Stop the io_context. This will cause run()
|
||||||
// to return immediately, eventually destroying the
|
// to return immediately, eventually destroying the
|
||||||
|
@ -12,7 +12,8 @@ static std::unique_ptr<Wt::WApplication> createApplication(const Wt::WEnvironmen
|
|||||||
return std::make_unique<Hello>(env, false);
|
return std::make_unique<Hello>(env, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Wt::WApplication> createBlogApplication(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool *blogDb) {
|
std::unique_ptr<Wt::WApplication> createBlogApplication(const Wt::WEnvironment &env,
|
||||||
|
Wt::Dbo::SqlConnectionPool *blogDb) {
|
||||||
return std::make_unique<BlogApplication>(env, *blogDb);
|
return std::make_unique<BlogApplication>(env, *blogDb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,31 +33,22 @@ WebApplication::WebApplication() {
|
|||||||
|
|
||||||
BlogSession::configureAuth();
|
BlogSession::configureAuth();
|
||||||
m_blogSqlConnectionPool = BlogSession::createConnectionPool(m_server->appRoot() + "database.sqlite");
|
m_blogSqlConnectionPool = BlogSession::createConnectionPool(m_server->appRoot() + "database.sqlite");
|
||||||
m_server->addEntryPoint(Wt::EntryPointType::Application, std::bind(&createBlogApplication, std::placeholders::_1, m_blogSqlConnectionPool.get()),
|
m_server->addEntryPoint(Wt::EntryPointType::Application,
|
||||||
|
std::bind(&createBlogApplication, std::placeholders::_1, m_blogSqlConnectionPool.get()),
|
||||||
"/blog");
|
"/blog");
|
||||||
m_server->addEntryPoint(Wt::EntryPointType::WidgetSet, createWidgetSet, "/gui/hello.js");
|
m_server->addEntryPoint(Wt::EntryPointType::WidgetSet, createWidgetSet, "/gui/hello.js");
|
||||||
Session::configureAuth();
|
Session::configureAuth();
|
||||||
m_server->addResource(std::make_shared<JsonResource>(), "/json");
|
m_server->addResource(std::make_shared<JsonResource>(), "/json");
|
||||||
m_server->addResource(std::make_shared<PlaintextResource>(), "/plaintext");
|
m_server->addResource(std::make_shared<PlaintextResource>(), "/plaintext");
|
||||||
m_server->addResource(std::make_shared<DbResource>("database.sqlite"), "/db");
|
m_server->addResource(std::make_shared<DbResource>("database.sqlite"), "/db");
|
||||||
m_thread = std::thread(&WebApplication::run, this);
|
|
||||||
|
|
||||||
|
m_server->start();
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
LOG(error) << e.what();
|
LOG(error) << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WebApplication::~WebApplication() {
|
WebApplication::~WebApplication() {
|
||||||
if (m_thread.joinable()) {
|
|
||||||
m_thread.join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApplication::run() {
|
|
||||||
try {
|
|
||||||
|
|
||||||
m_server->run();
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
LOG(error) << e.what();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -17,12 +17,8 @@ public:
|
|||||||
WebApplication();
|
WebApplication();
|
||||||
~WebApplication();
|
~WebApplication();
|
||||||
|
|
||||||
protected:
|
|
||||||
void run();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Wt::WServer> m_server;
|
std::unique_ptr<Wt::WServer> m_server;
|
||||||
std::thread m_thread;
|
|
||||||
std::unique_ptr<Wt::Dbo::SqlConnectionPool> m_blogSqlConnectionPool;
|
std::unique_ptr<Wt::Dbo::SqlConnectionPool> m_blogSqlConnectionPool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user