Showing the changes to libraries/script-engine/src/ScriptCache.cpp (1 of 2 files). Show all
Unified · Split
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | #include "ScriptEngines.h" |
| 27 | 27 | #include "ScriptEngineLogging.h" |
| 28 | +#include <QtCore/QTimer> | |
| 28 | 29 | |
| 29 | 30 | ScriptCache::ScriptCache(QObject* parent) { |
| 30 | 31 | // nothing to do here... |
| @@ -133,8 +134,11 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable · 102 unmodified lines | ||
| 133 | 134 | qCDebug(scriptengine) << "Found script in cache:" << url.toString(); |
| 134 | 135 | contentAvailable(url.toString(), scriptContent, true, true); |
| 135 | 136 | } else { |
| 136 | − bool alreadyWaiting = _contentCallbacks.contains(url); | |
| 137 | − _contentCallbacks.insert(url, contentAvailable); | |
| 137 | + auto& scriptRequest = _activeScriptRequests[url]; | |
| 138 | + | |
| 139 | + bool alreadyWaiting = scriptRequest.scriptUsers.size() > 0; | |
| 140 | + scriptRequest.scriptUsers.push_back(contentAvailable); | |
| 141 | + | |
| 138 | 142 | lock.unlock(); |
| 139 | 143 | |
| 140 | 144 | if (alreadyWaiting) { |
| @@ -152,6 +156,9 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable · 11 unmodified lines | ||
| 152 | 156 | } |
| 153 | 157 | } |
| 154 | 158 | |
| 159 | +static const int MAX_RETRIES = 5; | |
| 160 | +static int START_DELAY_BETWEEN_RETRIES = 200; | |
| 161 | + | |
| 155 | 162 | void ScriptCache::scriptContentAvailable() { |
| 156 | 163 | #ifdef THREAD_DEBUGGING |
| 157 | 164 | qCDebug(scriptengine) << "ScriptCache::scriptContentAvailable() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; |
| @@ -160,29 +167,60 @@ void ScriptCache::scriptContentAvailable() { · 2 unmodified lines | ||
| 160 | 167 | QUrl url = req->getUrl(); |
| 161 | 168 | |
| 162 | 169 | QString scriptContent; |
| 163 | − QList<contentAvailableCallback> allCallbacks; | |
| 170 | + std::vector<contentAvailableCallback> allCallbacks; | |
| 171 | + bool finished { false }; | |
| 164 | 172 | bool success { false }; |
| 165 | 173 | |
| 166 | 174 | { |
| 167 | − Lock lock(_containerLock); | |
| 168 | − allCallbacks = _contentCallbacks.values(url); | |
| 169 | − _contentCallbacks.remove(url); | |
| 170 | 175 | Q_ASSERT(req->getState() == ResourceRequest::Finished); |
| 171 | 176 | success = req->getResult() == ResourceRequest::Success; |
| 172 | 177 | |
| 173 | − if (success) { | |
| 174 | − _scriptCache[url] = scriptContent = req->getData(); | |
| 175 | − qCDebug(scriptengine) << "Done downloading script at:" << url.toString(); | |
| 176 | − } else { | |
| 177 | − // Dubious, but retained here because it matches the behavior before fixing the threading | |
| 178 | − scriptContent = _scriptCache[url]; | |
| 179 | − qCWarning(scriptengine) << "Error loading script from URL " << url; | |
| 178 | + Lock lock(_containerLock); | |
| 179 | + | |
| 180 | + if (_activeScriptRequests.contains(url)) { | |
| 181 | + auto& scriptRequest = _activeScriptRequests[url]; | |
| 182 | + | |
| 183 | + if (success) { | |
| 184 | + allCallbacks = scriptRequest.scriptUsers; | |
| 185 | + auto scriptContent = _scriptCache[url]; | |
| 186 | + | |
| 187 | + _activeScriptRequests.remove(url); | |
| 188 | + | |
| 189 | + _scriptCache[url] = scriptContent = req->getData(); | |
| 190 | + finished = true; | |
| 191 | + qCDebug(scriptengine) << "Done downloading script at:" << url.toString(); | |
| 192 | + } else { | |
| 193 | + if (scriptRequest.numRetries < MAX_RETRIES) { | |
| 194 | + ++scriptRequest.numRetries; | |
| 195 | + | |
| 196 | + qDebug() << "Script request failed: " << url; | |
| 197 | + | |
| 198 | + int timeout = exp(scriptRequest.numRetries) * START_DELAY_BETWEEN_RETRIES; | |
| 199 | + QTimer::singleShot(timeout, this, [this, url]() { | |
| 200 | + qDebug() << "Retrying script request: " << url; | |
| 201 | + | |
| 202 | + auto request = ResourceManager::createResourceRequest(nullptr, url); | |
| 203 | + Q_ASSERT(request); | |
| 204 | + | |
| 205 | + // We've already made a request, so the cache must be disabled or it wasn't there, so enabling | |
| 206 | + // it will do nothing. | |
| 207 | + request->setCacheEnabled(false); | |
| 208 | + connect(request, &ResourceRequest::finished, this, &ScriptCache::scriptContentAvailable); | |
| 209 | + request->send(); | |
| 210 | + }); | |
| 211 | + } else { | |
| 212 | + // Dubious, but retained here because it matches the behavior before fixing the threading | |
| 213 | + scriptContent = _scriptCache[url]; | |
| 214 | + finished = true; | |
| 215 | + qCWarning(scriptengine) << "Error loading script from URL " << url; | |
| 216 | + } | |
| 217 | + } | |
| 180 | 218 | } |
| 181 | 219 | } |
| 182 | 220 | |
| 183 | 221 | req->deleteLater(); |
| 184 | 222 | |
| 185 | − if (!DependencyManager::get<ScriptEngines>()->isStopped()) { | |
| 223 | + if (finished && !DependencyManager::get<ScriptEngines>()->isStopped()) { | |
| 186 | 224 | foreach(contentAvailableCallback thisCallback, allCallbacks) { |
| 187 | 225 | thisCallback(url.toString(), scriptContent, true, success); |
| 188 | 226 | } |