mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-04 16:56:53 +08:00
refs #581 Store a TTL value in the data cache revision file, skip loading a cached value if its timestamp is too old.
This commit is contained in:
@@ -99,6 +99,11 @@ namespace BlackMisc
|
||||
}
|
||||
}
|
||||
|
||||
void CDataCache::setTimeToLive(const QString &key, int ttl)
|
||||
{
|
||||
QTimer::singleShot(0, &m_serializer, [this, key, ttl] { m_revision.setTimeToLive(key, ttl); });
|
||||
}
|
||||
|
||||
QString lockFileError(const QLockFile &lock)
|
||||
{
|
||||
switch (lock.error())
|
||||
@@ -250,10 +255,13 @@ namespace BlackMisc
|
||||
}
|
||||
m_uuid = uuid;
|
||||
|
||||
auto timesToLive = fromJson(json.value("ttl").toObject());
|
||||
auto newTimestamps = fromJson(json.value("timestamps").toObject());
|
||||
for (auto it = newTimestamps.cbegin(); it != newTimestamps.cend(); ++it)
|
||||
{
|
||||
if (timestamps.value(it.key(), 0) < it.value())
|
||||
auto current = timestamps.value(it.key(), 0);
|
||||
auto ttl = timesToLive.value(it.key(), -1);
|
||||
if (current < it.value() && (ttl < 0 || QDateTime::currentMSecsSinceEpoch() < it.value() + ttl))
|
||||
{
|
||||
m_timestamps.insert(it.key(), it.value());
|
||||
}
|
||||
@@ -302,6 +310,7 @@ namespace BlackMisc
|
||||
QJsonObject json;
|
||||
json.insert("uuid", m_uuid.toString());
|
||||
json.insert("timestamps", toJson(timestamps));
|
||||
json.insert("ttl", toJson(m_timesToLive));
|
||||
revisionFile.write(QJsonDocument(json).toJson());
|
||||
}
|
||||
|
||||
@@ -368,6 +377,13 @@ namespace BlackMisc
|
||||
return std::move(m_promises); // move into the return value, so m_promises becomes empty
|
||||
}
|
||||
|
||||
void CDataCacheRevision::setTimeToLive(const QString &key, int ttl)
|
||||
{
|
||||
Q_ASSERT(! m_updateInProgress);
|
||||
|
||||
m_timesToLive.insert(key, ttl);
|
||||
}
|
||||
|
||||
QJsonObject CDataCacheRevision::toJson(const QMap<QString, qint64> ×tamps)
|
||||
{
|
||||
QJsonObject result;
|
||||
|
||||
@@ -72,6 +72,9 @@ namespace BlackMisc
|
||||
//! Returns (by move) the container of promises to load values.
|
||||
std::vector<std::tuple<QObject *, QString, std::promise<CVariant>>> loadedValuePromises();
|
||||
|
||||
//! Set TTL value that will be written to the revision file.
|
||||
void setTimeToLive(const QString &key, int ttl);
|
||||
|
||||
private:
|
||||
mutable QMutex m_mutex { QMutex::Recursive };
|
||||
bool m_updateInProgress = false;
|
||||
@@ -81,6 +84,7 @@ namespace BlackMisc
|
||||
QLockFile m_lockFile { m_basename + "/.lock" };
|
||||
QUuid m_uuid;
|
||||
QMap<QString, qint64> m_timestamps;
|
||||
QMap<QString, qint64> m_timesToLive;
|
||||
std::vector<std::tuple<QObject *, QString, std::promise<CVariant>>> m_promises;
|
||||
|
||||
static QJsonObject toJson(const QMap<QString, qint64> ×tamps);
|
||||
@@ -149,6 +153,9 @@ namespace BlackMisc
|
||||
//! Method used for implementing CData::syncLoad.
|
||||
std::future<CVariant> syncLoad(QObject *pageOwner, const QString &key);
|
||||
|
||||
//! Method used for implementing TTL.
|
||||
void setTimeToLive(const QString &key, int ttl);
|
||||
|
||||
private:
|
||||
CDataCache();
|
||||
|
||||
@@ -183,7 +190,9 @@ namespace BlackMisc
|
||||
CData(T *owner, NotifySlot<T> slot = nullptr) :
|
||||
CData::CCached(CDataCache::instance(), Trait::key(), Trait::isValid, Trait::defaultValue(), owner, slot),
|
||||
m_owner(owner)
|
||||
{}
|
||||
{
|
||||
if (Trait::timeToLive() >= 0) { CDataCache::instance()->setTimeToLive(Trait::key(), Trait::timeToLive()); }
|
||||
}
|
||||
|
||||
//! Reset the data to its default value.
|
||||
void setDefault() { this->set(Trait::defaultValue()); }
|
||||
@@ -191,6 +200,9 @@ namespace BlackMisc
|
||||
//! Return the file that is used for persistence for this value.
|
||||
QString getFilename() const { return CDataCache::filenameForKey(this->getKey()); }
|
||||
|
||||
//! True if the current timestamp is older than the TTL (time to live).
|
||||
bool isStale() const { return this->getTimestamp() + Trait::timeToLive() > QDateTime::currentMSecsSinceEpoch(); }
|
||||
|
||||
//! Return a future providing the value. If the value is still loading, the future will wait for it.
|
||||
//! If the value is not present, the variant is null. Bypasses async get and inhibits notification slot.
|
||||
std::future<CVariant> syncLoad() { return CDataCache::instance()->syncLoad(m_owner, this->getKey()); }
|
||||
@@ -222,6 +234,10 @@ namespace BlackMisc
|
||||
//! Default implementation returns a default-constructed value.
|
||||
static const T &defaultValue() { static const T def {}; return def; }
|
||||
|
||||
//! Number of milliseconds after which cached value becomes stale.
|
||||
//! Default is -1 which means value never becomes stale.
|
||||
static int timeToLive() { return -1; }
|
||||
|
||||
//! Deleted default constructor.
|
||||
CDataTrait() = delete;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user