< Summary

Class:AvatarSystem.WearableItemResolver
Assembly:AvatarSystemLoaders
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableItemResolver.cs
Covered lines:29
Uncovered lines:23
Coverable lines:52
Total lines:133
Line coverage:55.7% (29 of 52)
Covered branches:0
Total branches:0
Covered methods:5
Total methods:7
Method coverage:71.4% (5 of 7)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
WearableItemResolver(...)0%110100%
ResolveAndSplit()0%42600%
Resolve()0%6.984042.86%
Resolve()0%52.8919054.55%
Forget(...)0%2.152066.67%
Forget(...)0%2100%
Dispose()0%330100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/Loader/WearableItemResolver.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCL.Helpers;
 3using DCLServices.WearablesCatalogService;
 4using System;
 5using System.Collections.Generic;
 6using System.Linq;
 7using System.Threading;
 8
 9namespace AvatarSystem
 10{
 11    public class WearableItemResolver : IWearableItemResolver
 12    {
 51913        private CancellationTokenSource disposeCts = new CancellationTokenSource();
 51914        private readonly Dictionary<string, WearableItem> wearablesRetrieved = new Dictionary<string, WearableItem>();
 15        private readonly IWearablesCatalogService wearablesCatalogService;
 16
 51917        public WearableItemResolver(IWearablesCatalogService wearablesCatalogService)
 18        {
 51919            this.wearablesCatalogService = wearablesCatalogService;
 51920        }
 21
 22        public async UniTask<(List<WearableItem> wearables, List<WearableItem> emotes)> ResolveAndSplit(IEnumerable<stri
 23        {
 24            try
 25            {
 026                IEnumerable<string> parsedWearablesIds = wearableIds.Select(ExtendedUrnParser.GetShortenedUrn);
 027                WearableItem[] allItems = await Resolve(parsedWearablesIds, ct);
 28
 029                List<WearableItem> wearables = new List<WearableItem>();
 030                List<WearableItem> emotes = new List<WearableItem>();
 31
 032                for (int i = 0; i < allItems.Length; i++)
 33                {
 034                    if (allItems[i] == null)
 35                        continue;
 36
 037                    if (allItems[i].IsEmote())
 038                        emotes.Add(allItems[i]);
 39                    else
 040                        wearables.Add(allItems[i]);
 41                }
 42
 043                return (
 44                    wearables,
 45                    emotes
 46                );
 47            }
 048            catch (OperationCanceledException)
 49            {
 50                //No disposing required
 051                throw;
 52            }
 053        }
 54
 55        public async UniTask<WearableItem[]> Resolve(IEnumerable<string> wearableId, CancellationToken ct = default)
 56        {
 157            ct.ThrowIfCancellationRequested();
 58
 59            try
 60            {
 61
 1662                return await UniTask.WhenAll(wearableId.Select(x => Resolve(x, ct)));
 63            }
 064            catch (OperationCanceledException)
 65            {
 66                //No disposing required
 067                throw;
 68            }
 169        }
 70
 71        public async UniTask<WearableItem> Resolve(string wearableId, CancellationToken ct = default)
 72        {
 1573            if (disposeCts == null)
 1474                disposeCts = new CancellationTokenSource();
 1575            using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ct, disposeCts.Tok
 76
 1577            linkedCts.Token.ThrowIfCancellationRequested();
 78
 79            try
 80            {
 1581                if (wearablesRetrieved.ContainsKey(wearableId))
 082                    return wearablesRetrieved[wearableId];
 83
 84                // AttachExternalCancellation is needed because a CustomYieldInstruction requires a frame to operate
 1585                WearableItem wearable = await wearablesCatalogService.RequestWearableAsync(wearableId, linkedCts.Token).
 86
 1587                if (wearable == null && !wearableId.StartsWith("urn"))
 088                    wearable = await wearablesCatalogService.RequestWearableFromBuilderAsync(wearableId, linkedCts.Token
 89
 90                // Cancelling is irrelevant at this point,
 91                // either we have the wearable and we have to add it to forget it later
 92                // or it's null and we just return it
 1593                if (wearable != null)
 94                    // TODO: dispose replaced wearable if exists
 095                    wearablesRetrieved[wearableId] = wearable;
 96
 97                // return promise.value;
 1598                return wearable;
 99
 100            }
 0101            catch (Exception ex) when (ex is OperationCanceledException or PromiseException)
 102            {
 0103                wearablesRetrieved.Remove(wearableId);
 0104                return null;
 105            }
 106            finally
 107            {
 15108                disposeCts?.Dispose();
 15109                disposeCts = null;
 110            }
 15111        }
 112
 113        public void Forget(List<string> wearableIds)
 114        {
 1042115            foreach (string wearableId in wearableIds)
 116            {
 0117                wearablesRetrieved.Remove(wearableId);
 118            }
 521119            wearablesCatalogService.RemoveWearablesInUse(wearableIds);
 521120        }
 121
 0122        public void Forget(string wearableId) { wearablesCatalogService.RemoveWearablesInUse(new List<string> { wearable
 123
 124        public void Dispose()
 125        {
 521126            disposeCts?.Cancel();
 521127            disposeCts?.Dispose();
 521128            disposeCts = null;
 521129            Forget(wearablesRetrieved.Keys.ToList());
 521130            wearablesRetrieved.Clear();
 521131        }
 132    }
 133}