< Summary

Class:DCL.MessagingBus
Assembly:DCL.Runtime
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/Messaging/MessagingBus.cs
Covered lines:98
Uncovered lines:36
Coverable lines:134
Total lines:333
Line coverage:73.1% (98 of 134)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
MessagingBus(...)0%110100%
Start()0%2100%
Stop()0%2.032080%
Dispose()0%110100%
Enqueue(...)0%16.0116096.88%
ProcessQueue(...)0%52.6626065.96%
OnMessageProcessed()0%220100%
AddReliableMessage(...)0%220100%
RemoveFirstReliableMessage()0%330100%
RemoveUnreliableMessage(...)0%6200%
LogMessage(...)0%6200%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/Messaging/MessagingBus.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Linq;
 5using UnityEngine;
 6using UnityEngine.Assertions;
 7using DCL.Interface;
 8using DCL.Models;
 9using MainScripts.DCL.Analytics.PerformanceAnalytics;
 10using UnityEngine.SceneManagement;
 11
 12namespace DCL
 13{
 14    public enum QueueMode
 15    {
 16        Reliable,
 17        Lossy,
 18    }
 19
 20    public class MessagingBus : IDisposable
 21    {
 22        public static bool VERBOSE = false;
 23
 24        public IMessageProcessHandler handler;
 25
 210426        public LinkedList<QueuedSceneMessage> pendingMessages = new LinkedList<QueuedSceneMessage>();
 027        public bool hasPendingMessages => pendingMessagesCount > 0;
 28
 29        //NOTE(Brian): This is handled manually. We aren't using pendingMessages.Count because is slow. Used heavily on 
 30        public int pendingMessagesCount;
 031        public long processedMessagesCount { get; set; }
 32
 033        private static bool renderingIsDisabled => !CommonScriptableObjects.rendererState.Get();
 34        private float timeBudgetValue;
 35
 36        public CustomYieldInstruction msgYieldInstruction;
 37
 38        public MessagingBusType type;
 39        public string debugTag;
 40
 41        public MessagingController owner;
 42        private IMessagingControllersManager manager;
 43
 210444        Dictionary<string, LinkedListNode<QueuedSceneMessage>> unreliableMessages =
 45            new Dictionary<string, LinkedListNode<QueuedSceneMessage>>();
 46
 47        public int unreliableMessagesReplaced = 0;
 48
 49        public bool enabled;
 50
 51        public float timeBudget
 52        {
 053            get => renderingIsDisabled ? float.MaxValue : timeBudgetValue;
 054            set => timeBudgetValue = value;
 55        }
 56
 210457        public MessagingBus(MessagingBusType type, IMessageProcessHandler handler, MessagingController owner)
 58        {
 210459            Assert.IsNotNull(handler, "IMessageHandler can't be null!");
 210460            this.handler = handler;
 210461            this.enabled = false;
 210462            this.type = type;
 210463            this.owner = owner;
 210464            this.pendingMessagesCount = 0;
 210465            manager = owner.messagingManager;
 210466        }
 67
 68        public void Start()
 69        {
 070            enabled = true;
 071        }
 72
 73        public void Stop()
 74        {
 613575            enabled = false;
 76
 613577            if (msgYieldInstruction is CleanableYieldInstruction cleanableYieldInstruction)
 078                cleanableYieldInstruction.Cleanup();
 79
 613580            pendingMessagesCount = 0;
 613581        }
 82
 83        public void Dispose()
 84        {
 207685            Stop();
 207686        }
 87
 88        public void Enqueue(QueuedSceneMessage message, QueueMode queueMode = QueueMode.Reliable)
 89        {
 3790            lock (unreliableMessages)
 91            {
 3792                if (message == null)
 093                    throw new Exception("A null message?");
 94
 3795                bool enqueued = true;
 96
 97                // When removing an entity we have to ensure that the enqueued lossy messages after it are processed and
 3798                if (message is QueuedSceneMessage_Scene queuedSceneMessage &&
 99                    queuedSceneMessage.payload is Protocol.RemoveEntity removeEntityPayload)
 100                {
 1101                    unreliableMessages = unreliableMessages
 1102                        .Where(kvp => !kvp.Key.Contains(removeEntityPayload.entityId))
 0103                        .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
 104                }
 105
 37106                if (queueMode == QueueMode.Reliable)
 107                {
 33108                    message.isUnreliable = false;
 33109                    AddReliableMessage(message);
 33110                }
 111                else
 112                {
 4113                    LinkedListNode<QueuedSceneMessage> node = null;
 4114                    message.isUnreliable = true;
 115
 4116                    if (unreliableMessages.ContainsKey(message.tag))
 117                    {
 1118                        node = unreliableMessages[message.tag];
 119
 1120                        if (node.List != null)
 121                        {
 1122                            node.Value = message;
 1123                            enqueued = false;
 1124                            unreliableMessagesReplaced++;
 125                        }
 126                    }
 127
 4128                    if (enqueued)
 129                    {
 3130                        node = AddReliableMessage(message);
 3131                        unreliableMessages[message.tag] = node;
 132                    }
 133                }
 134
 37135                if (enqueued)
 136                {
 36137                    if (message.type == QueuedSceneMessage.Type.SCENE_MESSAGE)
 138                    {
 2139                        QueuedSceneMessage_Scene sm = message as QueuedSceneMessage_Scene;
 2140                        ProfilingEvents.OnMessageWillQueue?.Invoke(sm.method);
 141                    }
 142
 36143                    if (type == MessagingBusType.INIT)
 144                    {
 27145                        manager.pendingInitMessagesCount++;
 146                    }
 147
 36148                    if (owner != null)
 149                    {
 36150                        owner.enabled = true;
 36151                        manager.MarkBusesDirty();
 152                    }
 153                }
 37154            }
 37155        }
 156
 157        public bool ProcessQueue(float timeBudget, out IEnumerator yieldReturn)
 158        {
 12159            yieldReturn = null;
 160
 161            // Note (Zak): This check is to avoid calling Time.realtimeSinceStartup
 162            // unnecessarily because it's pretty slow in JS
 12163            if (timeBudget <= 0 || !enabled || pendingMessagesCount == 0)
 0164                return false;
 165
 12166            float startTime = Time.realtimeSinceStartup;
 167
 44168            while (enabled && pendingMessagesCount > 0 && Time.realtimeSinceStartup - startTime < timeBudget)
 169            {
 170                LinkedListNode<QueuedSceneMessage> pendingMessagesFirst;
 171
 32172                lock (pendingMessages)
 173                {
 32174                    pendingMessagesFirst = pendingMessages.First;
 32175                }
 176
 177                // Note (Kinerius): This may be caused by 2 threads fighting for messages
 32178                if (pendingMessagesFirst == null)
 179                {
 0180                    pendingMessagesCount = 0;
 181
 0182                    continue;
 183                }
 184
 32185                QueuedSceneMessage m = pendingMessagesFirst.Value;
 186
 32187                PerformanceAnalytics.MessagesProcessedTracker.Track();
 188
 32189                RemoveFirstReliableMessage();
 190
 32191                if (m.isUnreliable)
 0192                    RemoveUnreliableMessage(m);
 193
 32194                bool shouldLogMessage = VERBOSE;
 195
 32196                switch (m.type)
 197                {
 198                    case QueuedSceneMessage.Type.NONE:
 199                        break;
 200                    case QueuedSceneMessage.Type.SCENE_MESSAGE:
 201
 1202                        if (!(m is QueuedSceneMessage_Scene sceneMessage))
 203                            continue;
 204
 1205                        if (handler.ProcessMessage(sceneMessage, out msgYieldInstruction))
 206                        {
 207#if UNITY_EDITOR
 0208                            if (DataStore.i.debugConfig.msgStepByStep)
 209                            {
 0210                                if (VERBOSE)
 211                                {
 0212                                    LogMessage(m, this, false);
 0213                                    shouldLogMessage = false;
 214                                }
 215
 0216                                return true;
 217                            }
 218#endif
 219                        }
 220                        else
 221                        {
 1222                            shouldLogMessage = false;
 223                        }
 224
 1225                        OnMessageProcessed();
 1226                        ProfilingEvents.OnMessageWillDequeue?.Invoke(sceneMessage.method);
 227
 1228                        if (msgYieldInstruction != null)
 229                        {
 0230                            processedMessagesCount++;
 231
 0232                            msgYieldInstruction = null;
 233                        }
 234
 0235                        break;
 236                    case QueuedSceneMessage.Type.LOAD_PARCEL:
 27237                        handler.LoadParcelScenesExecute(m.message);
 27238                        ProfilingEvents.OnMessageWillDequeue?.Invoke("LoadScene");
 239
 0240                        break;
 241                    case QueuedSceneMessage.Type.UNLOAD_PARCEL:
 2242                        handler.UnloadParcelSceneExecute(m.message);
 2243                        ProfilingEvents.OnMessageWillDequeue?.Invoke("UnloadScene");
 244
 0245                        break;
 246                    case QueuedSceneMessage.Type.UPDATE_PARCEL:
 1247                        handler.UpdateParcelScenesExecute(m.message);
 1248                        ProfilingEvents.OnMessageWillDequeue?.Invoke("UpdateScene");
 249
 0250                        break;
 251                    case QueuedSceneMessage.Type.UNLOAD_SCENES:
 1252                        handler.UnloadAllScenes();
 1253                        ProfilingEvents.OnMessageWillDequeue?.Invoke("UnloadAllScenes");
 254
 255                        break;
 256                }
 257
 32258                OnMessageProcessed();
 259#if UNITY_EDITOR
 32260                if (shouldLogMessage)
 261                {
 0262                    LogMessage(m, this);
 263                }
 264#endif
 265            }
 266
 12267            return false;
 268        }
 269
 270        public void OnMessageProcessed()
 271        {
 33272            processedMessagesCount++;
 273
 33274            if (type == MessagingBusType.INIT)
 275            {
 27276                manager.pendingInitMessagesCount--;
 27277                manager.processedInitMessagesCount++;
 278            }
 33279        }
 280
 281        private LinkedListNode<QueuedSceneMessage> AddReliableMessage(QueuedSceneMessage message)
 282        {
 36283            manager.pendingMessagesCount++;
 36284            pendingMessagesCount++;
 285
 286            LinkedListNode<QueuedSceneMessage> addReliableMessage;
 287
 36288            lock (pendingMessages)
 289            {
 36290                addReliableMessage = pendingMessages.AddLast(message);
 36291            }
 292
 36293            return addReliableMessage;
 294        }
 295
 296        private void RemoveFirstReliableMessage()
 297        {
 32298            lock (pendingMessages)
 299            {
 32300                if (pendingMessages.First != null)
 301                {
 32302                    pendingMessages.RemoveFirst();
 32303                    pendingMessagesCount--;
 32304                    manager.pendingMessagesCount--;
 305                }
 32306            }
 32307        }
 308
 309        private void RemoveUnreliableMessage(QueuedSceneMessage message)
 310        {
 0311            lock (unreliableMessages)
 312            {
 0313                unreliableMessages.Remove(message.tag);
 0314            }
 0315        }
 316
 317        private void LogMessage(QueuedSceneMessage m, MessagingBus bus, bool logType = true)
 318        {
 0319            string finalTag = WorldStateUtils.TryToGetSceneCoordsID(bus.debugTag);
 320
 0321            if (logType)
 322            {
 0323                Debug.Log(
 324                    $"#{bus.processedMessagesCount} ... bus = {finalTag}, id = {bus.type}... processing msg... type = {m
 0325            }
 326            else
 327            {
 0328                Debug.Log(
 329                    $"#{bus.processedMessagesCount} ... Bus = {finalTag}, id = {bus.type}... processing msg... {m.messag
 330            }
 0331        }
 332    }
 333}