mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-08-24 03:29:58 +00:00
114 lines
3.9 KiB
C++
114 lines
3.9 KiB
C++
// Copyright (c) 2026 Pyxis contributors
|
|
// SPDX-License-Identifier: MIT
|
|
#include "NomadNetCacheFlow.h"
|
|
|
|
namespace UI { namespace LXMF { namespace NomadNet {
|
|
|
|
CacheFlowState NomadNetCacheFlow::begin(const CacheKey& key, std::uint64_t now,
|
|
bool reload) {
|
|
cancel();
|
|
key_ = key;
|
|
now_ = now;
|
|
ExternalVector<std::uint8_t>().swap(page_);
|
|
status_ = reload ? "Invalidating cached page..." : "Checking page cache...";
|
|
lookup_admitted_ = false;
|
|
invalidation_admitted_ = false;
|
|
if (reload) {
|
|
state_ = CacheFlowState::INVALIDATE;
|
|
if (!cache_.busy()) {
|
|
invalidation_admitted_ = cache_.invalidate(key_) == CacheResult::PENDING;
|
|
}
|
|
return state_;
|
|
}
|
|
state_ = CacheFlowState::LOOKUP;
|
|
if (!cache_.busy()) {
|
|
lookup_admitted_ = cache_.beginLookup(key_, now, false) == CacheResult::PENDING;
|
|
if (!lookup_admitted_) {
|
|
state_ = CacheFlowState::NEED_LIVE;
|
|
status_ = "Requesting page...";
|
|
}
|
|
}
|
|
return state_;
|
|
}
|
|
|
|
void NomadNetCacheFlow::service() {
|
|
if (state_ == CacheFlowState::CANCELLED || state_ == CacheFlowState::FAILED)
|
|
return;
|
|
if (cache_.busy()) cache_.service();
|
|
if (state_ == CacheFlowState::INVALIDATE) {
|
|
if (cache_.busy()) return;
|
|
if (!invalidation_admitted_) {
|
|
invalidation_admitted_ = cache_.invalidate(key_) == CacheResult::PENDING;
|
|
return;
|
|
}
|
|
if (cache_.lastResult() == CacheResult::MISS) {
|
|
state_ = CacheFlowState::NEED_LIVE;
|
|
status_ = "Requesting page...";
|
|
} else {
|
|
state_ = CacheFlowState::FAILED;
|
|
status_ = "Page cache invalidation failed";
|
|
}
|
|
return;
|
|
}
|
|
if (state_ != CacheFlowState::LOOKUP || cache_.busy()) return;
|
|
if (!lookup_admitted_) {
|
|
lookup_admitted_ = cache_.beginLookup(key_, now_, false) == CacheResult::PENDING;
|
|
if (!lookup_admitted_) {
|
|
state_ = CacheFlowState::NEED_LIVE;
|
|
status_ = "Requesting page...";
|
|
}
|
|
return;
|
|
}
|
|
if (cache_.lastResult() == CacheResult::HIT && cache_.takeBody(page_)) {
|
|
state_ = CacheFlowState::READY;
|
|
status_ = "Cached page; current reachability not checked";
|
|
} else {
|
|
state_ = CacheFlowState::NEED_LIVE;
|
|
status_ = "Requesting page...";
|
|
}
|
|
}
|
|
|
|
bool NomadNetCacheFlow::acceptLive(const std::vector<std::uint8_t>& body,
|
|
const CacheEligibility& eligibility,
|
|
std::uint64_t now) {
|
|
if (state_ != CacheFlowState::NEED_LIVE || !eligibility.successful ||
|
|
!eligibility.valid || eligibility.partial || eligibility.malformed ||
|
|
eligibility.truncated || eligibility.error || body.empty()) {
|
|
state_ = CacheFlowState::FAILED;
|
|
status_ = "Malformed NomadNet response";
|
|
return false;
|
|
}
|
|
try {
|
|
page_.assign(body.begin(), body.end());
|
|
} catch (const std::bad_alloc&) {
|
|
state_ = CacheFlowState::FAILED;
|
|
status_ = "Page is too large for available memory";
|
|
return false;
|
|
}
|
|
state_ = CacheFlowState::READY;
|
|
status_ = "Page loaded (live)";
|
|
if (cache_eligible(eligibility)) {
|
|
const auto directive = parse_cache_directive(body.data(), body.size());
|
|
if (directive.valid && directive.ttl)
|
|
cache_.beginCommit(key_, body, now, directive.ttl);
|
|
else
|
|
cache_.invalidate(key_);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void NomadNetCacheFlow::cancel() {
|
|
if (cache_.busy()) cache_.cancel();
|
|
ExternalVector<std::uint8_t>().swap(page_);
|
|
if (state_ != CacheFlowState::IDLE) state_ = CacheFlowState::CANCELLED;
|
|
status_.clear();
|
|
}
|
|
|
|
bool NomadNetCacheFlow::takePage(ExternalVector<std::uint8_t>& output) {
|
|
if (!pageReady()) return false;
|
|
output.swap(page_);
|
|
return true;
|
|
}
|
|
|
|
}}} // namespace UI::LXMF::NomadNet
|