diff options
| author | Stefan Boberg <[email protected]> | 2026-03-20 21:31:06 +0100 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2026-03-20 21:31:06 +0100 |
| commit | fde1a25fca225ed32cbd462ab65dcad14064e139 (patch) | |
| tree | 1612b4f70a780e4ac9e5d8a15ccd6eedb05d1558 /src/zenserver/storage/projectstore | |
| parent | Fix flaky DroppedMessageDetection test by removing timing dependency (diff) | |
| parent | auth fail no cache (#871) (diff) | |
| download | zen-sb/sessionize.tar.xz zen-sb/sessionize.zip | |
Merge remote-tracking branch 'origin/main' into sb/sessionizesb/sessionize
Diffstat (limited to 'src/zenserver/storage/projectstore')
| -rw-r--r-- | src/zenserver/storage/projectstore/httpprojectstore.cpp | 244 |
1 files changed, 152 insertions, 92 deletions
diff --git a/src/zenserver/storage/projectstore/httpprojectstore.cpp b/src/zenserver/storage/projectstore/httpprojectstore.cpp index 2fa10a292..03b8aa382 100644 --- a/src/zenserver/storage/projectstore/httpprojectstore.cpp +++ b/src/zenserver/storage/projectstore/httpprojectstore.cpp @@ -546,7 +546,7 @@ namespace { Host.empty() ? OverrideHost : Host, /*Quiet*/ false, /*Unattended*/ false, - /*Hidden*/ true); + /*Hidden*/ false); TokenProviderMaybe) { TokenProvider = TokenProviderMaybe.value(); @@ -636,18 +636,6 @@ namespace { return Result; } - std::pair<HttpResponseCode, std::string> ConvertResult(const RemoteProjectStore::Result& Result) - { - if (Result.ErrorCode == 0) - { - return {HttpResponseCode::OK, Result.Text}; - } - return {static_cast<HttpResponseCode>(Result.ErrorCode), - Result.Reason.empty() ? Result.Text - : Result.Text.empty() ? Result.Reason - : fmt::format("{}: {}", Result.Reason, Result.Text)}; - } - static uint64_t GetMaxMemoryBufferSize(size_t MaxBlockSize, bool BoostWorkerMemory) { return BoostWorkerMemory ? (MaxBlockSize + 16u * 1024u) : 1024u * 1024u; @@ -2671,44 +2659,38 @@ HttpProjectService::HandleOplogLoadRequest(HttpRouterRequest& Req) WorkerThreadPool& WorkerPool = GetLargeWorkerPool(EWorkloadType::Background); - RemoteProjectStore::LoadContainerResult ContainerResult = BuildContainer( - m_CidStore, - *Project, - *Oplog, - WorkerPool, - MaxBlockSize, - MaxChunkEmbedSize, - MaxChunksPerBlock, - ChunkFileSizeLimit, - /* BuildBlocks */ false, - /* IgnoreMissingAttachments */ false, - /* AllowChunking*/ false, - [](CompressedBuffer&&, ChunkBlockDescription&&) {}, - [](const IoHash&, TGetAttachmentBufferFunc&&) {}, - [](std::vector<std::pair<IoHash, FetchChunkFunc>>&&) {}, - /* EmbedLooseFiles*/ false); - - if (ContainerResult.ErrorCode == 0) - { - return HttpReq.WriteResponse(HttpResponseCode::OK, ContainerResult.ContainerObject); - } - else - { - ZEN_DEBUG("Request {}: '{}' failed with {}. Reason: `{}`", - ToString(HttpReq.RequestVerb()), - HttpReq.QueryString(), - ContainerResult.ErrorCode, - ContainerResult.Reason); - - if (ContainerResult.Reason.empty()) + try + { + CbObject ContainerObject = BuildContainer( + m_CidStore, + *Project, + *Oplog, + WorkerPool, + MaxBlockSize, + MaxChunksPerBlock, + MaxChunkEmbedSize, + ChunkFileSizeLimit, + /* BuildBlocks */ false, + /* IgnoreMissingAttachments */ false, + /* AllowChunking*/ false, + [](CompressedBuffer&&, ChunkBlockDescription&&) {}, + [](const IoHash&, TGetAttachmentBufferFunc&&) {}, + [](std::vector<std::pair<IoHash, FetchChunkFunc>>&&) {}, + /* EmbedLooseFiles*/ false); + return HttpReq.WriteResponse(HttpResponseCode::OK, ContainerObject); + } + catch (const HttpClientError& HttpEx) + { + if (HttpEx.GetInternalErrorCode() != HttpClientErrorCode::kOK) { - return HttpReq.WriteResponse(HttpResponseCode(ContainerResult.ErrorCode)); + return HttpReq.WriteResponse(HttpResponseCode::InternalServerError, HttpContentType::kText, HttpEx.what()); } else { - return HttpReq.WriteResponse(HttpResponseCode(ContainerResult.ErrorCode), HttpContentType::kText, ContainerResult.Reason); + return HttpReq.WriteResponse(HttpEx.GetHttpResponseCode(), HttpContentType::kText, HttpEx.what()); } } + // Let server request handler deal with other exceptions } void @@ -2872,32 +2854,70 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req) WorkerThreadPool& NetworkWorkerPool = Workers->GetNetworkPool(); Context.ReportMessage(fmt::format("{}", Workers->GetWorkersInfo())); - RemoteProjectStore::Result Result = LoadOplog(LoadOplogContext{ - .ChunkStore = m_CidStore, - .RemoteStore = *RemoteStoreResult->Store, - .OptionalCache = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->Cache.get() : nullptr, - .CacheBuildId = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->BuildsId : Oid::Zero, - .OptionalCacheStats = RemoteStoreResult->OptionalCache ? &RemoteStoreResult->OptionalCache->Stats : nullptr, - .Oplog = *Oplog, - .NetworkWorkerPool = NetworkWorkerPool, - .WorkerPool = WorkerPool, - .ForceDownload = Force, - .IgnoreMissingAttachments = IgnoreMissingAttachments, - .CleanOplog = CleanOplog, - .PartialBlockRequestMode = PartialBlockRequestMode, - .PopulateCache = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->Populate : false, - .StoreLatencySec = RemoteStoreResult->LatencySec, - .StoreMaxRangeCountPerRequest = RemoteStoreResult->MaxRangeCountPerRequest, - .CacheLatencySec = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->LatencySec : -1.0, - .CacheMaxRangeCountPerRequest = - RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->MaxRangeCountPerRequest : 0, - .OptionalJobContext = &Context}); - auto Response = ConvertResult(Result); - ZEN_INFO("LoadOplog: Status: {} '{}'", ToString(Response.first), Response.second); - if (!IsHttpSuccessCode(Response.first)) + + try { - throw JobError(Response.second.empty() ? fmt::format("Status: {}", ToString(Response.first)) : Response.second, - (int)Response.first); + LoadOplog(LoadOplogContext{ + .ChunkStore = m_CidStore, + .RemoteStore = *RemoteStoreResult->Store, + .OptionalCache = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->Cache.get() : nullptr, + .CacheBuildId = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->BuildsId : Oid::Zero, + .OptionalCacheStats = RemoteStoreResult->OptionalCache ? &RemoteStoreResult->OptionalCache->Stats : nullptr, + .Oplog = *Oplog, + .NetworkWorkerPool = NetworkWorkerPool, + .WorkerPool = WorkerPool, + .ForceDownload = Force, + .IgnoreMissingAttachments = IgnoreMissingAttachments, + .CleanOplog = CleanOplog, + .PartialBlockRequestMode = PartialBlockRequestMode, + .PopulateCache = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->Populate : false, + .StoreLatencySec = RemoteStoreResult->LatencySec, + .StoreMaxRangeCountPerRequest = RemoteStoreResult->MaxRangeCountPerRequest, + .CacheLatencySec = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->LatencySec : -1.0, + .CacheMaxRangeCountPerRequest = + RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->MaxRangeCountPerRequest : 0, + .OptionalJobContext = &Context}); + } + catch (const HttpClientError& HttpEx) + { + if (HttpEx.GetInternalErrorCode() != HttpClientErrorCode::kOK) + { + throw JobError(fmt::format("Failed due to an http exception (Err: {}): {}", + static_cast<int>(HttpEx.GetInternalErrorCode()), + HttpEx.what()), + static_cast<int>(HttpEx.GetResponseClass())); + } + else + { + throw JobError(fmt::format("Failed due to an http exception (Status: {}): {}", + static_cast<int>(HttpEx.GetHttpResponseCode()), + HttpEx.what()), + static_cast<int>(HttpEx.GetHttpResponseCode())); + } + } + catch (const AssertException& AssertEx) + { + throw JobError(fmt::format("Failed due to an assert exception: {}", AssertEx.FullDescription()), + static_cast<int>(HttpResponseCode::InternalServerError)); + } + catch (const std::system_error& SysEx) + { + throw JobError(fmt::format("Failed due to a system error ({}): {}", SysEx.code().value(), SysEx.what()), + SysEx.code().value()); + } + catch (const std::exception& Ex) + { + throw JobError(fmt::format("Failed due to an exception: {}", Ex.what()), + static_cast<int>(HttpResponseCode::InternalServerError)); + } + + if (Context.IsCancelled()) + { + ZEN_INFO("LoadOplog: Operation cancelled"); + } + else + { + ZEN_INFO("LoadOplog: Complete"); } }); @@ -2961,26 +2981,63 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req) WorkerThreadPool& WorkerPool = Workers->GetIOWorkerPool(); WorkerThreadPool& NetworkWorkerPool = Workers->GetNetworkPool(); - RemoteProjectStore::Result Result = SaveOplog(m_CidStore, - *ActualRemoteStore, - *Project, - *Oplog, - NetworkWorkerPool, - WorkerPool, - MaxBlockSize, - MaxChunksPerBlock, - MaxChunkEmbedSize, - ChunkFileSizeLimit, - EmbedLooseFile, - Force, - IgnoreMissingAttachments, - &Context); - auto Response = ConvertResult(Result); - ZEN_INFO("SaveOplog: Status: {} '{}'", ToString(Response.first), Response.second); - if (!IsHttpSuccessCode(Response.first)) + try + { + SaveOplog(m_CidStore, + *ActualRemoteStore, + *Project, + *Oplog, + NetworkWorkerPool, + WorkerPool, + MaxBlockSize, + MaxChunksPerBlock, + MaxChunkEmbedSize, + ChunkFileSizeLimit, + EmbedLooseFile, + Force, + IgnoreMissingAttachments, + &Context); + } + catch (const HttpClientError& HttpEx) + { + if (HttpEx.GetInternalErrorCode() != HttpClientErrorCode::kOK) + { + throw JobError(fmt::format("Failed due to an http exception (Err: {}): {}", + static_cast<int>(HttpEx.GetInternalErrorCode()), + HttpEx.what()), + static_cast<int>(HttpEx.GetResponseClass())); + } + else + { + throw JobError(fmt::format("Failed due to an http exception (Status: {}): {}", + static_cast<int>(HttpEx.GetHttpResponseCode()), + HttpEx.what()), + static_cast<int>(HttpEx.GetHttpResponseCode())); + } + } + catch (const AssertException& AssertEx) + { + throw JobError(fmt::format("Failed due to an assert exception: {}", AssertEx.FullDescription()), + static_cast<int>(HttpResponseCode::InternalServerError)); + } + catch (const std::system_error& SysEx) + { + throw JobError(fmt::format("Failed due to a system error ({}): {}", SysEx.code().value(), SysEx.what()), + SysEx.code().value()); + } + catch (const std::exception& Ex) + { + throw JobError(fmt::format("Failed due to an exception: {}", Ex.what()), + static_cast<int>(HttpResponseCode::InternalServerError)); + } + + if (Context.IsCancelled()) + { + ZEN_INFO("SaveOplog: Operation cancelled"); + } + else { - throw JobError(Response.second.empty() ? fmt::format("Status: {}", ToString(Response.first)) : Response.second, - (int)Response.first); + ZEN_INFO("SaveOplog: Complete"); } }); @@ -3104,8 +3161,10 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req) continue; } - std::error_code Ec; - const std::filesystem::path FilePath = std::filesystem::canonical(Project->RootDir / ServerPath, Ec); + std::error_code Ec; + // Long paths require MakeSafeAbsolutePath otherwise canonical will yield an error code + const std::filesystem::path SafeAbsFilePath = MakeSafeAbsolutePath(Project->RootDir / ServerPath); + const std::filesystem::path FilePath = std::filesystem::canonical(SafeAbsFilePath, Ec); if (Ec) { @@ -3126,7 +3185,8 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req) } BasicFile DataFile; - DataFile.Open(FilePath, BasicFile::Mode::kRead, Ec); + // Must use SafeAbsFilePath because canonical will have removed leading chars for handling long paths + DataFile.Open(SafeAbsFilePath, BasicFile::Mode::kRead, Ec); if (Ec) { |