public void LoadIGPTopology(Topology.IGP.Topology topology)
        {
            topology.Clear();

            foreach (var record in GetIGPTopology())
            {
                var path = record.Values["p"].As <IPath>();

                Dictionary <long, string> nodeDatabaseIds = new Dictionary <long, string>();
                Dictionary <long, bool>   pseudonodes     = new Dictionary <long, bool>();

                foreach (var node in path.Nodes)
                {
                    string igpRouterIdentifier = TryGetNodePropertyAsString(node, "IGP_Router_Identifier");

                    if (!string.IsNullOrWhiteSpace(igpRouterIdentifier))
                    {
                        nodeDatabaseIds.Add(node.Id, igpRouterIdentifier);

                        Topology.Node.Node n = new Topology.Node.Node()
                        {
                            IgpRouterIdentifier = igpRouterIdentifier,
                            Psn = TryGetNodeProperty <int>(node, "psn"),
                            IPv4RouterIdentifier = TryGetNodePropertyAsString(node, "IPv4_Router_Identifier"),
                            NodeName             = TryGetNodePropertyAsString(node, "Node_Name"),
                            FirstSeen            = TryGetNodeProperty <long>(node, "First_Seen"),
                            LastEvent            = TryGetNodeProperty <long>(node, "Last_Event"),
                            OperationalStatus    = true
                        };

                        if (Regex.IsMatch(igpRouterIdentifier, @"^\d{12}$") && n.Psn == 0)
                        {
                            n.IsPseudonode = false;
                            n.NodeCost     = 1;

                            pseudonodes.Add(node.Id, n.IsPseudonode);
                        }
                        else
                        {
                            if (Regex.IsMatch(igpRouterIdentifier, @"^\d{12}\d+$") && n.Psn != 0)
                            {
                                n.IsPseudonode = true;
                                n.NodeCost     = 0;

                                pseudonodes.Add(node.Id, n.IsPseudonode);
                            }
                        }

                        topology.Update(n);
                    }
                }

                foreach (var link in path.Relationships)
                {
                    Topology.IGP.Link.Link l = new Topology.IGP.Link.Link()
                    {
                        SourceNode                     = nodeDatabaseIds[link.StartNodeId],
                        TargetNode                     = nodeDatabaseIds[link.EndNodeId],
                        Asn                            = TryGetRelProperty <long>(link, "asn"),
                        MaximumLinkBandwidth           = TryGetRelProperty <double>(link, "Maximum_Link_Bandwidth"),
                        MaximumReservableLinkBandwidth = TryGetRelProperty <double>(link, "Maximum_Reservable_Bandwidth"),
                        UnreservedBandwidth            = TryGetRelPropertyAsArray <double>(link, "Unreserved_Bandwidth"),
                        Rtt                            = TryGetRelProperty <long>(link, "rtt"),
                        IPv4InterfaceAddress           = TryGetRelPropertyAsString(link, "IPv4_Interface_Address"),
                        SharedRiskLinkGroups           = TryGetRelPropertyAsArray <long>(link, "Shared_Risk_Link_Groups"),
                        FirstSeen                      = TryGetRelProperty <long>(link, "First_Seen"),
                        LastEvent                      = TryGetRelProperty <long>(link, "Last_Event"),
                        OperationalStatus              = true
                    };

                    if (pseudonodes[link.StartNodeId] || pseudonodes[link.EndNodeId])
                    {
                        l.LinkCost = 0.5;
                    }
                    else
                    {
                        l.LinkCost = 1;
                    }

                    topology.Update(l);
                }
            }
        }
        static void Main(string[] args)
        {
            #region SHIFT YGGRDASIL2

            igp_topology  = new Topology.IGP.Topology();
            mpls_topology = new Topology.MPLS.Topology();

            ConcurrentQueue <JObject> igp_topology_changes_queue = new ConcurrentQueue <JObject>(); // IGP Topology Buffer
            bool igp_topology_task_enabled = false;

            ConcurrentQueue <JObject> mpls_topology_changes_queue = new ConcurrentQueue <JObject>(); // MPLS Topology Buffer
            bool mpls_topology_task_enabled = false;

            // Messaging
            Messaging.ControlQueue cq = new Messaging.ControlQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.ControlQueueRoutingKey
                );

            Messaging.IGP.TopologyQueue tq_igp = new Messaging.IGP.TopologyQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.IGPTopologyQueueRoutingKey
                );
            Messaging.MPLS.TopologyQueue tq_mpls = new Messaging.MPLS.TopologyQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.MPLSTopologyQueueRoutingKey
                );

            Messaging.PerformanceQueue pq = new Messaging.PerformanceQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.PerformanceQueueRoutingKey
                );
            Messaging.NodePCCQueue nq = new Messaging.NodePCCQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.NodePCCQueueRoutingKey
                );

            Messaging.IntentQueueConsumer intentQueueConsumer = new Messaging.IntentQueueConsumer(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.IntentQueueRoutingKey
                );
            #endregion

            #region SHIFT BACKEND CONNECTION

            // IGP Topology Queue Task
            var igp_topology_queue_task = new Task(() =>
            {
                while (igp_topology_task_enabled)
                {
                    while (!igp_topology_changes_queue.IsEmpty)
                    {
                        if (igp_topology_changes_queue.TryDequeue(out JObject data))
                        {
                            // Console.WriteLine("Topology Change: " + data);
                            igp_topology.Update(data);
                        }
                    }

                    Thread.Sleep(10);
                }
            }, TaskCreationOptions.LongRunning);

            // MPLS Topology Queue Task
            var mpls_topology_queue_task = new Task(() =>
            {
                while (mpls_topology_task_enabled)
                {
                    while (!mpls_topology_changes_queue.IsEmpty)
                    {
                        if (mpls_topology_changes_queue.TryDequeue(out JObject data))
                        {
                            // Console.WriteLine("Topology Change: " + data);
                            mpls_topology.Update(data);
                        }
                    }

                    Thread.Sleep(10);
                }
            }, TaskCreationOptions.LongRunning);

            // Control Queue Event Setup
            cq.OnStartCallback += (routing_key) =>
            {
                // IGP Topology Queue
                tq_igp.RoutingKey = routing_key;
                tq_igp.Connect();

                // MPLS Topology Queue
                tq_mpls.Connect();

                // Performance Queue
                pq.Connect();

                // Node PCC Queue
                nq.Connect();

                // Setup Topology Events
                igp_topology.OnNodeUpdateCallback += Igp_topology_OnNodeUpdateCallback;
                igp_topology.OnLinkUpdateCallback += Igp_topology_OnLinkUpdateCallback;
                igp_topology.OnLinkUpCallback     += Igp_topology_OnLinkUpCallback;
                igp_topology.OnLinkDownCallback   += Igp_topology_OnLinkDownCallback;

                // Load Topology
                data.Neo4J Neo4J = new data.Neo4J
                {
                    Neo4J_URI      = config.Neo4J_URI,
                    Neo4J_User     = config.Neo4J_User,
                    Neo4J_Password = config.Neo4J_Password
                };

                Neo4J.LoadIGPTopology(igp_topology);
                mpls_topology = Neo4J.LoadMPLSTopology();

                // Start Processing IGP Topology Changes Queue
                igp_topology_task_enabled = true;
                igp_topology_queue_task.Start();

                // Start Processing MPLS Topology Changes Queue
                mpls_topology_task_enabled = true;
                mpls_topology_queue_task.Start();

                // Connect Intent Queue Consumer
                intentQueueConsumer.Connect();
            };

            cq.OnTopologyQueueChangeCallback += (routing_key) =>
            {
                // Disconnect Intent Queue Cosumer
                intentQueueConsumer.Disconnect();

                // Stop Processing Topology Changes Queue
                igp_topology_task_enabled = false;
                while (igp_topology_queue_task.Status == TaskStatus.Running)
                {
                    Thread.Sleep(100);
                }

                // IGP Topology Queue
                tq_igp.RoutingKey = routing_key;
                tq_igp.Connect();

                // Setup Topology Events
                igp_topology.OnNodeUpdateCallback += Igp_topology_OnNodeUpdateCallback;
                igp_topology.OnLinkUpdateCallback += Igp_topology_OnLinkUpdateCallback;
                igp_topology.OnLinkUpCallback     += Igp_topology_OnLinkUpCallback;
                igp_topology.OnLinkDownCallback   += Igp_topology_OnLinkDownCallback;

                // Load Topology
                data.Neo4J Neo4J = new data.Neo4J
                {
                    Neo4J_URI      = config.Neo4J_URI,
                    Neo4J_User     = config.Neo4J_User,
                    Neo4J_Password = config.Neo4J_Password
                };

                Neo4J.LoadIGPTopology(igp_topology);
                mpls_topology = Neo4J.LoadMPLSTopology();

                // Start Processing Topology Changes Queue
                igp_topology_task_enabled = true;
                igp_topology_queue_task.Start();

                // Connect Intent Queue Consumer
                intentQueueConsumer.Connect();
            };

            // IGP Topology Queue Event Setup
            tq_igp.OnTopologyChangeCallback += (data) =>
            {
                // Enqueue Topology Change
                igp_topology_changes_queue.Enqueue(data);
            };

            // MPLS Topology Queue Event Setup
            tq_mpls.OnTopologyChangeCallback += (data) =>
            {
                // Enqueue Topology Change
                mpls_topology_changes_queue.Enqueue(data);
            };

            // Performance Queue Event Setup
            pq.OnPerformanceUpdateCallback += (data) =>
            {
                //Console.WriteLine("Performance Update: " + data);

                igp_topology.Update(data);
            };

            // Node PCC Queue Event Setup
            nq.OnNodePCCUpdateCallback += (data) =>
            {
                // Console.WriteLine("Node PCC Update: " + data);

                igp_topology.Update(data);
            };

            // Intent Queue Event Setup
            intentQueueConsumer.OnIntentJobCallback += IntentQueueConsumer_OnIntentJobCallback;

            // Control Queue Connect
            cq.Connect();

            #endregion

            Console.WriteLine("Runner Started.");

            string cmd = Console.ReadLine();

            while (cmd != "exit")
            {
                Console.WriteLine("Command not found.");
                Console.Write("> ");
                cmd = Console.ReadLine();
            }

            #region SHIFT BACKEND DISCONNECT
            cq.Disconnect();

            tq_igp.Disconnect();
            tq_mpls.Disconnect();

            pq.Disconnect();
            nq.Disconnect();

            intentQueueConsumer.Disconnect();
            #endregion
        }