From edf6184c81b271cd4460cf284862ecdefa1914e7 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sat, 11 Apr 2026 19:16:44 +1000 Subject: [PATCH] fix: retry reading file before warn Some programs will not write to the file atomically, causing us to read a malformed JSON while the write is in progress. Add a retry system to avoid false warnings. --- plugin/src/Caelestia/Config/configobject.cpp | 23 ++++++++++++++++++-- plugin/src/Caelestia/Config/configobject.hpp | 2 ++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/plugin/src/Caelestia/Config/configobject.cpp b/plugin/src/Caelestia/Config/configobject.cpp index 6ab8b14f..8b9001fd 100644 --- a/plugin/src/Caelestia/Config/configobject.cpp +++ b/plugin/src/Caelestia/Config/configobject.cpp @@ -285,6 +285,11 @@ void ConfigObject::setupFileBackend(const QString& path) { m_watcher = new QFileSystemWatcher(this); m_saveTimer = new QTimer(this); m_cooldownTimer = new QTimer(this); + m_retryTimer = new QTimer(this); + + m_retryTimer->setSingleShot(true); + m_retryTimer->setInterval(50); + connect(m_retryTimer, &QTimer::timeout, this, &ConfigObject::reloadFromFile); m_saveTimer->setSingleShot(true); m_saveTimer->setInterval(500); @@ -337,10 +342,20 @@ void ConfigObject::reloadFromFile() { auto doc = QJsonDocument::fromJson(file.readAll(), &error); if (error.error != QJsonParseError::NoError) { - qCWarning(lcConfig) << "Failed to parse" << m_filePath << ":" << error.errorString(); + if (m_retryTimer && m_parseRetries < 3) { + m_parseRetries++; + qCDebug(lcConfig, "Failed to parse %s: %s - retrying (%d/3)", qPrintable(m_filePath), + qPrintable(error.errorString()), m_parseRetries); + m_retryTimer->start(); + } else { + qCWarning(lcConfig, "Failed to parse %s: %s", qPrintable(m_filePath), qPrintable(error.errorString())); + m_parseRetries = 0; + } return; } + m_parseRetries = 0; + qCDebug(lcConfig) << "Reloading" << metaObject()->className() << "from" << m_filePath; clearLoadedKeys(); @@ -357,8 +372,12 @@ void ConfigObject::onFileChanged() { if (!m_watcher->files().contains(m_filePath)) m_watcher->addPath(m_filePath); - if (!m_recentlySaved) + if (!m_recentlySaved) { + m_parseRetries = 0; + if (m_retryTimer) + m_retryTimer->stop(); reloadFromFile(); + } } } // namespace caelestia::config diff --git a/plugin/src/Caelestia/Config/configobject.hpp b/plugin/src/Caelestia/Config/configobject.hpp index bb56e9c7..096fb9e8 100644 --- a/plugin/src/Caelestia/Config/configobject.hpp +++ b/plugin/src/Caelestia/Config/configobject.hpp @@ -105,6 +105,8 @@ private: QFileSystemWatcher* m_watcher = nullptr; QTimer* m_saveTimer = nullptr; QTimer* m_cooldownTimer = nullptr; + QTimer* m_retryTimer = nullptr; + int m_parseRetries = 0; // Per-monitor overlay state ConfigObject* m_global = nullptr;