Rework chache handling

* No longer provide multiple HTTP helper functions with the same name
* Default to cache not being used
* Explicitly use the cache for certain Twitch actions and conditions
* Clear caches on shutdown to avoid leaks being reported
This commit is contained in:
WarmUpTill 2025-03-13 19:29:26 +01:00 committed by WarmUpTill
parent d670b6d07e
commit 34e125f82d
5 changed files with 95 additions and 61 deletions

View File

@ -193,7 +193,7 @@ void CategoryGrabber::Search(const std::string &)
httplib::Params params = {{"first", "100"},
{"after", cursor},
{"query", _searchString}};
auto response = SendGetRequest(*_token, uri, path, params);
auto response = SendGetRequest(*_token, uri, path, params, true);
while (response.status == 200 && !_stop) {
cursor = ParseReply(response.data);
@ -203,7 +203,7 @@ void CategoryGrabber::Search(const std::string &)
params = {{"first", "100"},
{"after", cursor},
{"query", _searchString}};
response = SendGetRequest(*_token, uri, path, params);
response = SendGetRequest(*_token, uri, path, params, true);
emit CategoryCountUpdated(_categoryMap.size() - startCount);
}
}
@ -217,7 +217,7 @@ void CategoryGrabber::GetAll()
static std::string cursor;
httplib::Params params = {{"first", "100"}, {"after", cursor}};
auto response = SendGetRequest(*_token, uri, path, params);
auto response = SendGetRequest(*_token, uri, path, params, true);
while (response.status == 200 && !_stop) {
cursor = ParseReply(response.data);
@ -225,7 +225,7 @@ void CategoryGrabber::GetAll()
break; // End of category list
}
params = {{"first", "100"}, {"after", cursor}};
response = SendGetRequest(*_token, uri, path, params);
response = SendGetRequest(*_token, uri, path, params, true);
emit CategoryCountUpdated(_categoryMap.size());
}
}

View File

@ -37,7 +37,7 @@ std::string TwitchChannel::GetUserID(const TwitchToken &token) const
}
auto res = SendGetRequest(token, "https://api.twitch.tv",
"/helix/users", {{"login", _name}});
"/helix/users", {{"login", _name}}, true);
if (res.status == 400) {
userIDCache[_name] = "invalid";

View File

@ -136,7 +136,7 @@ TwitchPointsRewardSelection::GetPointsRewards(
auto response = SendGetRequest(*token, "https://api.twitch.tv",
"/helix/channel_points/custom_rewards",
params);
params, true);
if (response.status != 200) {
blog(LOG_WARNING,

View File

@ -1,4 +1,5 @@
#include "twitch-helpers.hpp"
#include "plugin-state-helpers.hpp"
#include "token.hpp"
#include <log-helper.hpp>
@ -65,6 +66,12 @@ static bool cacheIsValid(const std::map<Args, CacheEntry> &cache,
return it != cache.end() && !cacheIsTooOld(it->second);
}
static void cleanupCache(std::map<Args, CacheEntry> &cache, std::mutex &mtx)
{
std::lock_guard<std::mutex> lock(mtx);
cache.clear();
}
static httplib::Headers getTokenRequestHeaders(const std::string &token)
{
return {
@ -104,9 +111,10 @@ static RequestResult processResult(const httplib::Result &response,
return result;
}
RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params)
static RequestResult sendGetRequest(const TwitchToken &token,
const std::string &uri,
const std::string &path,
const httplib::Params &params)
{
httplib::Client cli(uri);
auto tokenStr = token.GetToken();
@ -130,7 +138,11 @@ RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
{
static std::map<Args, CacheEntry> cache;
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
[[maybe_unused]] static bool _ = []() {
AddPluginCleanupStep([]() { cleanupCache(cache, mtx); });
return true;
}();
auto tokenStr = token.GetToken();
if (!tokenStr) {
@ -140,21 +152,27 @@ RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
auto headers = getTokenRequestHeaders(*tokenStr);
Args args(uri, path, "", params, headers);
if (useCache && cacheIsValid(cache, args)) {
if (!useCache) {
return sendGetRequest(token, uri, path, params);
}
std::lock_guard<std::mutex> lock(mtx);
if (cacheIsValid(cache, args)) {
auto it = cache.find(args);
return it->second.result;
}
auto result = SendGetRequest(token, uri, path, params);
auto result = sendGetRequest(token, uri, path, params);
cache[args] = {result};
return result;
}
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data)
static RequestResult sendPostRequest(const TwitchToken &token,
const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data)
{
httplib::Client cli(uri);
auto tokenStr = token.GetToken();
@ -182,7 +200,11 @@ RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
{
static std::map<Args, CacheEntry> cache;
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
[[maybe_unused]] static bool _ = []() {
AddPluginCleanupStep([]() { cleanupCache(cache, mtx); });
return true;
}();
auto tokenStr = token.GetToken();
if (!tokenStr) {
@ -193,20 +215,27 @@ RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
auto body = getRequestBody(data);
Args args(uri, path, body, params, headers);
if (useCache && cacheIsValid(cache, args)) {
if (!useCache) {
return sendPostRequest(token, uri, path, params, data);
}
std::lock_guard<std::mutex> lock(mtx);
if (cacheIsValid(cache, args)) {
auto it = cache.find(args);
return it->second.result;
}
auto result = SendPostRequest(token, uri, path, params, data);
auto result = sendPostRequest(token, uri, path, params, data);
cache[args] = {result};
return result;
}
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params, const OBSData &data)
static RequestResult sendPutRequest(const TwitchToken &token,
const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data)
{
httplib::Client cli(uri);
auto tokenStr = token.GetToken();
@ -234,7 +263,11 @@ RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
{
static std::map<Args, CacheEntry> cache;
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
[[maybe_unused]] static bool _ = []() {
AddPluginCleanupStep([]() { cleanupCache(cache, mtx); });
return true;
}();
auto tokenStr = token.GetToken();
if (!tokenStr) {
@ -245,21 +278,27 @@ RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
auto body = getRequestBody(data);
Args args(uri, path, body, params, headers);
if (useCache && cacheIsValid(cache, args)) {
if (!useCache) {
return sendPutRequest(token, uri, path, params, data);
}
std::lock_guard<std::mutex> lock(mtx);
if (cacheIsValid(cache, args)) {
auto it = cache.find(args);
return it->second.result;
}
auto result = SendPutRequest(token, uri, path, params, data);
auto result = sendPutRequest(token, uri, path, params, data);
cache[args] = {result};
return result;
}
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data)
static RequestResult sendPatchRequest(const TwitchToken &token,
const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data)
{
httplib::Client cli(uri);
auto tokenStr = token.GetToken();
@ -287,7 +326,11 @@ RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
{
static std::map<Args, CacheEntry> cache;
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
[[maybe_unused]] static bool _ = []() {
AddPluginCleanupStep([]() { cleanupCache(cache, mtx); });
return true;
}();
auto tokenStr = token.GetToken();
if (!tokenStr) {
@ -298,20 +341,26 @@ RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
auto body = getRequestBody(data);
Args args(uri, path, body, params, headers);
if (useCache && cacheIsValid(cache, args)) {
if (!useCache) {
return sendPatchRequest(token, uri, path, params, data);
}
std::lock_guard<std::mutex> lock(mtx);
if (cacheIsValid(cache, args)) {
auto it = cache.find(args);
return it->second.result;
}
auto result = SendPatchRequest(token, uri, path, params, data);
auto result = sendPatchRequest(token, uri, path, params, data);
cache[args] = {result};
return result;
}
RequestResult SendDeleteRequest(const TwitchToken &token,
const std::string &uri, const std::string &path,
const httplib::Params &params)
static RequestResult sendDeleteRequest(const TwitchToken &token,
const std::string &uri,
const std::string &path,
const httplib::Params &params)
{
httplib::Client cli(uri);
auto tokenStr = token.GetToken();

View File

@ -15,45 +15,30 @@ struct RequestResult {
const char *GetClientID();
// These functions do *not* use or create RequestResult cache entries
// These functions can cache the RequestResult for 10s
RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params = {});
const httplib::Params &params = {},
bool useCache = false);
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params = {},
const OBSData &data = nullptr);
const OBSData &data = nullptr,
bool useCache = false);
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params = {},
const OBSData &data = nullptr);
const OBSData &data = nullptr,
bool useCache = false);
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params = {},
const OBSData &data = nullptr);
RequestResult SendDeleteRequest(const TwitchToken &token,
const std::string &uri, const std::string &path,
const httplib::Params &params = {});
// These functions will cache the RequestResult for 10s
// Note that the cache will be reported as a "memory leak" on OBS shutdown
RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params, bool useCache);
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data, bool useCache);
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params, const OBSData &data,
bool useCache);
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data, bool useCache);
const OBSData &data = nullptr,
bool useCache = false);
// Helper functions to set temp var values
void SetJsonTempVars(const std::string &jsonStr,
std::function<void(const char *, const char *)> setVarFunc);
void SetJsonTempVars(obs_data_t *data,