29 std::string_view name;
44 using key_t = uint32_t;
45 using local_id_t = std::string;
46 using result_t = std::tuple<long, key_t>;
47 using item_map_t = std::map<key_t, local_id_t>;
49 using AsyncList = std::vector<std::future<result_t>>;
59 using namespace std::chrono_literals;
60 using namespace std::chrono;
62 auto sysWriteTime = time_point_cast<system_clock::duration>(
63 fileTimePoint - decltype(fileTimePoint)::clock::now() +
74 return fileClockToSystemClock(std::filesystem::last_write_time(filePath));
80 std::error_code mEc{};
81 std::string mRootURI{};
83 mutable file_status mStoreStatus{};
86 item_map_t mItemMap{};
88 AsyncList mAsyncList{};
91 std::chrono::system_clock::duration mCacheValidDuration{};
93 void asyncFetchItem(item_map_t::value_type& item) {
94 auto itemPath = mStoreRoot;
95 auto tempPath = mStoreRoot;
96 auto itemName = translateItemLocalId(item.second);
97 itemPath.append(itemName);
98 tempPath.append(
'.' + itemName);
99 if (!itemPath.empty()) {
100 std::optional<time_t> cacheFileTime{};
101 if (exists(itemPath))
102 if (cacheFileTime = cacheTime(itemPath); !cacheFileTime) {
103 cacheLoaded.transmit(item.first, 503);
107 mAsyncList.emplace_back(
108 std::async(std::launch::async, fetch, item.first, constructUrl(item.second), itemPath, tempPath,
110 CommonSignals::getCommonSignals().frameSignal.connect(mFrameProtocol);
126 WebCache(
const std::string &rootUri,
const path &xdgDir,
const std::string &storeRoot,
127 std::chrono::system_clock::duration duration);
129 template<
typename It>
130 WebCache(
const std::string &rootUri,
const path &xdgDir,
const std::string &storeRoot,
131 std::chrono::system_clock::duration duration, It first, It last)
132 :
WebCache(rootUri, xdgDir, storeRoot, duration) {
133 setCacheItem(first, last);
142 mItemMap[key] = std::move(localId);
151 template<
typename It>
153 while (first != last) {
154 setCacheItem(first->key, std::string(first->name));
164 if (!status_known(mStoreStatus))
165 mStoreStatus = status(mStoreRoot);
167 return exists(mStoreStatus) && is_directory(mStoreStatus);
187 if (
auto item = mItemMap.find(key); item != mItemMap.end()) {
188 auto itemPath = mStoreRoot;
189 itemPath.append(translateItemLocalId(item->second));
201 if (
auto itemPath = itemLocalPath(key); !itemPath.empty()) {
202 if (exists(itemPath))
215 auto cacheFiletime = fileClockToSystemClock(std::filesystem::last_write_time(itemPath));
216 auto cacheFileAge = std::chrono::system_clock::now() - cacheFiletime;
217 if (cacheFileAge > mCacheValidDuration)
218 return std::chrono::system_clock::to_time_t(cacheFiletime);
230 static WebCache::result_t
231 fetch(WebCache::key_t key,
const std::string &itemUrl,
const path &itemPath,
const path &tempPath,
232 std::optional<time_t> cacheFileTime);
241 return mRootURI + localId;
244 bool itemKnown(key_t key) {
245 return mItemMap.find(key) != mItemMap.end();
252 AsyncList asyncList{};
253 std::lock_guard<std::mutex> lockGuard{mMutex};
255 for (
auto &item : mItemMap) {
256 asyncFetchItem(item);
258 return !mAsyncList.empty();
261 bool fetchItem(key_t key) {
262 auto item = mItemMap.find(key);
263 if (item != mItemMap.end()) {
264 asyncFetchItem(*item);
266 return !mAsyncList.empty();
269 bool pendingFutures()
const {
270 return !mAsyncList.empty();
273 bool processFutures() {
274 if (mAsyncList.empty())
277 std::lock_guard<std::mutex> lockGuard{mMutex};
278 std::chrono::milliseconds span{100};
279 for (
auto &item : mAsyncList) {
282 if (
auto futureStatus = item.wait_for(span); futureStatus == std::future_status::ready) {
283 auto[status, key] = item.get();
284 cacheLoaded.transmit(key,status);
287 }
catch (
const std::exception &e) {
288 std::cout << __PRETTY_FUNCTION__ <<
' ' << e.what() <<
'\n';
292 mAsyncList.erase(std::remove_if(mAsyncList.begin(), mAsyncList.end(),
293 [](std::future<result_t> &f) ->
bool {
return !f.valid(); }),
296 return !mAsyncList.empty();
A convenience structure that composes Signal and Slot types from a protocol signature, and provides a Slot factory.
Definition: Signals.h:122
path itemLocalPath(key_t key)
Get the filesystem path of a local item by key.
Definition: WebCache.h:186
static std::chrono::system_clock::time_point fileClockToSystemClock(const path &filePath)
Convert a filesystem time to a system clock time point.
Definition: WebCache.h:73
virtual std::string translateItemLocalId(local_id_t localId)
Translate a local id.
Definition: WebCache.h:177
std::optional< path > localItemExists(key_t key)
Get the local path to an item if it is known and exists in the local store.
Definition: WebCache.h:200
std::shared_ptr< Slot< Args... > > slot_type
Composed Slot type.
Definition: Signals.h:123
Fetch web resources caching them in the local filesystem following XDG specifications.
Definition: WebCache.h:40
void setCacheItem(key_t key, local_id_t localId)
Add or change a cache item.
Definition: WebCache.h:141
bool storeExists() const
Test to see if the store exists.
Definition: WebCache.h:163
bool fetchAll()
Fetch all cache items which have not been previously cached or have expired cache times...
Definition: WebCache.h:251
static std::chrono::system_clock::time_point fileClockToSystemClock(T fileTimePoint)
Convert a filesystem time to a system clock time point.
Definition: WebCache.h:58
Definition: WebCache.h:27
void setCacheItem(It first, It last)
Add or change cache items from a container.
Definition: WebCache.h:152
std::optional< time_t > cacheTime(const path &itemPath)
Get the time the item was cached if the cache time has expired.
Definition: WebCache.h:214
ToDo: There is an issue that the initial scroll interaction is lost if the click/press lands on a Wid...
Definition: CelestialOverlay.cpp:13
The transmitter portion of a Signal-Slot transmitter receiver pair.
Definition: Signals.h:40
virtual std::string constructUrl(const local_id_t &localId)
Construct the appropriate URL for the item.
Definition: WebCache.h:240
std::mutex mMutex
Mutex for locking the WebFileCache.
Definition: WebCache.h:84