aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzousar <[email protected]>2025-09-24 22:12:11 -0600
committerzousar <[email protected]>2025-09-24 22:12:11 -0600
commitebfade799e7199f7c6b981f17a55ed67d4323c41 (patch)
treedd04a483893bb3b9ab4c125fa61f967978ce67b3 /src
parentAdjust the responses from PUT commands (diff)
downloadzen-ebfade799e7199f7c6b981f17a55ed67d4323c41.tar.xz
zen-ebfade799e7199f7c6b981f17a55ed67d4323c41.zip
Report Incomplete Records To Client
When requesting partial records, report back when a record is incomplete via an "Incomplete" array of bools that is a sibling to the "Result" array for batch/rpc operations, or via the HttpResponseCode::PartialContent status code for individual record requests.
Diffstat (limited to 'src')
-rw-r--r--src/zenserver/cache/httpstructuredcache.cpp8
-rw-r--r--src/zenstore/cache/cacherpc.cpp44
2 files changed, 44 insertions, 8 deletions
diff --git a/src/zenserver/cache/httpstructuredcache.cpp b/src/zenserver/cache/httpstructuredcache.cpp
index dc14465de..bc3f4ee20 100644
--- a/src/zenserver/cache/httpstructuredcache.cpp
+++ b/src/zenserver/cache/httpstructuredcache.cpp
@@ -821,7 +821,8 @@ HttpStructuredCacheService::HandleGetCacheRecord(HttpServerRequest& Request, con
const bool SkipData = EnumHasAllFlags(PolicyFromUrl, CachePolicy::SkipData);
const bool PartialRecord = EnumHasAllFlags(PolicyFromUrl, CachePolicy::PartialRecord);
- bool Success = false;
+ bool Success = false;
+ uint32_t MissingCount = 0;
ZenCacheValue ClientResultValue;
if (!EnumHasAnyFlags(PolicyFromUrl, CachePolicy::Query))
{
@@ -844,7 +845,6 @@ HttpStructuredCacheService::HandleGetCacheRecord(HttpServerRequest& Request, con
if (ContentType == ZenContentType::kCbObject)
{
CbPackage Package;
- uint32_t MissingCount = 0;
CbValidateError ValidateError = CbValidateError::None;
if (CbObject PackageObject = ValidateAndReadCompactBinaryObject(std::move(ClientResultValue.Value), ValidateError);
ValidateError == CbValidateError::None)
@@ -936,7 +936,9 @@ HttpStructuredCacheService::HandleGetCacheRecord(HttpServerRequest& Request, con
else
{
// kCbPackage handled SkipData when constructing the ClientResultValue, kcbObject ignores SkipData
- return Request.WriteResponse(HttpResponseCode::OK, ClientResultValue.Value.GetContentType(), ClientResultValue.Value);
+ return Request.WriteResponse((MissingCount == 0) ? HttpResponseCode::OK : HttpResponseCode::PartialContent,
+ ClientResultValue.Value.GetContentType(),
+ ClientResultValue.Value);
}
}
else if (!HasUpstream || !EnumHasAllFlags(PolicyFromUrl, CachePolicy::QueryRemote))
diff --git a/src/zenstore/cache/cacherpc.cpp b/src/zenstore/cache/cacherpc.cpp
index 77ca26409..fc34a28cf 100644
--- a/src/zenstore/cache/cacherpc.cpp
+++ b/src/zenstore/cache/cacherpc.cpp
@@ -860,14 +860,10 @@ CacheRpcHandler::HandleRpcGetCacheRecords(const CacheRequestContext& Context, Cb
Key.Hash);
}
}
- if (!Value.Exists && !EnumHasAllFlags(ValuePolicy, CachePolicy::SkipData))
+ if (!Value.Exists)
{
Request.Complete = false;
}
- // Request.Complete does not need to be set to false for upstream SkipData attachments.
- // In the PartialRecord==false case, the upstream will have failed the entire record if any SkipData attachment
- // didn't exist and we will not get here. In the PartialRecord==true case, we do not need to inform the client of
- // any missing SkipData attachments.
}
Request.ElapsedTimeUs += Timer.GetElapsedTimeUs();
}
@@ -883,7 +879,9 @@ CacheRpcHandler::HandleRpcGetCacheRecords(const CacheRequestContext& Context, Cb
ResponsePackage.ReserveAttachments(Requests.size());
+ eastl::fixed_vector<size_t, 4> IncompleteResultIndexes;
ResponseObject.BeginArray("Result"sv);
+ size_t ResultIndex = 0;
for (RecordRequestData& Request : Requests)
{
const CacheKey& Key = Request.Key;
@@ -899,6 +897,12 @@ CacheRpcHandler::HandleRpcGetCacheRecords(const CacheRequestContext& Context, Cb
}
}
+ if (!Request.Complete)
+ {
+ // If requesting a partial record, report back that the record overall is incomplete to the client
+ IncompleteResultIndexes.push_back(ResultIndex);
+ }
+
ZEN_DEBUG("GETCACHERECORD HIT - '{}/{}/{}' {}{} ({}) in {}",
*Namespace,
Key.Bucket,
@@ -935,8 +939,38 @@ CacheRpcHandler::HandleRpcGetCacheRecords(const CacheRequestContext& Context, Cb
m_CacheStats.MissCount++;
}
}
+ ++ResultIndex;
}
ResponseObject.EndArray();
+
+ if (!IncompleteResultIndexes.empty())
+ {
+ size_t IndexIntoIncompleteResultArray = 0;
+ size_t IncompleteResultIndex = IncompleteResultIndexes[IndexIntoIncompleteResultArray];
+ ResultIndex = 0;
+ ResponseObject.BeginArray("Incomplete"sv);
+ for (ResultIndex = 0; ResultIndex < Requests.size(); ++ResultIndex)
+ {
+ if (IncompleteResultIndex == ResultIndex)
+ {
+ ResponseObject.AddBool(true);
+ if (++IndexIntoIncompleteResultArray >= IncompleteResultIndexes.size())
+ {
+ // Set IncompleteResultIndex into a value we can't encounter while marching ResultIndex forward
+ IncompleteResultIndex = 0;
+ }
+ else
+ {
+ IncompleteResultIndex = IncompleteResultIndexes[IndexIntoIncompleteResultArray];
+ }
+ }
+ else
+ {
+ ResponseObject.AddBool(true);
+ }
+ }
+ ResponseObject.EndArray();
+ }
ResponsePackage.SetObject(ResponseObject.Save());
return ResponsePackage;
}