| 189 | } |
| 190 | |
| 191 | void ChainDataModel::getAccountImpl(QString accountIdentifier, Account* const * accountInContainer) |
| 192 | { |
| 193 | try { |
| 194 | ilog("Fetching account ${acct}", ("acct", accountIdentifier.toStdString())); |
| 195 | auto result = m_db_api->get_full_accounts([this](const fc::variant& v) { |
| 196 | vector<variant> updates = v.as<vector<variant>>(); |
| 197 | for (const variant& update : updates) { |
| 198 | if (update.is_object()) |
| 199 | processUpdatedObject(update); |
| 200 | else |
| 201 | elog("Handling object deletions is not yet implemented: ${update}", ("update", update)); |
| 202 | } |
| 203 | // TODO: replace true on the next line with a smarter decision as to whether we need status updates or not |
| 204 | }, {accountIdentifier.toStdString()}, true); |
| 205 | fc::optional<full_account> accountPackage; |
| 206 | |
| 207 | if (result.count(accountIdentifier.toStdString())) { |
| 208 | accountPackage = result.at(accountIdentifier.toStdString()); |
| 209 | |
| 210 | // Fetch all necessary assets |
| 211 | QList<asset_id_type> assetsToFetch; |
| 212 | QList<Asset* const *> assetPlaceholders; |
| 213 | assetsToFetch.reserve(accountPackage->balances.size()); |
| 214 | // Get list of asset IDs the account has a balance in |
| 215 | std::transform(accountPackage->balances.begin(), accountPackage->balances.end(), std::back_inserter(assetsToFetch), |
| 216 | [](const account_balance_object& b) { return b.asset_type; }); |
| 217 | auto function = [this,&assetsToFetch,&assetPlaceholders] { |
| 218 | auto itr = assetsToFetch.begin(); |
| 219 | const auto& assets_by_id = m_assets.get<by_id>(); |
| 220 | // Filter out assets I already have, create placeholders for the ones I don't. |
| 221 | while (itr != assetsToFetch.end()) { |
| 222 | if (assets_by_id.count(itr->instance)) |
| 223 | itr = assetsToFetch.erase(itr); |
| 224 | else { |
| 225 | assetPlaceholders.push_back(&*m_assets.insert(new Asset(itr->instance, QString(), 0, this)).first); |
| 226 | ++itr; |
| 227 | } |
| 228 | } |
| 229 | }; |
| 230 | QMetaObject::invokeMethod(parent(), "execute", Qt::BlockingQueuedConnection, |
| 231 | Q_ARG(const std::function<void()>&, function)); |
| 232 | assert(assetsToFetch.size() == assetPlaceholders.size()); |
| 233 | |
| 234 | // Blocking call to fetch and complete initialization for all the assets |
| 235 | for (int i = 0; i < assetsToFetch.size(); ++i) |
| 236 | getAssetImpl(idToString(assetsToFetch[i]), assetPlaceholders[i]); |
| 237 | } |
| 238 | |
| 239 | // Run in main thread |
| 240 | Q_EMIT queueExecute([this,accountPackage,accountInContainer](){ |
| 241 | ilog("Processing result ${r}", ("r", accountPackage)); |
| 242 | auto itr = m_accounts.iterator_to(*accountInContainer); |
| 243 | |
| 244 | if (!accountPackage.valid()) { |
| 245 | (*itr)->deleteLater(); |
| 246 | m_accounts.erase(itr); |
| 247 | } else { |
| 248 | m_accounts.modify(itr, [this,&accountPackage](Account* a){ |
nothing calls this directly
no test coverage detected