< 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:79
Uncovered lines:33
Coverable lines:112
Total lines:262
Line coverage:70.5% (79 of 112)
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%
OnBeforeLoadOrReuse()0%110100%
OnAfterLoadOrReuse()0%110100%
LoadAssetBundleWithDeps()0%2320080.43%
LoadLocalAssetBundle(...)0%2100%
LoadAssetBundle(...)0%4.594066.67%
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 System.IO;
 5using UnityEngine;
 6using UnityEngine.Networking;
 7
 8namespace DCL
 9{
 10    public class AssetPromise_AB : AssetPromise_WithUrl<Asset_AB>
 11    {
 112        public static bool VERBOSE = false;
 3013        public static int MAX_CONCURRENT_REQUESTS => CommonScriptableObjects.rendererState.Get() ? 30 : 256;
 14
 115        public static int concurrentRequests = 0;
 16        public static event Action OnDownloadingProgressUpdate;
 17
 18        bool requestRegistered = false;
 19
 020        public static int downloadingCount => concurrentRequests;
 021        public static int queueCount => AssetPromiseKeeper_AB.i.waitingPromisesCount;
 22
 23        Coroutine loadCoroutine;
 124        static HashSet<string> failedRequestUrls = new HashSet<string>();
 25
 4326        List<AssetPromise_AB> dependencyPromises = new List<AssetPromise_AB>();
 27
 128        public static AssetBundlesLoader assetBundlesLoader = new AssetBundlesLoader();
 29        private Transform containerTransform;
 30        private WebRequestAsyncOperation asyncOp;
 31
 32        public AssetPromise_AB(string contentUrl, string hash,
 4333            Transform containerTransform = null) : base(contentUrl,
 34            hash)
 35        {
 4336            this.containerTransform = containerTransform;
 4337            assetBundlesLoader.Start();
 4338        }
 39
 40        protected override bool AddToLibrary()
 41        {
 2242            if (!library.Add(asset))
 43            {
 044                Debug.Log("add to library fail?");
 45
 046                return false;
 47            }
 48
 2249            if (asset == null)
 50            {
 051                Debug.LogWarning($"Asset is null when trying to add it to the library: hash == {this.GetId()}");
 52
 053                return false;
 54            }
 55
 2256            asset = library.Get(asset.id);
 57
 2258            return true;
 59        }
 60
 61        protected override void OnCancelLoading()
 62        {
 863            if (loadCoroutine != null)
 64            {
 865                CoroutineStarter.Stop(loadCoroutine);
 866                loadCoroutine = null;
 67            }
 68
 1669            if (asyncOp != null) { asyncOp.Dispose(); }
 70
 1671            for (int i = 0; i < dependencyPromises.Count; i++) { dependencyPromises[i].Unload(); }
 72
 873            dependencyPromises.Clear();
 74
 1675            if (asset != null) { asset.CancelShow(); }
 76
 877            UnregisterConcurrentRequest();
 878        }
 79
 4380        protected override void OnBeforeLoadOrReuse() { }
 81
 3582        protected override void OnAfterLoadOrReuse() { }
 83
 84        protected IEnumerator LoadAssetBundleWithDeps(string baseUrl, string hash, Action OnSuccess, Action<Exception> O
 85        {
 3086            string localUrl = Application.dataPath + "/../AssetBundles/" + hash;
 87
 88            // Local Asset Bundles support, if you have the asset bundles in that folder, we are going to load them from
 89#if UNITY_EDITOR
 3090            if (File.Exists(localUrl))
 91            {
 092                Debug.Log($"File exists! {localUrl}");
 093                LoadLocalAssetBundle(localUrl);
 94            }
 95            else
 96            {
 97#endif
 3098                string finalUrl = baseUrl + hash;
 99
 30100                if (failedRequestUrls.Contains(finalUrl))
 101                {
 0102                    OnFail?.Invoke(new Exception($"The url {finalUrl} has failed"));
 103
 0104                    yield break;
 105                }
 106
 30107                yield return WaitForConcurrentRequestsSlot();
 108
 30109                RegisterConcurrentRequest();
 110#if (UNITY_EDITOR || UNITY_STANDALONE)
 30111                asyncOp = Environment.i.platform.webRequest.GetAssetBundle(url: finalUrl, hash: Hash128.Compute(hash),
 112                    disposeOnCompleted: false);
 113#else
 114            //NOTE(Brian): Disable in build because using the asset bundle caching uses IDB.
 115            asyncOp = Environment.i.platform.webRequest.GetAssetBundle(url: finalUrl, disposeOnCompleted: false);
 116#endif
 117
 118                // 1. Download asset bundle, but don't load its objects yet
 30119                yield return asyncOp;
 120
 24121                if (asyncOp.isDisposed)
 122                {
 0123                    OnFail?.Invoke(new Exception("Operation is disposed"));
 124
 0125                    yield break;
 126                }
 127
 24128                if (!asyncOp.isSucceded)
 129                {
 2130                    if (VERBOSE)
 0131                        Debug.Log($"Request failed? {asyncOp.webRequest.error} ... {finalUrl}");
 132
 2133                    failedRequestUrls.Add(finalUrl);
 2134                    OnFail?.Invoke(new Exception($"Request failed? {asyncOp.webRequest.error} ... {finalUrl}"));
 2135                    asyncOp.Dispose();
 136
 2137                    yield break;
 138                }
 139
 22140                if (!LoadAssetBundle(OnFail, finalUrl))
 0141                    yield break;
 142#if UNITY_EDITOR
 22143            }
 144#endif
 145
 146            // 2. Check internal metadata file (dependencies, version, timestamp) and if it doesn't exist, fetch the ext
 22147            TextAsset metadata = asset.GetMetadata();
 148
 22149            if (metadata != null) { AssetBundleDepMapLoadHelper.LoadDepMapFromJSON(metadata.text, hash); }
 150            else
 151            {
 22152                if (!AssetBundleDepMapLoadHelper.dependenciesMap.ContainsKey(hash))
 4153                    CoroutineStarter.Start(AssetBundleDepMapLoadHelper.LoadExternalDepMap(baseUrl, hash));
 154
 22155                yield return AssetBundleDepMapLoadHelper.WaitUntilExternalDepMapIsResolved(hash);
 156            }
 157
 158            // 3. Resolve dependencies
 22159            if (AssetBundleDepMapLoadHelper.dependenciesMap.ContainsKey(hash))
 160            {
 20161                using (var it = AssetBundleDepMapLoadHelper.dependenciesMap[hash].GetEnumerator())
 162                {
 33163                    while (it.MoveNext())
 164                    {
 13165                        var dep = it.Current;
 13166                        var promise = new AssetPromise_AB(baseUrl, dep, containerTransform);
 13167                        AssetPromiseKeeper_AB.i.Keep(promise);
 13168                        dependencyPromises.Add(promise);
 169                    }
 20170                }
 171            }
 172
 22173            UnregisterConcurrentRequest();
 174
 83175            foreach (var promise in dependencyPromises) { yield return promise; }
 176
 22177            assetBundlesLoader.MarkAssetBundleForLoad(asset, containerTransform, OnSuccess, OnFail);
 22178        }
 179
 180#if UNITY_EDITOR
 181        private void LoadLocalAssetBundle(string localUrl)
 182        {
 0183            var assetBundle = AssetBundle.LoadFromFile(localUrl);
 0184            asset.SetAssetBundle(assetBundle);
 0185            asset.LoadMetrics();
 0186        }
 187#endif
 188
 189        private bool LoadAssetBundle(Action<Exception> OnFail, string finalUrl)
 190        {
 22191            var assetBundle = DownloadHandlerAssetBundle.GetContent(asyncOp.webRequest);
 22192            asyncOp.Dispose();
 193
 22194            if (assetBundle == null || asset == null)
 195            {
 0196                OnFail?.Invoke(new Exception("Asset bundle or asset is null"));
 0197                failedRequestUrls.Add(finalUrl);
 198
 0199                return false;
 200            }
 201
 22202            asset.SetAssetBundle(assetBundle);
 22203            asset.LoadMetrics();
 204
 22205            return true;
 206        }
 207
 208        public override string ToString()
 209        {
 0210            string result = $"AB request... loadCoroutine = {loadCoroutine} ... state = {state}\n";
 211
 0212            if (asyncOp.webRequest != null)
 0213                result +=
 214                    $"url = {asyncOp.webRequest.url} ... code = {asyncOp.webRequest.responseCode} ... progress = {asyncO
 215            else
 0216                result += $"null request for url: {contentUrl + hash}\n";
 217
 0218            if (dependencyPromises != null && dependencyPromises.Count > 0)
 219            {
 0220                result += "Dependencies:\n\n";
 221
 0222                foreach (var p in dependencyPromises) { result += p.ToString() + "\n\n"; }
 223            }
 224
 0225            result += "Concurrent requests = " + concurrentRequests;
 226
 0227            return result;
 228        }
 229
 230        protected override void OnLoad(Action OnSuccess, Action<Exception> OnFail)
 231        {
 30232            loadCoroutine = CoroutineStarter.Start(DCLCoroutineRunner.Run(
 233                LoadAssetBundleWithDeps(contentUrl, hash, OnSuccess, OnFail),
 0234                exception => OnFail?.Invoke(exception)));
 30235        }
 236
 237        IEnumerator WaitForConcurrentRequestsSlot()
 238        {
 30239            while (concurrentRequests >= MAX_CONCURRENT_REQUESTS) { yield return null; }
 30240        }
 241
 242        void RegisterConcurrentRequest()
 243        {
 30244            if (requestRegistered)
 0245                return;
 246
 30247            concurrentRequests++;
 30248            OnDownloadingProgressUpdate?.Invoke();
 30249            requestRegistered = true;
 30250        }
 251
 252        void UnregisterConcurrentRequest()
 253        {
 30254            if (!requestRegistered)
 0255                return;
 256
 30257            concurrentRequests--;
 30258            OnDownloadingProgressUpdate?.Invoke();
 30259            requestRegistered = false;
 30260        }
 261    }
 262}