mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-27 01:45:35 -05:00
cache server icon results
This commit is contained in:
parent
e74e56e8ff
commit
ff5af54b07
2 changed files with 139 additions and 1 deletions
|
@ -97,4 +97,140 @@ namespace server {
|
|||
ServerPromise<ServerModsList> getMods(ModsQuery const& query);
|
||||
ServerPromise<ServerModMetadata> getMod(std::string const& id);
|
||||
ServerPromise<ByteVector> getModLogo(std::string const& id);
|
||||
|
||||
// Caching for server endpoints
|
||||
namespace impl_cache {
|
||||
template <class R, class Q>
|
||||
struct ExtractServerReqParams {
|
||||
using Result = R;
|
||||
using Query = Q;
|
||||
ExtractServerReqParams(ServerPromise<R>(*)(Q const&)) {}
|
||||
};
|
||||
|
||||
template <auto F>
|
||||
class ServerResultCache final {
|
||||
public:
|
||||
using Extract = decltype(ExtractServerReqParams(F));
|
||||
using Result = Extract::Result;
|
||||
using Query = Extract::Query;
|
||||
|
||||
private:
|
||||
std::mutex m_cachedMutex;
|
||||
// The result and the query used for cached value
|
||||
std::optional<std::pair<Result, Query>> m_cached;
|
||||
|
||||
ServerPromise<Result> fetch(Query&& query) {
|
||||
return ServerPromise<Result>([this, query = std::move(query)](auto resolve, auto reject, auto progress, auto cancelled) {
|
||||
F(Query(query))
|
||||
.then([this, resolve, query = std::move(query)](auto res) {
|
||||
std::unique_lock lock(m_cachedMutex);
|
||||
m_cached = { res, query };
|
||||
lock.unlock();
|
||||
|
||||
resolve(res);
|
||||
})
|
||||
.expect([reject](auto err) {
|
||||
reject(err);
|
||||
})
|
||||
.progress([progress](auto prog) {
|
||||
progress(prog);
|
||||
})
|
||||
.link(cancelled);
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
ServerPromise<Result> get(Query&& query) {
|
||||
std::unique_lock lock(m_cachedMutex);
|
||||
// Return cached value if there is one and the query matches
|
||||
if (m_cached && m_cached->second == query) {
|
||||
auto cached = m_cached->first;
|
||||
lock.unlock();
|
||||
return ServerPromise<Result>([cached = std::move(cached)](auto resolve, auto) {
|
||||
resolve(std::move(cached));
|
||||
});
|
||||
}
|
||||
lock.unlock();
|
||||
return this->fetch(std::move(query));
|
||||
}
|
||||
|
||||
ServerPromise<Result> refetch(Query&& query) {
|
||||
// Clear cache
|
||||
std::unique_lock lock(m_cachedMutex);
|
||||
m_cached.reset();
|
||||
lock.unlock();
|
||||
|
||||
// Fetch new value
|
||||
return this->fetch(std::move(query));
|
||||
}
|
||||
};
|
||||
|
||||
template <auto F>
|
||||
class ServerMultiResultCache final {
|
||||
public:
|
||||
using Extract = decltype(ExtractServerReqParams(F));
|
||||
using Result = Extract::Result;
|
||||
using Query = Extract::Query;
|
||||
|
||||
private:
|
||||
std::mutex m_queriesMutex;
|
||||
std::map<Query, Result> m_queries;
|
||||
|
||||
ServerPromise<Result> fetch(Query const& query) {
|
||||
return ServerPromise<Result>([this, query = Query(query)](auto resolve, auto reject, auto progress, auto cancelled) {
|
||||
F(Query(query))
|
||||
.then([this, resolve, query = std::move(query)](auto res) {
|
||||
std::unique_lock lock(m_queriesMutex);
|
||||
m_queries[std::move(query)] = res;
|
||||
lock.unlock();
|
||||
|
||||
resolve(res);
|
||||
})
|
||||
.expect([reject](auto err) {
|
||||
reject(err);
|
||||
})
|
||||
.progress([progress](auto prog) {
|
||||
progress(prog);
|
||||
})
|
||||
.link(cancelled);
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
ServerPromise<Result> get(Query const& query) {
|
||||
std::unique_lock lock(m_queriesMutex);
|
||||
// Return cached value if there is one and the query matches
|
||||
if (m_queries.contains(query)) {
|
||||
auto cached = m_queries.at(query);
|
||||
lock.unlock();
|
||||
return ServerPromise<Result>([cached = std::move(cached)](auto resolve, auto) {
|
||||
resolve(std::move(cached));
|
||||
});
|
||||
}
|
||||
lock.unlock();
|
||||
return this->fetch(std::move(query));
|
||||
}
|
||||
|
||||
ServerPromise<Result> refetch(Query const& query) {
|
||||
// Clear cache for this query only
|
||||
std::unique_lock lock (m_queriesMutex);
|
||||
m_queries.erase(query);
|
||||
lock.unlock();
|
||||
|
||||
// Fetch new value
|
||||
return this->fetch(std::move(query));
|
||||
}
|
||||
|
||||
// Clear all caches
|
||||
void invalidateAll() {
|
||||
std::unique_lock _(m_queriesMutex);
|
||||
m_queries.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// todo: default shared caching for endpoints for all users
|
||||
// todo: (so it can be automatically cleared for example after leaving the geode layer)
|
||||
// template <auto F>
|
||||
// impl_cache::ServerResultCache<F> sharedCache() {}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,8 @@ protected:
|
|||
std::string m_modID;
|
||||
CCNode* m_sprite = nullptr;
|
||||
EventListener<PromiseEventFilter<ByteVector, server::ServerError>> m_listener;
|
||||
// todo: use shared cache once impl'd
|
||||
static inline server::impl_cache::ServerMultiResultCache<&server::getModLogo> s_cache = {};
|
||||
|
||||
bool init(std::string const& id, bool fetch) {
|
||||
if (!CCNode::init())
|
||||
|
@ -93,7 +95,7 @@ protected:
|
|||
this->setSprite(CCSprite::create("loadingCircle.png"));
|
||||
static_cast<CCSprite*>(m_sprite)->setBlendFunc({ GL_ONE, GL_ONE });
|
||||
m_sprite->runAction(CCRepeatForever::create(CCRotateBy::create(1.f, 360.f)));
|
||||
m_listener.setFilter(server::getModLogo(id).listen());
|
||||
m_listener.setFilter(s_cache.get(id).listen());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue