mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-31 13:16:39 +00:00
[Databuckets] Nested Caching
This commit is contained in:
+78
-7
@@ -19,6 +19,37 @@ extern WorldDatabase database;
|
|||||||
#error "You must define either ZONE or WORLD"
|
#error "You must define either ZONE or WORLD"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Key: compound cache key (e.g., account_id|character_id|zone_id|instance_id|top_key|full_key)
|
||||||
|
// Value: resolved DataBuckets with extracted nested value
|
||||||
|
static std::unordered_map<std::string, DataBucketsRepository::DataBuckets> g_nested_bucket_cache;
|
||||||
|
|
||||||
|
static std::string MakeNestedCacheKey(const DataBucketKey &k, const std::string &full_key) {
|
||||||
|
return fmt::format(
|
||||||
|
"account_id:{}|character_id:{}|npc_id:{}|bot_id:{}|zone_id:{}|instance_id:{}|top_key:{}|full_key:{}",
|
||||||
|
k.account_id, k.character_id, k.npc_id, k.bot_id, k.zone_id, k.instance_id,
|
||||||
|
Strings::Split(full_key, NESTED_KEY_DELIMITER).front(),
|
||||||
|
full_key
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string MakeNestedCacheKeyPrefix(const DataBucketKey &k, const std::string &top_key) {
|
||||||
|
return fmt::format(
|
||||||
|
"account_id:{}|character_id:{}|npc_id:{}|bot_id:{}|zone_id:{}|instance_id:{}|top_key:{}|",
|
||||||
|
k.account_id, k.character_id, k.npc_id, k.bot_id, k.zone_id, k.instance_id, top_key
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InvalidateNestedCacheForKey(const DataBucketKey &k, const std::string &top_key) {
|
||||||
|
std::string prefix = MakeNestedCacheKeyPrefix(k, top_key);
|
||||||
|
for (auto it = g_nested_bucket_cache.begin(); it != g_nested_bucket_cache.end(); ) {
|
||||||
|
if (it->first.find(prefix) == 0) {
|
||||||
|
it = g_nested_bucket_cache.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time)
|
void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time)
|
||||||
{
|
{
|
||||||
auto k = DataBucketKey{
|
auto k = DataBucketKey{
|
||||||
@@ -136,6 +167,15 @@ void DataBucket::SetData(const DataBucketKey &k_)
|
|||||||
// Serialize JSON back to string
|
// Serialize JSON back to string
|
||||||
b.value = json_value.dump();
|
b.value = json_value.dump();
|
||||||
b.key_ = top_key; // Use the top-level key
|
b.key_ = top_key; // Use the top-level key
|
||||||
|
|
||||||
|
if (CanCache(k_)) {
|
||||||
|
InvalidateNestedCacheForKey(k_, top_key);
|
||||||
|
std::string nested_cache_key = MakeNestedCacheKey(k_, k_.key);
|
||||||
|
auto extracted = ExtractNestedValue(b, k_.key);
|
||||||
|
if (extracted.id > 0) {
|
||||||
|
g_nested_bucket_cache[nested_cache_key] = extracted;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bucket_id) {
|
if (bucket_id) {
|
||||||
@@ -251,7 +291,19 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k_,
|
|||||||
LogDataBuckets("Returning key [{}] value [{}] from cache", e.key_, e.value);
|
LogDataBuckets("Returning key [{}] value [{}] from cache", e.key_, e.value);
|
||||||
|
|
||||||
if (is_nested_key && !k_.key.empty()) {
|
if (is_nested_key && !k_.key.empty()) {
|
||||||
return ExtractNestedValue(e, k_.key);
|
std::string nested_cache_key = MakeNestedCacheKey(k_, k.key);
|
||||||
|
|
||||||
|
auto it = g_nested_bucket_cache.find(nested_cache_key);
|
||||||
|
if (it != g_nested_bucket_cache.end()) {
|
||||||
|
LogDataBucketsDetail("Nested cache hit for key [{}]", nested_cache_key);
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto extracted = ExtractNestedValue(e, k_.key);
|
||||||
|
if (extracted.id > 0) {
|
||||||
|
g_nested_bucket_cache[nested_cache_key] = extracted;
|
||||||
|
}
|
||||||
|
return extracted;
|
||||||
}
|
}
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
@@ -315,23 +367,42 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k_,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the value to the cache if it doesn't exist
|
// Add the value to the cache if it doesn't exist
|
||||||
|
// If cacheable and not found in cache, short-circuit and assume it doesn't exist
|
||||||
if (can_cache) {
|
if (can_cache) {
|
||||||
bool has_cache = false;
|
bool found_in_cache = false;
|
||||||
for (const auto &e : g_data_bucket_cache) {
|
for (const auto &e : g_data_bucket_cache) {
|
||||||
if (e.id == bucket.id) {
|
if (CheckBucketMatch(e, k)) {
|
||||||
has_cache = true;
|
found_in_cache = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_cache) {
|
if (!found_in_cache) {
|
||||||
g_data_bucket_cache.emplace_back(bucket);
|
LogDataBuckets("Cache miss for key [{}] - skipping DB due to CanCache", k.key);
|
||||||
|
return DataBucketsRepository::NewEntity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle nested key extraction
|
// Handle nested key extraction
|
||||||
if (is_nested_key && !k_.key.empty()) {
|
if (is_nested_key && !k_.key.empty()) {
|
||||||
return ExtractNestedValue(bucket, k_.key);
|
if (CanCache(k_)) {
|
||||||
|
std::string nested_cache_key = MakeNestedCacheKey(k_, k.key);
|
||||||
|
|
||||||
|
auto it = g_nested_bucket_cache.find(nested_cache_key);
|
||||||
|
if (it != g_nested_bucket_cache.end()) {
|
||||||
|
LogDataBucketsDetail("Nested cache hit for key [{}]", nested_cache_key);
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto extracted = ExtractNestedValue(bucket, k_.key);
|
||||||
|
if (extracted.id > 0) {
|
||||||
|
g_nested_bucket_cache[nested_cache_key] = extracted;
|
||||||
|
}
|
||||||
|
return extracted;
|
||||||
|
} else {
|
||||||
|
// Not cacheable, just extract and return
|
||||||
|
return ExtractNestedValue(bucket, k_.key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bucket;
|
return bucket;
|
||||||
|
|||||||
Reference in New Issue
Block a user