< Summary

Class:DCL.AssetPromise_AB
Assembly:AssetPromiseKeeper
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/AssetManager/AssetBundles/AB/AssetPromise_AB.cs
Covered lines:77
Uncovered lines:31
Coverable lines:108
Total lines:248
Line coverage:71.2% (77 of 108)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AssetPromise_AB()0%110100%
AssetPromise_AB(...)0%110100%
AddToLibrary()0%4.123050%
OnCancelLoading()0%5.075085.71%
OnAfterLoadOrReuse()0%110100%
OnBeforeLoadOrReuse()0%110100%
LoadAssetBundleWithDeps()0%24.9921079.17%
ToString()0%30500%
OnLoad(...)0%110100%
WaitForConcurrentRequestsSlot()0%4.594066.67%
RegisterConcurrentRequest()0%3.043083.33%
UnregisterConcurrentRequest()0%3.043083.33%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/AssetManager/AssetBundles/AB/AssetPromise_AB.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using UnityEngine;
 5using UnityEngine.Networking;
 6
 7namespace DCL
 8{
 9    public class AssetPromise_AB : AssetPromise_WithUrl<Asset_AB>
 10    {
 11        const string METADATA_FILENAME = "metadata.json";
 12
 113        public static bool VERBOSE = false;
 2714        public static int MAX_CONCURRENT_REQUESTS => CommonScriptableObjects.rendererState.Get() ? 30 : 256;
 15
 116        public static int concurrentRequests = 0;
 17        public static event Action OnDownloadingProgressUpdate;
 18
 19        bool requestRegistered = false;
 20
 021        public static int downloadingCount => concurrentRequests;
 022        public static int queueCount => AssetPromiseKeeper_AB.i.waitingPromisesCount;
 23
 24        Coroutine loadCoroutine;
 125        static HashSet<string> failedRequestUrls = new HashSet<string>();
 26
 3927        List<AssetPromise_AB> dependencyPromises = new List<AssetPromise_AB>();
 28
 129        public static AssetBundlesLoader assetBundlesLoader = new AssetBundlesLoader();
 30        private Transform containerTransform;
 31        private WebRequestAsyncOperation asyncOp;
 32
 33        public AssetPromise_AB(string contentUrl, string hash,
 3934            Transform containerTransform = null) : base(contentUrl,
 35            hash)
 36        {
 3937            this.containerTransform = containerTransform;
 3938            assetBundlesLoader.Start();
 3939        }
 40
 41        protected override bool AddToLibrary()
 42        {
 2043            if (!library.Add(asset))
 44            {
 045                Debug.Log("add to library fail?");
 046                return false;
 47            }
 48
 2049            if (asset == null)
 50            {
 051                Debug.LogWarning($"Asset is null when trying to add it to the library: hash == {this.GetId()}");
 052                return false;
 53            }
 54
 2055            asset = library.Get(asset.id);
 2056            return true;
 57        }
 58
 59        protected override void OnCancelLoading()
 60        {
 761            if (loadCoroutine != null)
 62            {
 763                CoroutineStarter.Stop(loadCoroutine);
 764                loadCoroutine = null;
 65            }
 66
 767            if (asyncOp != null)
 68            {
 769                asyncOp.Dispose();
 70            }
 71
 1472            for (int i = 0; i < dependencyPromises.Count; i++)
 73            {
 074                dependencyPromises[i].Unload();
 75            }
 76
 777            dependencyPromises.Clear();
 78
 779            if (asset != null)
 80            {
 781                asset.CancelShow();
 82            }
 83
 784            UnregisterConcurrentRequest();
 785        }
 86
 87        protected override void OnAfterLoadOrReuse()
 88        {
 3289        }
 90
 91        protected override void OnBeforeLoadOrReuse()
 92        {
 3993        }
 94
 95        protected IEnumerator LoadAssetBundleWithDeps(string baseUrl, string hash, Action OnSuccess, Action<Exception> O
 96        {
 2797            string finalUrl = baseUrl + hash;
 98
 2799            if (failedRequestUrls.Contains(finalUrl))
 100            {
 0101                OnFail?.Invoke(new Exception($"The url {finalUrl} has failed"));
 0102                yield break;
 103            }
 104
 27105            yield return WaitForConcurrentRequestsSlot();
 106
 27107            RegisterConcurrentRequest();
 108#if (UNITY_EDITOR || UNITY_STANDALONE)
 27109            asyncOp = Environment.i.platform.webRequest.GetAssetBundle(url: finalUrl, hash: Hash128.Compute(hash),
 110                disposeOnCompleted: false);
 111#else
 112            //NOTE(Brian): Disable in build because using the asset bundle caching uses IDB.
 113            asyncOp = Environment.i.platform.webRequest.GetAssetBundle(url: finalUrl, disposeOnCompleted: false);
 114#endif
 115
 116            // 1. Download asset bundle, but don't load its objects yet
 27117            yield return asyncOp;
 118
 22119            if (asyncOp.isDisposed)
 120            {
 0121                OnFail?.Invoke(new Exception("Operation is disposed"));
 0122                yield break;
 123            }
 124
 22125            if (!asyncOp.isSucceded)
 126            {
 2127                if (VERBOSE)
 0128                    Debug.Log($"Request failed? {asyncOp.webRequest.error} ... {finalUrl}");
 2129                failedRequestUrls.Add(finalUrl);
 2130                OnFail?.Invoke(new Exception($"Request failed? {asyncOp.webRequest.error} ... {finalUrl}"));
 2131                asyncOp.Dispose();
 2132                yield break;
 133            }
 134
 20135            AssetBundle assetBundle = DownloadHandlerAssetBundle.GetContent(asyncOp.webRequest);
 20136            asyncOp.Dispose();
 137
 20138            if (assetBundle == null || asset == null)
 139            {
 0140                OnFail?.Invoke(new Exception("Asset bundle or asset is null"));
 0141                failedRequestUrls.Add(finalUrl);
 0142                yield break;
 143            }
 144
 20145            asset.ownerAssetBundle = assetBundle;
 20146            asset.assetBundleAssetName = assetBundle.name;
 147
 148            // 2. Check internal metadata file (dependencies, version, timestamp) and if it doesn't exist, fetch the ext
 20149            TextAsset metadata = assetBundle.LoadAsset<TextAsset>(METADATA_FILENAME);
 150
 20151            if (metadata != null)
 152            {
 0153                AssetBundleDepMapLoadHelper.LoadDepMapFromJSON(metadata.text, hash);
 0154            }
 155            else
 156            {
 20157                if (!AssetBundleDepMapLoadHelper.dependenciesMap.ContainsKey(hash))
 3158                    CoroutineStarter.Start(AssetBundleDepMapLoadHelper.LoadExternalDepMap(baseUrl, hash));
 159
 20160                yield return AssetBundleDepMapLoadHelper.WaitUntilExternalDepMapIsResolved(hash);
 161            }
 162
 163            // 3. Resolve dependencies
 20164            if (AssetBundleDepMapLoadHelper.dependenciesMap.ContainsKey(hash))
 165            {
 19166                using (var it = AssetBundleDepMapLoadHelper.dependenciesMap[hash].GetEnumerator())
 167                {
 31168                    while (it.MoveNext())
 169                    {
 12170                        var dep = it.Current;
 12171                        var promise = new AssetPromise_AB(baseUrl, dep, containerTransform);
 12172                        AssetPromiseKeeper_AB.i.Keep(promise);
 12173                        dependencyPromises.Add(promise);
 174                    }
 19175                }
 176            }
 177
 20178            UnregisterConcurrentRequest();
 179
 64180            foreach (var promise in dependencyPromises)
 181            {
 12182                yield return promise;
 183            }
 184
 20185            assetBundlesLoader.MarkAssetBundleForLoad(asset, assetBundle, containerTransform, OnSuccess, OnFail);
 20186        }
 187
 188        public override string ToString()
 189        {
 0190            string result = $"AB request... loadCoroutine = {loadCoroutine} ... state = {state}\n";
 191
 0192            if (asyncOp.webRequest != null)
 0193                result +=
 194                    $"url = {asyncOp.webRequest.url} ... code = {asyncOp.webRequest.responseCode} ... progress = {asyncO
 195            else
 0196                result += $"null request for url: {contentUrl + hash}\n";
 197
 198
 0199            if (dependencyPromises != null && dependencyPromises.Count > 0)
 200            {
 0201                result += "Dependencies:\n\n";
 0202                foreach (var p in dependencyPromises)
 203                {
 0204                    result += p.ToString() + "\n\n";
 205                }
 206            }
 207
 0208            result += "Concurrent requests = " + concurrentRequests;
 209
 0210            return result;
 211        }
 212
 213        protected override void OnLoad(Action OnSuccess, Action<Exception> OnFail)
 214        {
 27215            loadCoroutine = CoroutineStarter.Start(DCLCoroutineRunner.Run(
 216                LoadAssetBundleWithDeps(contentUrl, hash, OnSuccess, OnFail),
 0217                exception => OnFail?.Invoke(exception)));
 27218        }
 219
 220        IEnumerator WaitForConcurrentRequestsSlot()
 221        {
 27222            while (concurrentRequests >= MAX_CONCURRENT_REQUESTS)
 223            {
 0224                yield return null;
 225            }
 27226        }
 227
 228        void RegisterConcurrentRequest()
 229        {
 27230            if (requestRegistered)
 0231                return;
 232
 27233            concurrentRequests++;
 27234            OnDownloadingProgressUpdate?.Invoke();
 27235            requestRegistered = true;
 27236        }
 237
 238        void UnregisterConcurrentRequest()
 239        {
 27240            if (!requestRegistered)
 0241                return;
 242
 27243            concurrentRequests--;
 27244            OnDownloadingProgressUpdate?.Invoke();
 27245            requestRegistered = false;
 27246        }
 247    }
 248}