mirror of
https://gitee.com/an-tao/drogon.git
synced 2024-11-30 02:37:57 +08:00
add onSessionStart() and onSessionDestroy() events (#1412)
Co-authored-by: an-tao <antao2002@gmail.com>
This commit is contained in:
parent
ef93c91ec7
commit
1b11bfb668
@ -86,12 +86,16 @@ class CacheMap
|
|||||||
CacheMap(trantor::EventLoop *loop,
|
CacheMap(trantor::EventLoop *loop,
|
||||||
float tickInterval = TICK_INTERVAL,
|
float tickInterval = TICK_INTERVAL,
|
||||||
size_t wheelsNum = WHEELS_NUM,
|
size_t wheelsNum = WHEELS_NUM,
|
||||||
size_t bucketsNumPerWheel = BUCKET_NUM_PER_WHEEL)
|
size_t bucketsNumPerWheel = BUCKET_NUM_PER_WHEEL,
|
||||||
|
std::function<void(const T1 &)> fnOnInsert = nullptr,
|
||||||
|
std::function<void(const T1 &)> fnOnErase = nullptr)
|
||||||
: loop_(loop),
|
: loop_(loop),
|
||||||
tickInterval_(tickInterval),
|
tickInterval_(tickInterval),
|
||||||
wheelsNumber_(wheelsNum),
|
wheelsNumber_(wheelsNum),
|
||||||
bucketsNumPerWheel_(bucketsNumPerWheel),
|
bucketsNumPerWheel_(bucketsNumPerWheel),
|
||||||
ctrlBlockPtr_(std::make_shared<ControlBlock>())
|
ctrlBlockPtr_(std::make_shared<ControlBlock>()),
|
||||||
|
fnOnInsert_(fnOnInsert),
|
||||||
|
fnOnErase_(fnOnErase)
|
||||||
{
|
{
|
||||||
wheels_.resize(wheelsNumber_);
|
wheels_.resize(wheelsNumber_);
|
||||||
for (size_t i = 0; i < wheelsNumber_; ++i)
|
for (size_t i = 0; i < wheelsNumber_; ++i)
|
||||||
@ -215,6 +219,8 @@ class CacheMap
|
|||||||
std::lock_guard<std::mutex> lock(mtx_);
|
std::lock_guard<std::mutex> lock(mtx_);
|
||||||
map_.insert(std::make_pair(key, std::move(v)));
|
map_.insert(std::make_pair(key, std::move(v)));
|
||||||
}
|
}
|
||||||
|
if (fnOnInsert_)
|
||||||
|
fnOnInsert_(key);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Insert a key-value pair into the cache.
|
* @brief Insert a key-value pair into the cache.
|
||||||
@ -244,6 +250,8 @@ class CacheMap
|
|||||||
std::lock_guard<std::mutex> lock(mtx_);
|
std::lock_guard<std::mutex> lock(mtx_);
|
||||||
map_.insert(std::make_pair(key, std::move(v)));
|
map_.insert(std::make_pair(key, std::move(v)));
|
||||||
}
|
}
|
||||||
|
if (fnOnInsert_)
|
||||||
|
fnOnInsert_(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -284,9 +292,11 @@ class CacheMap
|
|||||||
* the key doesn't exist, a new one is created and passed to the handler and
|
* the key doesn't exist, a new one is created and passed to the handler and
|
||||||
* stored in the cache with the timeout parameter. The changing of the data
|
* stored in the cache with the timeout parameter. The changing of the data
|
||||||
* is protected by the mutex of the cache.
|
* is protected by the mutex of the cache.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
template <typename Callable>
|
template <typename Callable>
|
||||||
void modify(const T1 &key, Callable &&handler, size_t timeout = 0)
|
void modify(const T1 &key, Callable &&handler, size_t timeout = 0)
|
||||||
|
{
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mtx_);
|
std::lock_guard<std::mutex> lock(mtx_);
|
||||||
auto iter = map_.find(key);
|
auto iter = map_.find(key);
|
||||||
@ -298,6 +308,7 @@ class CacheMap
|
|||||||
eraseAfter(timeout, key);
|
eraseAfter(timeout, key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapValue v{T2(), timeout};
|
MapValue v{T2(), timeout};
|
||||||
handler(v.value_);
|
handler(v.value_);
|
||||||
map_.insert(std::make_pair(key, std::move(v)));
|
map_.insert(std::make_pair(key, std::move(v)));
|
||||||
@ -306,6 +317,10 @@ class CacheMap
|
|||||||
eraseAfter(timeout, key);
|
eraseAfter(timeout, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fnOnInsert_)
|
||||||
|
fnOnInsert_(key);
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if the value of the keyword exists
|
/// Check if the value of the keyword exists
|
||||||
bool find(const T1 &key)
|
bool find(const T1 &key)
|
||||||
{
|
{
|
||||||
@ -358,9 +373,13 @@ class CacheMap
|
|||||||
void erase(const T1 &key)
|
void erase(const T1 &key)
|
||||||
{
|
{
|
||||||
// in this case,we don't evoke the timeout callback;
|
// in this case,we don't evoke the timeout callback;
|
||||||
|
{
|
||||||
std::lock_guard<std::mutex> lock(mtx_);
|
std::lock_guard<std::mutex> lock(mtx_);
|
||||||
map_.erase(key);
|
map_.erase(key);
|
||||||
}
|
}
|
||||||
|
if (fnOnErase_)
|
||||||
|
fnOnErase_(key);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Get the event loop object
|
* @brief Get the event loop object
|
||||||
*
|
*
|
||||||
@ -425,6 +444,8 @@ class CacheMap
|
|||||||
size_t wheelsNumber_;
|
size_t wheelsNumber_;
|
||||||
size_t bucketsNumPerWheel_;
|
size_t bucketsNumPerWheel_;
|
||||||
std::shared_ptr<ControlBlock> ctrlBlockPtr_;
|
std::shared_ptr<ControlBlock> ctrlBlockPtr_;
|
||||||
|
std::function<void(const T1 &)> fnOnInsert_;
|
||||||
|
std::function<void(const T1 &)> fnOnErase_;
|
||||||
|
|
||||||
bool noWheels_{false};
|
bool noWheels_{false};
|
||||||
|
|
||||||
@ -486,21 +507,28 @@ class CacheMap
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::function<void()> cb = [this, key]() {
|
std::function<void()> cb = [this, key]() {
|
||||||
std::lock_guard<std::mutex> lock(mtx_);
|
bool erased{false};
|
||||||
if (map_.find(key) != map_.end())
|
std::function<void()> timeoutCallback;
|
||||||
{
|
{
|
||||||
auto &value = map_[key];
|
std::lock_guard<std::mutex> lock(mtx_);
|
||||||
|
auto iter = map_.find(key);
|
||||||
|
if (iter != map_.end())
|
||||||
|
{
|
||||||
|
auto &value = iter->second;
|
||||||
auto entryPtr = value.weakEntryPtr_.lock();
|
auto entryPtr = value.weakEntryPtr_.lock();
|
||||||
// entryPtr is used to avoid race conditions
|
// entryPtr is used to avoid race conditions
|
||||||
if (value.timeout_ > 0 && !entryPtr)
|
if (value.timeout_ > 0 && !entryPtr)
|
||||||
{
|
{
|
||||||
if (value.timeoutCallback_)
|
erased = true;
|
||||||
{
|
timeoutCallback = std::move(value.timeoutCallback_);
|
||||||
value.timeoutCallback_();
|
|
||||||
}
|
|
||||||
map_.erase(key);
|
map_.erase(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (erased && fnOnErase_)
|
||||||
|
fnOnErase_(key);
|
||||||
|
if (erased && timeoutCallback)
|
||||||
|
timeoutCallback();
|
||||||
};
|
};
|
||||||
entryPtr = std::make_shared<CallbackEntry>(std::move(cb));
|
entryPtr = std::make_shared<CallbackEntry>(std::move(cb));
|
||||||
map_[key].weakEntryPtr_ = entryPtr;
|
map_[key].weakEntryPtr_ = entryPtr;
|
||||||
|
@ -745,6 +745,20 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable
|
|||||||
return enableSession((size_t)timeout.count(), sameSite);
|
return enableSession((size_t)timeout.count(), sameSite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register an advice called when starting a new session.
|
||||||
|
/**
|
||||||
|
* @param advice is called with the session id.
|
||||||
|
*/
|
||||||
|
virtual HttpAppFramework ®isterSessionStartAdvice(
|
||||||
|
const AdviceStartSessionCallback &advice) = 0;
|
||||||
|
|
||||||
|
/// Register an advice called when destroying a session.
|
||||||
|
/**
|
||||||
|
* @param advice is called with the session id.
|
||||||
|
*/
|
||||||
|
virtual HttpAppFramework ®isterSessionDestroyAdvice(
|
||||||
|
const AdviceDestroySessionCallback &advice) = 0;
|
||||||
|
|
||||||
/// Disable sessions supporting.
|
/// Disable sessions supporting.
|
||||||
/**
|
/**
|
||||||
* @note
|
* @note
|
||||||
|
@ -26,6 +26,8 @@ class HttpRequest;
|
|||||||
using HttpRequestPtr = std::shared_ptr<HttpRequest>;
|
using HttpRequestPtr = std::shared_ptr<HttpRequest>;
|
||||||
using AdviceCallback = std::function<void(const HttpResponsePtr &)>;
|
using AdviceCallback = std::function<void(const HttpResponsePtr &)>;
|
||||||
using AdviceChainCallback = std::function<void()>;
|
using AdviceChainCallback = std::function<void()>;
|
||||||
|
using AdviceStartSessionCallback = std::function<void(const std::string &)>;
|
||||||
|
using AdviceDestroySessionCallback = std::function<void(const std::string &)>;
|
||||||
using FilterCallback = std::function<void(const HttpResponsePtr &)>;
|
using FilterCallback = std::function<void(const HttpResponsePtr &)>;
|
||||||
using FilterChainCallback = std::function<void()>;
|
using FilterChainCallback = std::function<void()>;
|
||||||
using HttpReqCallback = std::function<void(ReqResult, const HttpResponsePtr &)>;
|
using HttpReqCallback = std::function<void(ReqResult, const HttpResponsePtr &)>;
|
||||||
|
@ -571,7 +571,10 @@ void HttpAppFrameworkImpl::run()
|
|||||||
if (useSession_)
|
if (useSession_)
|
||||||
{
|
{
|
||||||
sessionManagerPtr_ =
|
sessionManagerPtr_ =
|
||||||
std::make_unique<SessionManager>(getLoop(), sessionTimeout_);
|
std::make_unique<SessionManager>(getLoop(),
|
||||||
|
sessionTimeout_,
|
||||||
|
sessionStartAdvices_,
|
||||||
|
sessionDestroyAdvices_);
|
||||||
}
|
}
|
||||||
// now start running!!
|
// now start running!!
|
||||||
running_ = true;
|
running_ = true;
|
||||||
|
@ -221,6 +221,21 @@ class HttpAppFrameworkImpl final : public HttpAppFramework
|
|||||||
useSession_ = false;
|
useSession_ = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpAppFramework ®isterSessionStartAdvice(
|
||||||
|
const AdviceStartSessionCallback &advice) override
|
||||||
|
{
|
||||||
|
sessionStartAdvices_.emplace_back(advice);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpAppFramework ®isterSessionDestroyAdvice(
|
||||||
|
const AdviceDestroySessionCallback &advice) override
|
||||||
|
{
|
||||||
|
sessionDestroyAdvices_.emplace_back(advice);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string &getDocumentRoot() const override
|
const std::string &getDocumentRoot() const override
|
||||||
{
|
{
|
||||||
return rootPath_;
|
return rootPath_;
|
||||||
@ -657,6 +672,8 @@ class HttpAppFrameworkImpl final : public HttpAppFramework
|
|||||||
std::function<void()> termSignalHandler_{[]() { app().quit(); }};
|
std::function<void()> termSignalHandler_{[]() { app().quit(); }};
|
||||||
std::function<void()> intSignalHandler_{[]() { app().quit(); }};
|
std::function<void()> intSignalHandler_{[]() { app().quit(); }};
|
||||||
std::unique_ptr<SessionManager> sessionManagerPtr_;
|
std::unique_ptr<SessionManager> sessionManagerPtr_;
|
||||||
|
std::vector<AdviceStartSessionCallback> sessionStartAdvices_;
|
||||||
|
std::vector<AdviceDestroySessionCallback> sessionDestroyAdvices_;
|
||||||
std::shared_ptr<trantor::AsyncFileLogger> asyncFileLoggerPtr_;
|
std::shared_ptr<trantor::AsyncFileLogger> asyncFileLoggerPtr_;
|
||||||
Json::Value jsonConfig_;
|
Json::Value jsonConfig_;
|
||||||
HttpResponsePtr custom404_;
|
HttpResponsePtr custom404_;
|
||||||
|
@ -17,8 +17,15 @@
|
|||||||
|
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
SessionManager::SessionManager(trantor::EventLoop *loop, size_t timeout)
|
SessionManager::SessionManager(
|
||||||
: loop_(loop), timeout_(timeout)
|
trantor::EventLoop* loop,
|
||||||
|
size_t timeout,
|
||||||
|
const std::vector<AdviceStartSessionCallback>& startAdvices,
|
||||||
|
const std::vector<AdviceDestroySessionCallback>& destroyAdvices)
|
||||||
|
: loop_(loop),
|
||||||
|
timeout_(timeout),
|
||||||
|
sessionStartAdvices_(startAdvices),
|
||||||
|
sessionDestroyAdvices_(destroyAdvices)
|
||||||
{
|
{
|
||||||
if (timeout_ > 0)
|
if (timeout_ > 0)
|
||||||
{
|
{
|
||||||
@ -38,25 +45,57 @@ SessionManager::SessionManager(trantor::EventLoop *loop, size_t timeout)
|
|||||||
tmpTimeout = tmpTimeout / 100;
|
tmpTimeout = tmpTimeout / 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionMapPtr_ = std::unique_ptr<CacheMap<std::string, SessionPtr>>(
|
sessionMapPtr_ = std::unique_ptr<CacheMap<std::string, SessionPtr>>(
|
||||||
new CacheMap<std::string, SessionPtr>(
|
new CacheMap<std::string, SessionPtr>(
|
||||||
loop_, 1.0, wheelNum, bucketNum));
|
loop_,
|
||||||
|
1.0,
|
||||||
|
wheelNum,
|
||||||
|
bucketNum,
|
||||||
|
[this](const std::string& key) {
|
||||||
|
for (auto& advice : sessionStartAdvices_)
|
||||||
|
{
|
||||||
|
advice(key);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[this](const std::string& key) {
|
||||||
|
for (auto& advice : sessionDestroyAdvices_)
|
||||||
|
{
|
||||||
|
advice(key);
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
else if (timeout_ == 0)
|
else if (timeout_ == 0)
|
||||||
{
|
{
|
||||||
sessionMapPtr_ = std::unique_ptr<CacheMap<std::string, SessionPtr>>(
|
sessionMapPtr_ = std::unique_ptr<CacheMap<std::string, SessionPtr>>(
|
||||||
new CacheMap<std::string, SessionPtr>(loop_, 0, 0, 0));
|
new CacheMap<std::string, SessionPtr>(
|
||||||
|
loop_,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
[this](const std::string& key) {
|
||||||
|
for (auto& advice : sessionStartAdvices_)
|
||||||
|
{
|
||||||
|
advice(key);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[this](const std::string& key) {
|
||||||
|
for (auto& advice : sessionDestroyAdvices_)
|
||||||
|
{
|
||||||
|
advice(key);
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionPtr SessionManager::getSession(const std::string &sessionID,
|
SessionPtr SessionManager::getSession(const std::string& sessionID,
|
||||||
bool needToSet)
|
bool needToSet)
|
||||||
{
|
{
|
||||||
assert(!sessionID.empty());
|
assert(!sessionID.empty());
|
||||||
SessionPtr sessionPtr;
|
SessionPtr sessionPtr;
|
||||||
sessionMapPtr_->modify(
|
sessionMapPtr_->modify(
|
||||||
sessionID,
|
sessionID,
|
||||||
[&sessionPtr, &sessionID, needToSet](SessionPtr &sessionInCache) {
|
[&sessionPtr, &sessionID, needToSet](SessionPtr& sessionInCache) {
|
||||||
if (sessionInCache)
|
if (sessionInCache)
|
||||||
{
|
{
|
||||||
sessionPtr = sessionInCache;
|
sessionPtr = sessionInCache;
|
||||||
@ -69,10 +108,11 @@ SessionPtr SessionManager::getSession(const std::string &sessionID,
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
timeout_);
|
timeout_);
|
||||||
|
|
||||||
return sessionPtr;
|
return sessionPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionManager::changeSessionId(const SessionPtr &sessionPtr)
|
void SessionManager::changeSessionId(const SessionPtr& sessionPtr)
|
||||||
{
|
{
|
||||||
auto oldId = sessionPtr->sessionId();
|
auto oldId = sessionPtr->sessionId();
|
||||||
auto newId = utils::getUuid();
|
auto newId = utils::getUuid();
|
||||||
|
@ -15,19 +15,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <drogon/Session.h>
|
#include <drogon/Session.h>
|
||||||
|
#include <drogon/drogon_callbacks.h>
|
||||||
#include <drogon/CacheMap.h>
|
#include <drogon/CacheMap.h>
|
||||||
#include <trantor/utils/NonCopyable.h>
|
#include <trantor/utils/NonCopyable.h>
|
||||||
#include <trantor/net/EventLoop.h>
|
#include <trantor/net/EventLoop.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace drogon
|
namespace drogon
|
||||||
{
|
{
|
||||||
class SessionManager : public trantor::NonCopyable
|
class SessionManager : public trantor::NonCopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SessionManager(trantor::EventLoop *loop, size_t timeout);
|
SessionManager(
|
||||||
|
trantor::EventLoop *loop,
|
||||||
|
size_t timeout,
|
||||||
|
const std::vector<AdviceStartSessionCallback> &startAdvices,
|
||||||
|
const std::vector<AdviceDestroySessionCallback> &destroyAdvices);
|
||||||
~SessionManager()
|
~SessionManager()
|
||||||
{
|
{
|
||||||
sessionMapPtr_.reset();
|
sessionMapPtr_.reset();
|
||||||
@ -39,5 +45,7 @@ class SessionManager : public trantor::NonCopyable
|
|||||||
std::unique_ptr<CacheMap<std::string, SessionPtr>> sessionMapPtr_;
|
std::unique_ptr<CacheMap<std::string, SessionPtr>> sessionMapPtr_;
|
||||||
trantor::EventLoop *loop_;
|
trantor::EventLoop *loop_;
|
||||||
size_t timeout_;
|
size_t timeout_;
|
||||||
|
const std::vector<AdviceStartSessionCallback> &sessionStartAdvices_;
|
||||||
|
const std::vector<AdviceDestroySessionCallback> &sessionDestroyAdvices_;
|
||||||
};
|
};
|
||||||
} // namespace drogon
|
} // namespace drogon
|
||||||
|
@ -319,6 +319,12 @@ int main()
|
|||||||
}
|
}
|
||||||
return nullResp;
|
return nullResp;
|
||||||
});
|
});
|
||||||
|
app().registerSessionStartAdvice([](const std::string &sessionId) {
|
||||||
|
LOG_DEBUG << "session start:" << sessionId;
|
||||||
|
});
|
||||||
|
app().registerSessionDestroyAdvice([](const std::string &sessionId) {
|
||||||
|
LOG_DEBUG << "session destroy:" << sessionId;
|
||||||
|
});
|
||||||
// Output information of all handlers
|
// Output information of all handlers
|
||||||
auto handlerInfo = app().getHandlersInfo();
|
auto handlerInfo = app().getHandlersInfo();
|
||||||
for (auto &info : handlerInfo)
|
for (auto &info : handlerInfo)
|
||||||
|
Loading…
Reference in New Issue
Block a user