< Summary

Class:Catalyst
Assembly:Catalyst
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/ServiceProviders/Catalyst/Catalyst.cs
Covered lines:13
Uncovered lines:102
Coverable lines:115
Total lines:235
Line coverage:11.3% (13 of 115)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Catalyst()0%7.615052.94%
Dispose()0%110100%
GetContent()0%12300%
GetDeployedScenes(...)0%2100%
GetDeployedScenes(...)0%20400%
GetEntities(...)0%1101000%
Get(...)0%2100%
PlayerRealmOnChange(...)0%2100%
PlayerRealmAboutOnChange(...)0%12300%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/ServiceProviders/Catalyst/Catalyst.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using Cysharp.Threading.Tasks;
 5using DCL;
 6using DCL.Helpers;
 7using Decentraland.Bff;
 8using UnityEngine;
 9using Variables.RealmsInfo;
 10
 11public class Catalyst : ICatalyst
 12{
 13    private const float DEFAULT_CACHE_TIME = 5 * 60;
 14    private const int MAX_POINTERS_PER_REQUEST = 90;
 15
 016    public string contentUrl => realmContentServerUrl;
 017    public string lambdasUrl { get; private set; }
 18
 11019    private string realmDomain = "https://peer.decentraland.org";
 11020    private string realmContentServerUrl = "https://peer.decentraland.org/content";
 21
 11022    private readonly IDataCache<CatalystSceneEntityPayload[]> deployedScenesCache = new DataCache<CatalystSceneEntityPay
 23
 11024    public Catalyst()
 25    {
 11026        if (DataStore.i.realm.playerRealm.Get() != null)
 27        {
 028            realmDomain = DataStore.i.realm.playerRealm.Get().domain;
 029            lambdasUrl = $"{realmDomain}/lambdas";
 030            realmContentServerUrl = DataStore.i.realm.playerRealm.Get().contentServerUrl;
 031        }
 11032        else if (DataStore.i.realm.playerRealmAbout.Get() != null)
 33        {
 34            //TODO: This checks are going to dissapear when we inject the urls in kernel. Currently they are null,
 35            //and we dont want to override the ones that have been set up in playerRealm
 036            if(!string.IsNullOrEmpty(DataStore.i.realm.playerRealmAbout.Get().Lambdas.PublicUrl))
 037                lambdasUrl = DataStore.i.realm.playerRealmAbout.Get().Lambdas.PublicUrl;
 038            if(!string.IsNullOrEmpty(DataStore.i.realm.playerRealmAbout.Get().Content.PublicUrl))
 039                realmContentServerUrl = DataStore.i.realm.playerRealmAbout.Get().Content.PublicUrl;
 40        }
 41
 11042        DataStore.i.realm.playerRealm.OnChange += PlayerRealmOnChange;
 11043        DataStore.i.realm.playerRealmAbout.OnChange += PlayerRealmAboutOnChange;
 11044    }
 45
 46    public void Dispose()
 47    {
 11048        DataStore.i.realm.playerRealm.OnChange -= PlayerRealmOnChange;
 11049        DataStore.i.realm.playerRealmAbout.OnChange -= PlayerRealmAboutOnChange;
 11050        deployedScenesCache.Dispose();
 11051    }
 52
 53    public async UniTask<string> GetContent(string hash)
 54    {
 055        string callResult = "";
 056        string url = $"{realmContentServerUrl}/contents/" + hash;
 57
 058        var callPromise = Get(url);
 059        callPromise.Then( result =>
 60        {
 061            callResult = result;
 062        });
 63
 064        callPromise.Catch( error =>
 65        {
 066            callResult = error;
 067        });
 068        await callPromise;
 069        return callResult;
 070    }
 71
 072    public Promise<CatalystSceneEntityPayload[]> GetDeployedScenes(string[] parcels) { return GetDeployedScenes(parcels,
 73
 74    public Promise<CatalystSceneEntityPayload[]> GetDeployedScenes(string[] parcels, float cacheMaxAgeSeconds)
 75    {
 076        var promise = new Promise<CatalystSceneEntityPayload[]>();
 77
 078        string cacheKey = string.Join(";", parcels);
 79
 080        if (cacheMaxAgeSeconds >= 0)
 81        {
 082            if (deployedScenesCache.TryGet(cacheKey, out CatalystSceneEntityPayload[] cacheValue, out float lastUpdate))
 83            {
 084                if (Time.unscaledTime - lastUpdate <= cacheMaxAgeSeconds)
 85                {
 086                    promise.Resolve(cacheValue);
 087                    return promise;
 88                }
 89            }
 90        }
 91
 092        GetEntities(CatalystEntitiesType.SCENE, parcels)
 93            .Then(json =>
 94            {
 095                CatalystSceneEntityPayload[] scenes = null;
 096                bool hasException = false;
 97                try
 98                {
 099                    CatalystSceneEntityPayload[] parsedValue = Utils.ParseJsonArray<CatalystSceneEntityPayload[]>(json);
 100
 101                    // remove duplicated
 0102                    List<CatalystSceneEntityPayload> noDuplicates = new List<CatalystSceneEntityPayload>();
 0103                    for (int i = 0; i < parsedValue.Length; i++)
 104                    {
 0105                        var sceneToCheck = parsedValue[i];
 0106                        if (noDuplicates.Any(scene => scene.id == sceneToCheck.id))
 107                            continue;
 108
 0109                        noDuplicates.Add(sceneToCheck);
 110                    }
 111
 0112                    scenes = noDuplicates.ToArray();
 0113                }
 0114                catch (Exception e)
 115                {
 0116                    promise.Reject(e.Message);
 0117                    hasException = true;
 0118                }
 119                finally
 120                {
 0121                    if (!hasException)
 122                    {
 0123                        deployedScenesCache.Add(cacheKey, scenes, DEFAULT_CACHE_TIME);
 0124                        promise.Resolve(scenes);
 125                    }
 0126                }
 0127            })
 0128            .Catch(error => promise.Reject(error));
 129
 0130        return promise;
 131    }
 132
 133    public Promise<string> GetEntities(string entityType, string[] pointers)
 134    {
 0135        Promise<string> promise = new Promise<string>();
 136
 137        string[][] pointersGroupsToFetch;
 138
 0139        if (pointers.Length <= MAX_POINTERS_PER_REQUEST)
 140        {
 0141            pointersGroupsToFetch = new [] { pointers };
 0142        }
 143        else
 144        {
 145            // split pointers array in length of MAX_POINTERS_PER_REQUEST
 0146            int i = 0;
 0147            var query = from s in pointers
 0148                let num = i++
 0149                group s by num / MAX_POINTERS_PER_REQUEST
 150                into g
 0151                select g.ToArray();
 0152            pointersGroupsToFetch = query.ToArray();
 153        }
 154
 0155        if (pointersGroupsToFetch.Length == 0)
 156        {
 0157            promise.Reject("error: no pointers to fetch");
 0158            return promise;
 159        }
 160
 0161        Promise<string>[] splittedPromises = new Promise<string>[pointersGroupsToFetch.Length];
 162
 0163        for (int i = 0; i < pointersGroupsToFetch.Length; i++)
 164        {
 0165            string urlParams = "";
 0166            urlParams = pointersGroupsToFetch[i].Aggregate(urlParams, (current, pointer) => current + $"&pointer={pointe
 0167            string url = $"{realmContentServerUrl}/entities/{entityType}?{urlParams}";
 168
 0169            splittedPromises[i] = Get(url);
 0170            splittedPromises[i]
 171                .Then(value =>
 172                {
 173                    // check if all other promises have been resolved
 0174                    for (int j = 0; j < splittedPromises.Length; j++)
 175                    {
 0176                        if (splittedPromises[j] == null || splittedPromises[j].keepWaiting || !string.IsNullOrEmpty(spli
 177                        {
 0178                            return;
 179                        }
 180                    }
 181
 182                    // make sure not to continue if promise was already resolved
 0183                    if (!promise.keepWaiting)
 0184                        return;
 185
 186                    // build json with all promises result
 0187                    string json = splittedPromises[0].value.Substring(1, splittedPromises[0].value.Length - 2);
 0188                    for (int j = 1; j < splittedPromises.Length; j++)
 189                    {
 0190                        string jsonContent = splittedPromises[j].value.Substring(1, splittedPromises[j].value.Length - 2
 0191                        if (!string.IsNullOrEmpty(jsonContent))
 0192                            json += $",{jsonContent}";
 193                    }
 194
 0195                    promise.Resolve($"[{json}]");
 0196                });
 0197            splittedPromises[i].Catch(error => promise.Reject(error));
 198        }
 199
 0200        return promise;
 201    }
 202
 203    public Promise<string> Get(string url)
 204    {
 0205        Promise<string> promise = new Promise<string>();
 206
 0207        DCL.Environment.i.platform.webRequest.Get(url, null, request =>
 208        {
 0209            promise.Resolve(request.webRequest.downloadHandler.text);
 0210        }, request =>
 211        {
 0212            promise.Reject($"{request.webRequest.error} {request.webRequest.downloadHandler.text} at url {url}");
 0213        });
 214
 0215        return promise;
 216    }
 217
 218    private void PlayerRealmOnChange(CurrentRealmModel current, CurrentRealmModel previous)
 219    {
 0220        realmDomain = current.domain;
 0221        lambdasUrl = $"{realmDomain}/lambdas";
 0222        realmContentServerUrl = current.contentServerUrl;
 0223    }
 224
 225    private void PlayerRealmAboutOnChange(AboutResponse current, AboutResponse previous)
 226    {
 227        //TODO: This checks are going to dissapear when we inject the urls in kernel. Currently they are null,
 228        //and we dont want to override the ones that have been set up in playerRealm
 0229        if(!string.IsNullOrEmpty(current.Lambdas.PublicUrl))
 0230            lambdasUrl = current.Lambdas.PublicUrl;
 0231        if(!string.IsNullOrEmpty(current.Content.PublicUrl))
 0232            realmContentServerUrl = current.Content.PublicUrl;
 0233    }
 234
 235}