Showing the changes to libraries/script-engine/src/ScriptCache.cpp (1 of 14 files). Show all
Unified · Split
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <QObject> |
| 20 | 20 | #include <QThread> |
| 21 | 21 | #include <QRegularExpression> |
| 22 | +#include <QMetaEnum> | |
| 22 | 23 | |
| 23 | 24 | #include <assert.h> |
| 24 | 25 | #include <SharedUtil.h> |
| @@ -27,12 +28,18 @@ · 2 unmodified lines | ||
| 27 | 28 | #include "ScriptEngineLogging.h" |
| 28 | 29 | #include <QtCore/QTimer> |
| 29 | 30 | |
| 31 | +const QString ScriptCache::STATUS_INLINE { "Inline" }; | |
| 32 | +const QString ScriptCache::STATUS_CACHED { "Cached" }; | |
| 33 | + | |
| 30 | 34 | ScriptCache::ScriptCache(QObject* parent) { |
| 31 | 35 | // nothing to do here... |
| 32 | 36 | } |
| 33 | 37 | |
| 34 | 38 | void ScriptCache::clearCache() { |
| 35 | 39 | Lock lock(_containerLock); |
| 40 | + foreach(auto& url, _scriptCache.keys()) { | |
| 41 | + qCDebug(scriptengine) << "clearing cache: " << url; | |
| 42 | + } | |
| 36 | 43 | _scriptCache.clear(); |
| 37 | 44 | } |
| 38 | 45 | |
| @@ -49,35 +56,6 @@ void ScriptCache::clearATPScriptsFromCache() { · 10 unmodified lines | ||
| 49 | 56 | } |
| 50 | 57 | } |
| 51 | 58 | |
| 52 | −QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUser, bool& isPending, bool reload) { | |
| 53 | − QUrl url = ResourceManager::normalizeURL(unnormalizedURL); | |
| 54 | − QString scriptContents; | |
| 55 | − | |
| 56 | − Lock lock(_containerLock); | |
| 57 | − if (_scriptCache.contains(url) && !reload) { | |
| 58 | − qCDebug(scriptengine) << "Found script in cache:" << url.toString(); | |
| 59 | − scriptContents = _scriptCache[url]; | |
| 60 | − lock.unlock(); | |
| 61 | − scriptUser->scriptContentsAvailable(url, scriptContents); | |
| 62 | − isPending = false; | |
| 63 | − } else { | |
| 64 | − isPending = true; | |
| 65 | − bool alreadyWaiting = _scriptUsers.contains(url); | |
| 66 | − _scriptUsers.insert(url, scriptUser); | |
| 67 | − lock.unlock(); | |
| 68 | − | |
| 69 | − if (alreadyWaiting) { | |
| 70 | − qCDebug(scriptengine) << "Already downloading script at:" << url.toString(); | |
| 71 | − } else { | |
| 72 | − auto request = ResourceManager::createResourceRequest(nullptr, url); | |
| 73 | − request->setCacheEnabled(!reload); | |
| 74 | − connect(request, &ResourceRequest::finished, this, &ScriptCache::scriptDownloaded); | |
| 75 | − request->send(); | |
| 76 | − } | |
| 77 | − } | |
| 78 | − return scriptContents; | |
| 79 | −} | |
| 80 | − | |
| 81 | 59 | void ScriptCache::deleteScript(const QUrl& unnormalizedURL) { |
| 82 | 60 | QUrl url = ResourceManager::normalizeURL(unnormalizedURL); |
| 83 | 61 | Lock lock(_containerLock); |
| @@ -87,37 +65,7 @@ void ScriptCache::deleteScript(const QUrl& unnormalizedURL) { · 3 unmodified lines | ||
| 87 | 65 | } |
| 88 | 66 | } |
| 89 | 67 | |
| 90 | −void ScriptCache::scriptDownloaded() { | |
| 91 | − ResourceRequest* req = qobject_cast<ResourceRequest*>(sender()); | |
| 92 | − QUrl url = req->getUrl(); | |
| 93 | − | |
| 94 | − Lock lock(_containerLock); | |
| 95 | − QList<ScriptUser*> scriptUsers = _scriptUsers.values(url); | |
| 96 | − _scriptUsers.remove(url); | |
| 97 | − | |
| 98 | − if (!DependencyManager::get<ScriptEngines>()->isStopped()) { | |
| 99 | − if (req->getResult() == ResourceRequest::Success) { | |
| 100 | − auto scriptContents = req->getData(); | |
| 101 | − _scriptCache[url] = scriptContents; | |
| 102 | − lock.unlock(); | |
| 103 | − qCDebug(scriptengine) << "Done downloading script at:" << url.toString(); | |
| 104 | − | |
| 105 | − foreach(ScriptUser* user, scriptUsers) { | |
| 106 | − user->scriptContentsAvailable(url, scriptContents); | |
| 107 | − } | |
| 108 | − } else { | |
| 109 | − lock.unlock(); | |
| 110 | − qCWarning(scriptengine) << "Error loading script from URL " << url; | |
| 111 | − foreach(ScriptUser* user, scriptUsers) { | |
| 112 | − user->errorInLoadingScript(url); | |
| 113 | − } | |
| 114 | − } | |
| 115 | − } | |
| 116 | − | |
| 117 | − req->deleteLater(); | |
| 118 | −} | |
| 119 | − | |
| 120 | −void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailableCallback contentAvailable, bool forceDownload) { | |
| 68 | +void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailableCallback contentAvailable, bool forceDownload, int maxRetries) { | |
| 121 | 69 | #ifdef THREAD_DEBUGGING |
| 122 | 70 | qCDebug(scriptengine) << "ScriptCache::getScriptContents() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; |
| 123 | 71 | #endif |
| @@ -128,7 +76,7 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable · 4 unmodified lines | ||
| 128 | 76 | // entityScript use case) |
| 129 | 77 | if (unnormalizedURL.scheme().isEmpty() && |
| 130 | 78 | scriptOrURL.simplified().replace(" ", "").contains(QRegularExpression(R"(\(function\([a-z]?[\w,]*\){)"))) { |
| 131 | − contentAvailable(scriptOrURL, scriptOrURL, false, true); | |
| 79 | + contentAvailable(scriptOrURL, scriptOrURL, false, true, STATUS_INLINE); | |
| 132 | 80 | return; |
| 133 | 81 | } |
| 134 | 82 | |
| @@ -136,7 +84,7 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable · 1 unmodified line | ||
| 136 | 84 | if (unnormalizedURL.scheme() == "javascript") { |
| 137 | 85 | QString contents { scriptOrURL }; |
| 138 | 86 | contents.replace(QRegularExpression("^javascript:"), ""); |
| 139 | − contentAvailable(scriptOrURL, contents, false, true); | |
| 87 | + contentAvailable(scriptOrURL, contents, false, true, STATUS_INLINE); | |
| 140 | 88 | return; |
| 141 | 89 | } |
| 142 | 90 | |
| @@ -145,34 +93,32 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable · 2 unmodified lines | ||
| 145 | 93 | auto scriptContent = _scriptCache[url]; |
| 146 | 94 | lock.unlock(); |
| 147 | 95 | qCDebug(scriptengine) << "Found script in cache:" << url.toString(); |
| 148 | − contentAvailable(url.toString(), scriptContent, true, true); | |
| 96 | + contentAvailable(url.toString(), scriptContent, true, true, STATUS_CACHED); | |
| 149 | 97 | } else { |
| 150 | 98 | auto& scriptRequest = _activeScriptRequests[url]; |
| 151 | − | |
| 152 | 99 | bool alreadyWaiting = scriptRequest.scriptUsers.size() > 0; |
| 153 | 100 | scriptRequest.scriptUsers.push_back(contentAvailable); |
| 154 | 101 | |
| 155 | 102 | lock.unlock(); |
| 156 | 103 | |
| 157 | 104 | if (alreadyWaiting) { |
| 158 | − qCDebug(scriptengine) << "Already downloading script at:" << url.toString(); | |
| 105 | + qCDebug(scriptengine) << QString("Already downloading script at: %1 (retry: %2; scriptusers: %3)") | |
| 106 | + .arg(url.toString()).arg(scriptRequest.numRetries).arg(scriptRequest.scriptUsers.size()); | |
| 159 | 107 | } else { |
| 108 | + scriptRequest.maxRetries = maxRetries; | |
| 160 | 109 | #ifdef THREAD_DEBUGGING |
| 161 | 110 | qCDebug(scriptengine) << "about to call: ResourceManager::createResourceRequest(this, url); on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; |
| 162 | 111 | #endif |
| 163 | 112 | auto request = ResourceManager::createResourceRequest(nullptr, url); |
| 164 | 113 | Q_ASSERT(request); |
| 165 | 114 | request->setCacheEnabled(!forceDownload); |
| 166 | − connect(request, &ResourceRequest::finished, this, &ScriptCache::scriptContentAvailable); | |
| 115 | + connect(request, &ResourceRequest::finished, this, [=]{ scriptContentAvailable(maxRetries); }); | |
| 167 | 116 | request->send(); |
| 168 | 117 | } |
| 169 | 118 | } |
| 170 | 119 | } |
| 171 | 120 | |
| 172 | −static const int MAX_RETRIES = 5; | |
| 173 | −static int START_DELAY_BETWEEN_RETRIES = 200; | |
| 174 | − | |
| 175 | −void ScriptCache::scriptContentAvailable() { | |
| 121 | +void ScriptCache::scriptContentAvailable(int maxRetries) { | |
| 176 | 122 | #ifdef THREAD_DEBUGGING |
| 177 | 123 | qCDebug(scriptengine) << "ScriptCache::scriptContentAvailable() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; |
| 178 | 124 | #endif |
| @@ -181,7 +127,7 @@ void ScriptCache::scriptContentAvailable() { · 2 unmodified lines | ||
| 181 | 127 | |
| 182 | 128 | QString scriptContent; |
| 183 | 129 | std::vector<contentAvailableCallback> allCallbacks; |
| 184 | − bool finished { false }; | |
| 130 | + QString status = QMetaEnum::fromType<ResourceRequest::Result>().valueToKey(req->getResult()); | |
| 185 | 131 | bool success { false }; |
| 186 | 132 | |
| 187 | 133 | { |
| @@ -199,7 +145,6 @@ void ScriptCache::scriptContentAvailable() { · 11 unmodified lines | ||
| 199 | 145 | _activeScriptRequests.remove(url); |
| 200 | 146 | |
| 201 | 147 | _scriptCache[url] = scriptContent = req->getData(); |
| 202 | − finished = true; | |
| 203 | 148 | qCDebug(scriptengine) << "Done downloading script at:" << url.toString(); |
| 204 | 149 | } else { |
| 205 | 150 | auto result = req->getResult(); |
| @@ -207,16 +152,19 @@ void ScriptCache::scriptContentAvailable() { · 1 unmodified line | ||
| 207 | 152 | result == ResourceRequest::AccessDenied || |
| 208 | 153 | result == ResourceRequest::InvalidURL || |
| 209 | 154 | result == ResourceRequest::NotFound || |
| 210 | − scriptRequest.numRetries >= MAX_RETRIES; | |
| 155 | + scriptRequest.numRetries >= maxRetries; | |
| 211 | 156 | |
| 212 | 157 | if (!irrecoverable) { |
| 213 | 158 | ++scriptRequest.numRetries; |
| 214 | 159 | |
| 215 | − qCDebug(scriptengine) << "Script request failed: " << url; | |
| 160 | + int timeout = exp(scriptRequest.numRetries) * ScriptRequest::START_DELAY_BETWEEN_RETRIES; | |
| 161 | + int attempt = scriptRequest.numRetries; | |
| 162 | + qCDebug(scriptengine) << QString("Script request failed [%1]: %2 (will retry %3 more times; attempt #%4 in %5ms...)") | |
| 163 | + .arg(status).arg(url.toString()).arg(maxRetries - attempt + 1).arg(attempt).arg(timeout); | |
| 216 | 164 | |
| 217 | − int timeout = exp(scriptRequest.numRetries) * START_DELAY_BETWEEN_RETRIES; | |
| 218 | − QTimer::singleShot(timeout, this, [this, url]() { | |
| 219 | − qCDebug(scriptengine) << "Retrying script request: " << url; | |
| 165 | + QTimer::singleShot(timeout, this, [this, url, attempt, maxRetries]() { | |
| 166 | + qCDebug(scriptengine) << QString("Retrying script request [%1 / %2]: %3") | |
| 167 | + .arg(attempt).arg(maxRetries).arg(url.toString()); | |
| 220 | 168 | |
| 221 | 169 | auto request = ResourceManager::createResourceRequest(nullptr, url); |
| 222 | 170 | Q_ASSERT(request); |
| @@ -224,7 +172,7 @@ void ScriptCache::scriptContentAvailable() { · 1 unmodified line | ||
| 224 | 172 | // We've already made a request, so the cache must be disabled or it wasn't there, so enabling |
| 225 | 173 | // it will do nothing. |
| 226 | 174 | request->setCacheEnabled(false); |
| 227 | − connect(request, &ResourceRequest::finished, this, &ScriptCache::scriptContentAvailable); | |
| 175 | + connect(request, &ResourceRequest::finished, this, [=]{ scriptContentAvailable(maxRetries); }); | |
| 228 | 176 | request->send(); |
| 229 | 177 | }); |
| 230 | 178 | } else { |
| @@ -232,9 +180,12 @@ void ScriptCache::scriptContentAvailable() { · 1 unmodified line | ||
| 232 | 180 | |
| 233 | 181 | allCallbacks = scriptRequest.scriptUsers; |
| 234 | 182 | |
| 235 | − scriptContent = _scriptCache[url]; | |
| 236 | − finished = true; | |
| 237 | − qCWarning(scriptengine) << "Error loading script from URL " << url; | |
| 183 | + if (_scriptCache.contains(url)) { | |
| 184 | + scriptContent = _scriptCache[url]; | |
| 185 | + } | |
| 186 | + _activeScriptRequests.remove(url); | |
| 187 | + qCWarning(scriptengine) << "Error loading script from URL " << url << "(" << status <<")"; | |
| 188 | + | |
| 238 | 189 | } |
| 239 | 190 | } |
| 240 | 191 | } |
| @@ -242,9 +193,9 @@ void ScriptCache::scriptContentAvailable() { · 1 unmodified line | ||
| 242 | 193 | |
| 243 | 194 | req->deleteLater(); |
| 244 | 195 | |
| 245 | − if (finished && !DependencyManager::get<ScriptEngines>()->isStopped()) { | |
| 196 | + if (allCallbacks.size() > 0 && !DependencyManager::get<ScriptEngines>()->isStopped()) { | |
| 246 | 197 | foreach(contentAvailableCallback thisCallback, allCallbacks) { |
| 247 | − thisCallback(url.toString(), scriptContent, true, success); | |
| 198 | + thisCallback(url.toString(), scriptContent, true, success, status); | |
| 248 | 199 | } |
| 249 | 200 | } |
| 250 | 201 | } |