Example #1
0
        static void Main(string[] args)
        {
            Console.WriteLine("Starting...");


            ILogger           logger           = new SerilogLogger();
            ISerializer       serializer       = new ProtobufSerializer();
            IMessagePublisher messagePublisher = new MessagePublisher(logger, serializer);
            IOutgoingQueue    outgoingQueue    = new OutgoingQueue(logger, messagePublisher);

            messagePublisher.Start(9193);
            outgoingQueue.Start();

            IOrderRepository          orderRepository          = new OrderRepository();
            IOrderDispatcher          orderDispatcher          = new OrderDispatcher(outgoingQueue, logger, new DateService(), orderRepository);
            IIncomingMessageProcessor incomingMessageProcessor = new IncomingMessageProcessor(orderRepository, outgoingQueue, new DateService(), orderDispatcher, new ProtobufSerializer());
            IPerformanceRecorder      performanceRecorder      = new PerformanceRecorderDirectConsoleOutput(new DateService());
            IIncomingMessageQueue     incomingMessageQueue     = new IncomingMessageQueue(logger, incomingMessageProcessor, performanceRecorder);
            IClientMessagePuller      clientMessagePuller      = new ClientMessagePuller(logger, new ProtobufSerializer(), incomingMessageQueue);

            incomingMessageQueue.Start();
            clientMessagePuller.Start(9192);

            Console.WriteLine("Started. Hit any key to quit.");
            Console.ReadKey();

            Console.WriteLine("Stopping...");

            clientMessagePuller.Stop();
            incomingMessageQueue.Stop();
            outgoingQueue.Stop();
            messagePublisher.Stop();

            Console.WriteLine("Stopped");
        }
Example #2
0
        public ArraySegment <byte> GetNextChunk()
        {
            int chunky = 0;

            if (RemainingBytes >= Chunksizes)
            {
                chunky = Chunksizes;
            }
            else
            {
                chunky = RemainingBytes;
            }

            outgoing.Encode(CurrentOutGoingQueuedMessage, chunky, CurrentOutgoingMessageNumber, TotalOutgoingMessages, ChannelNumber);

            CurrentOutgoingMessageNumber++;
            if (CurrentOutgoingMessageNumber > TotalOutgoingMessages)
            {
                CurrentOutgoingMessageNumber = 0;
                TotalOutgoingMessages        = 0;

                if (OutgoingQueue.Count > 0)
                {
                    SetupOutGoing(OutgoingQueue.Dequeue());
                }
            }
            return(outgoing.GetEncodedMessage());
            // return new ArraySegment<byte>(outgoing.buffer,0,outgoing.buffer.Length);
        }
Example #3
0
        public ArraySegment <byte> GetNextChunk()
        {
            int chunky = 0;

            if (RemainingBytes >= Chunksizes)
            {
                chunky = Chunksizes;
            }
            else
            {
                chunky = RemainingBytes;
            }

            Array.Copy(CurrentOutGoingQueuedMessage, outgoing.buffer, chunky);
            outgoing.MessageLength = chunky;
            outgoing.MessageNumber = (ushort)CurrentOutgoingMessageNumber;
            outgoing.TotalMessages = (ushort)TotalOutgoingMessages;
            outgoing.ChannelNumber = ChannelNumber;
            outgoing.Encode();

            CurrentOutgoingMessageNumber++;
            if (CurrentOutgoingMessageNumber > TotalOutgoingMessages)
            {
                CurrentOutgoingMessageNumber = 0;
                TotalOutgoingMessages        = 0;

                if (OutgoingQueue.Count > 0)
                {
                    SetupOutGoing(OutgoingQueue.Dequeue());
                }
            }

            return(new ArraySegment <byte>(outgoing.buffer, 0, outgoing.buffer.Length));
        }
Example #4
0
        public override void SendNextPackets()
        {
            //check sending acks
            if (_mustSendAcks)
            {
                _mustSendAcks = false;
                NetUtils.DebugWrite("[RR]SendAcks");
                Monitor.Enter(_outgoingAcks);
                Peer.SendRawData(_outgoingAcks);
                Monitor.Exit(_outgoingAcks);
            }

            long currentTime = DateTime.UtcNow.Ticks;

            Monitor.Enter(_pendingPackets);
            //get packets from queue
            Monitor.Enter(OutgoingQueue);
            while (OutgoingQueue.Count > 0)
            {
                int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart);
                if (relate < _windowSize)
                {
                    PendingPacket pendingPacket = _pendingPackets[_localSeqence % _windowSize];
                    pendingPacket.Sended          = false;
                    pendingPacket.Packet          = OutgoingQueue.Dequeue();
                    pendingPacket.Packet.Sequence = (ushort)_localSeqence;
                    _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence;
                }
                else //Queue filled
                {
                    break;
                }
            }
            Monitor.Exit(OutgoingQueue);
            //send
            double resendDelay = Peer.ResendDelay;

            for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
            {
                PendingPacket currentPacket = _pendingPackets[pendingSeq % _windowSize];
                if (currentPacket.Packet == null)
                {
                    continue;
                }
                if (currentPacket.Sended) //check send time
                {
                    double packetHoldTime = currentTime - currentPacket.TimeStamp;
                    if (packetHoldTime < resendDelay * TimeSpan.TicksPerMillisecond)
                    {
                        continue;
                    }
                    NetUtils.DebugWrite("[RC]Resend: {0} > {1}", (int)packetHoldTime, resendDelay);
                }

                currentPacket.TimeStamp = currentTime;
                currentPacket.Sended    = true;
                Peer.SendRawData(currentPacket.Packet);
            }
            Monitor.Exit(_pendingPackets);
        }
        public void Queue_should_dequeue_item_once()
        {
            var queue = new OutgoingQueue<int>(10);
            queue.Enqueue(1);
            queue.Enqueue(2);
            Assert.Equal(new[] { 1 }, queue.Dequeue(1, TimeSpan.Zero, CancellationToken.None));

            Assert.Equal(new[] { 2 }, queue.Dequeue(1, TimeSpan.Zero, CancellationToken.None));
        }
Example #6
0
        public void Queue_should_dequeue_item_once()
        {
            var queue = new OutgoingQueue <int>(10);

            queue.Enqueue(1);
            queue.Enqueue(2);
            Assert.Equal(new[] { 1 }, queue.Dequeue(1, TimeSpan.Zero, CancellationToken.None));

            Assert.Equal(new[] { 2 }, queue.Dequeue(1, TimeSpan.Zero, CancellationToken.None));
        }
 public MonitorDataExchange(IHealthMonitorRegistry registry, IHealthMonitorExchangeClient exchangeClient, IMonitorableEndpointRegistry monitorableEndpointRegistry, DataExchangeConfig config)
 {
     _config = config;
     _registry = registry;
     _exchangeClient = exchangeClient;
     _monitorableEndpointRegistry = monitorableEndpointRegistry;
     _outgoingQueue = new OutgoingQueue<EndpointHealthUpdate>(_config.OutgoingQueueMaxCapacity);
     _exchangeThread = new Thread(StartExchange) { Name = "Exchange" };
     _exchangeThread.Start();
 }
        public void Queue_should_override_old_items_if_limit_is_reached()
        {
            var maxCapacity = 10;
            var queue = new OutgoingQueue<int>(maxCapacity);
            var all = Enumerable.Range(0, maxCapacity * 2).ToArray();
            foreach (var i in all)
                queue.Enqueue(i);

            var actual = queue.Dequeue(queue.Count, TimeSpan.Zero, CancellationToken.None);
            var expected = all.Skip(all.Length - maxCapacity).ToArray();
            Assert.Equal(expected, actual);
        }
Example #9
0
 public override void SendNextPackets()
 {
     lock (OutgoingQueue)
     {
         while (OutgoingQueue.Count > 0)
         {
             NetPacket packet = OutgoingQueue.Dequeue();
             Peer.SendUserData(packet);
             Peer.Recycle(packet);
         }
     }
 }
Example #10
0
 public bool Queue(string message)
 {
     if (OutgoingQueue.Count == 0)
     {
         SetupOutGoing(message);
     }
     else
     {
         OutgoingQueue.Enqueue(message);
     }
     return(true);
 }
Example #11
0
 public MonitorDataExchange(IHealthMonitorRegistry registry, IHealthMonitorExchangeClient exchangeClient, IMonitorableEndpointRegistry monitorableEndpointRegistry, DataExchangeConfig config)
 {
     _config         = config;
     _registry       = registry;
     _exchangeClient = exchangeClient;
     _monitorableEndpointRegistry = monitorableEndpointRegistry;
     _outgoingQueue  = new OutgoingQueue <EndpointHealthUpdate>(_config.OutgoingQueueMaxCapacity);
     _exchangeThread = new Thread(StartExchange)
     {
         Name = "Exchange"
     };
     _exchangeThread.Start();
 }
Example #12
0
 public override void SendNextPackets()
 {
     lock (OutgoingQueue)
     {
         while (OutgoingQueue.Count > 0)
         {
             NetPacket packet = OutgoingQueue.Dequeue();
             _localSequence  = (_localSequence + 1) % NetConstants.MaxSequence;
             packet.Sequence = (ushort)_localSequence;
             Peer.SendRawData(packet);
             Peer.Recycle(packet);
         }
     }
 }
Example #13
0
        protected override bool SendNextPackets()
        {
            if (_reliable && OutgoingQueue.Count == 0)
            {
                long currentTime    = DateTime.UtcNow.Ticks;
                long packetHoldTime = currentTime - _lastPacketSendTime;
                if (packetHoldTime >= Peer.ResendDelay * TimeSpan.TicksPerMillisecond)
                {
                    var packet = _lastPacket;
                    if (packet != null)
                    {
                        _lastPacketSendTime = currentTime;
                        Peer.SendUserData(packet);
                    }
                }
            }
            else
            {
                lock (OutgoingQueue)
                {
                    while (OutgoingQueue.Count > 0)
                    {
                        NetPacket packet = OutgoingQueue.Dequeue();
                        _localSequence   = (_localSequence + 1) % NetConstants.MaxSequence;
                        packet.Sequence  = (ushort)_localSequence;
                        packet.ChannelId = _id;
                        Peer.SendUserData(packet);

                        if (_reliable && OutgoingQueue.Count == 0)
                        {
                            _lastPacketSendTime = DateTime.UtcNow.Ticks;
                            _lastPacket         = packet;
                        }
                        else
                        {
                            Peer.NetManager.NetPacketPool.Recycle(packet);
                        }
                    }
                }
            }

            if (_reliable && _mustSendAck)
            {
                _mustSendAck        = false;
                _ackPacket.Sequence = _remoteSequence;
                Peer.SendUserData(_ackPacket);
            }

            return(_lastPacket != null);
        }
Example #14
0
        protected override bool SendNextPackets()
        {
            if (_mustSendAcks)
            {
                _mustSendAcks = false;
                NetDebug.Write("[RR]SendAcks");
                lock (_outgoingAcks)
                    Peer.SendUserData(_outgoingAcks);
            }

            long currentTime       = DateTime.UtcNow.Ticks;
            bool hasPendingPackets = false;

            lock (_pendingPackets)
            {
                //get packets from queue
                lock (OutgoingQueue)
                {
                    while (OutgoingQueue.Count > 0)
                    {
                        int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart);
                        if (relate >= _windowSize)
                        {
                            break;
                        }

                        var netPacket = OutgoingQueue.Dequeue();
                        netPacket.Sequence  = (ushort)_localSeqence;
                        netPacket.ChannelId = _id;
                        _pendingPackets[_localSeqence % _windowSize].Init(netPacket);
                        _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence;
                    }
                }

                //send
                for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
                {
                    // Please note: TrySend is invoked on a mutable struct, it's important to not extract it into a variable here
                    bool hasPacket;
                    _pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer, out hasPacket);
                    if (hasPacket)
                    {
                        hasPendingPackets = true;
                    }
                }
            }

            return(hasPendingPackets || _mustSendAcks || OutgoingQueue.Count > 0);
        }
        public void Queue_should_return_immediately_a_bucket_if_there_is_enough_elements_to_fill_it()
        {
            var maxCapacity = 1000;
            var bucketSize = 500;
            var queue = new OutgoingQueue<int>(maxCapacity);
            for (var i = 0; i < maxCapacity; i++)
                queue.Enqueue(i);

            var watch = Stopwatch.StartNew();
            var items = queue.Dequeue(bucketSize, TimeSpan.FromSeconds(2), CancellationToken.None);
            watch.Stop();

            Assert.Equal(bucketSize, items.Length);
            Assert.True(watch.Elapsed < TimeSpan.FromSeconds(1), "watch.Elapsed < TimeSpan.FromSeconds(1)");
        }
        public void Queue_should_return_available_items_if_timeout_reached()
        {
            var bucketSize = 500;
            var queue = new OutgoingQueue<int>(bucketSize + 1);
            var availableItemsCount = bucketSize - 1;
            for (var i = 0; i < availableItemsCount; i++)
                queue.Enqueue(i);

            var timeout = TimeSpan.FromMilliseconds(500);
            var watch = Stopwatch.StartNew();
            var items = queue.Dequeue(bucketSize, timeout, CancellationToken.None);
            watch.Stop();

            Assert.Equal(availableItemsCount, items.Length);
            Assert.True(watch.Elapsed > (timeout - AcceptableTimeDelta).Duration(), $"Expected full timeout! Elapsed time: {watch.Elapsed}");
        }
Example #17
0
        public void Queue_should_override_old_items_if_limit_is_reached()
        {
            var maxCapacity = 10;
            var queue       = new OutgoingQueue <int>(maxCapacity);
            var all         = Enumerable.Range(0, maxCapacity * 2).ToArray();

            foreach (var i in all)
            {
                queue.Enqueue(i);
            }

            var actual   = queue.Dequeue(queue.Count, TimeSpan.Zero, CancellationToken.None);
            var expected = all.Skip(all.Length - maxCapacity).ToArray();

            Assert.Equal(expected, actual);
        }
Example #18
0
        /// <summary>
        /// The main entry function for the application.
        /// </summary>
        /// <param name="args">Command line arguments.</param>
        // ReSharper disable once UnusedParameter.Local
        static void Main(String[] args)
        {
            //Console.SetBufferSize(250, 20000);
            //Console.SetWindowSize(250, 50);
            Logger.Info("TwitchTally v" + Assembly.GetExecutingAssembly().GetName().Version + " started.");
            OutgoingQueue.Initialize();
            //ConnectToIrc();
            Boolean exitApplication = false;

            while (!exitApplication)
            {
                Console.Write("> ");
                exitApplication = ParseCommand(Console.ReadLine());
            }
            Close();
            Environment.Exit(1);
        }
        public void Queue_should_return_available_items_if_cancelled()
        {
            var bucketSize = 500;
            var queue = new OutgoingQueue<int>(bucketSize + 1);
            var availableItemsCount = bucketSize - 1;
            for (var i = 0; i < availableItemsCount; i++)
                queue.Enqueue(i);

            var timeout = TimeSpan.FromMilliseconds(500);
            var watch = Stopwatch.StartNew();
            var maxWaitTime = TimeSpan.FromSeconds(5);
            var items = queue.Dequeue(bucketSize, maxWaitTime, new CancellationTokenSource(timeout).Token);
            watch.Stop();

            Assert.Equal(availableItemsCount, items.Length);
            Assert.True((watch.Elapsed - timeout).Duration() < maxWaitTime, $"Expected task cancellation before {maxWaitTime}");
        }
Example #20
0
        public override void SendNextPackets()
        {
            if (_mustSendAcks)
            {
                _mustSendAcks = false;
                NetDebug.Write("[RR]SendAcks");
                lock (_outgoingAcks)
                {
                    Peer.SendUserData(_outgoingAcks);
                }
            }

            var currentTime = DateTime.UtcNow.Ticks;

            lock (_pendingPackets)
            {
                //get packets from queue
                lock (OutgoingQueue)
                {
                    while (OutgoingQueue.Count > 0)
                    {
                        var relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart);
                        if (relate >= _windowSize)
                        {
                            break;
                        }

                        var netPacket = OutgoingQueue.Dequeue();
                        netPacket.Sequence  = (ushort)_localSeqence;
                        netPacket.ChannelId = _id;
                        _pendingPackets[_localSeqence % _windowSize].Init(netPacket);
                        _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence;
                    }
                }

                //send
                for (var pendingSeq = _localWindowStart;
                     pendingSeq != _localSeqence;
                     pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
                {
                    _pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer);
                }
            }
        }
Example #21
0
        public void Queue_should_return_immediately_a_bucket_if_there_is_enough_elements_to_fill_it()
        {
            var maxCapacity = 1000;
            var bucketSize  = 500;
            var queue       = new OutgoingQueue <int>(maxCapacity);

            for (var i = 0; i < maxCapacity; i++)
            {
                queue.Enqueue(i);
            }

            var watch = Stopwatch.StartNew();
            var items = queue.Dequeue(bucketSize, TimeSpan.FromSeconds(2), CancellationToken.None);

            watch.Stop();

            Assert.Equal(bucketSize, items.Length);
            Assert.True(watch.Elapsed < TimeSpan.FromSeconds(1), "watch.Elapsed < TimeSpan.FromSeconds(1)");
        }
Example #22
0
        public void Queue_should_return_available_items_if_timeout_reached()
        {
            var bucketSize          = 500;
            var queue               = new OutgoingQueue <int>(bucketSize + 1);
            var availableItemsCount = bucketSize - 1;

            for (var i = 0; i < availableItemsCount; i++)
            {
                queue.Enqueue(i);
            }

            var timeout = TimeSpan.FromMilliseconds(500);
            var watch   = Stopwatch.StartNew();
            var items   = queue.Dequeue(bucketSize, timeout, CancellationToken.None);

            watch.Stop();

            Assert.Equal(availableItemsCount, items.Length);
            Assert.True(watch.Elapsed > (timeout - AcceptableTimeDelta).Duration(), $"Expected full timeout! Elapsed time: {watch.Elapsed}");
        }
Example #23
0
        public override void SendNextPackets()
        {
            if (_reliable && OutgoingQueue.Count == 0)
            {
                NetPacket packet = _lastPacket;
                if (packet != null)
                {
                    Peer.SendUserData(packet);
                }
            }
            else
            {
                lock (OutgoingQueue)
                {
                    while (OutgoingQueue.Count > 0)
                    {
                        NetPacket packet = OutgoingQueue.Dequeue();
                        _localSequence   = (_localSequence + 1) % NetConstants.MaxSequence;
                        packet.Sequence  = (ushort)_localSequence;
                        packet.ChannelId = _id;
                        Peer.SendUserData(packet);

                        if (_reliable && OutgoingQueue.Count == 0)
                        {
                            _lastPacket = packet;
                        }
                        else
                        {
                            Peer.Recycle(packet);
                        }
                    }
                }
            }

            if (_reliable && _mustSendAck)
            {
                _mustSendAck        = false;
                _ackPacket.Sequence = _remoteSequence;
                Peer.SendUserData(_ackPacket);
            }
        }
Example #24
0
        public override void SendNextPackets()
        {
            //check sending acks
            if (_mustSendAcks)
            {
                _mustSendAcks = false;
                NetDebug.Write("[RR]SendAcks");
                Monitor.Enter(_outgoingAcks);
                Peer.SendUserData(_outgoingAcks);
                Monitor.Exit(_outgoingAcks);
            }

            long currentTime = DateTime.UtcNow.Ticks;

            Monitor.Enter(_pendingPackets);
            //get packets from queue
            Monitor.Enter(OutgoingQueue);
            while (OutgoingQueue.Count > 0)
            {
                int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart);
                if (relate < _windowSize)
                {
                    var netPacket = OutgoingQueue.Dequeue();
                    netPacket.Sequence  = (ushort)_localSeqence;
                    netPacket.ChannelId = _id;
                    _pendingPackets[_localSeqence % _windowSize].Init(netPacket);
                    _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence;
                }
                else //Queue filled
                {
                    break;
                }
            }
            Monitor.Exit(OutgoingQueue);
            //send
            for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
            {
                _pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer);
            }
            Monitor.Exit(_pendingPackets);
        }
Example #25
0
        public void Queue_should_return_available_items_if_cancelled()
        {
            var bucketSize          = 500;
            var queue               = new OutgoingQueue <int>(bucketSize + 1);
            var availableItemsCount = bucketSize - 1;

            for (var i = 0; i < availableItemsCount; i++)
            {
                queue.Enqueue(i);
            }

            var timeout     = TimeSpan.FromMilliseconds(500);
            var watch       = Stopwatch.StartNew();
            var maxWaitTime = TimeSpan.FromSeconds(5);
            var items       = queue.Dequeue(bucketSize, maxWaitTime, new CancellationTokenSource(timeout).Token);

            watch.Stop();

            Assert.Equal(availableItemsCount, items.Length);
            Assert.True((watch.Elapsed - timeout).Duration() < maxWaitTime, $"Expected task cancellation before {maxWaitTime}");
        }
Example #26
0
        public static void Replay(String fileName)
        {
            Logger.Info("Replaying Chat Log: {0}", new FileInfo(fileName).Name);
            Int64     ircCounter  = 0;
            Int64     metaCounter = 0;
            Stopwatch stopwatch;

            using (StreamReader logReader = File.OpenText(fileName)) {
                String curLine;
                stopwatch = Stopwatch.StartNew();
                while ((curLine = logReader.ReadLine()) != null)
                {
                    if (curLine.Length >= 29)
                    {
                        if (curLine.Substring(28, 1) == "|")
                        {
                            // Do we want to change this to QueueLog just in case we do something
                            // special later?
                            OutgoingQueue.QueueRaw(curLine);
                            ircCounter++;
                        }
                        else if (curLine.Substring(28, 1) == "#")
                        {
                            // Do we do anything here?
                            metaCounter++;
                        }
                    }
                }
                stopwatch.Stop();
            }
            Int64  totalLines = ircCounter + metaCounter;
            Double speed      = (Double)totalLines / stopwatch.ElapsedMilliseconds * 1000.0;

            Logger.Info("   Done! Took {0:n0} milliseconds.", stopwatch.ElapsedMilliseconds);
            Logger.Info("      IRC Lines: {0:n0}", ircCounter);
            Logger.Info("     Meta Lines: {0:n0}", metaCounter);
            Logger.Info("          Speed: {0:n0} Lines/Sec", speed);
        }
        private async Task <bool> SendMessage(string messageText)
        {
            Debug.WriteLine("starting sendmessage");
            try
            {
                if (messageText != string.Empty)
                {
                    var           now     = Util.CurrentTimeMillis();
                    SignalMessage message = new SignalMessage()
                    {
                        Author            = null,
                        ComposedTimestamp = now,
                        Content           = new SignalMessageContent()
                        {
                            Content = messageText
                        },
                        ThreadId          = SelectedThread.ThreadId,
                        ReceivedTimestamp = now,
                        Direction         = SignalMessageDirection.Outgoing,
                        Read = true,
                        Type = SignalMessageType.Normal
                    };
                    Debug.WriteLine("keydown lock await");
                    using (await ActionInProgress.LockAsync())
                    {
                        Debug.WriteLine("keydown lock grabbed");

                        /* update in-memory data */
                        SelectedThread.MessagesCount       += 1;
                        SelectedThread.UnreadCount          = 0;
                        SelectedThread.LastMessage          = message;
                        SelectedThread.LastSeenMessageIndex = SelectedThread.MessagesCount;
                        SelectedThread.View.UpdateConversationDisplay(SelectedThread);
                        var container = new SignalMessageContainer(message, (int)SelectedThread.MessagesCount - 1);
                        View.Thread.Append(container, true);
                        MoveThreadToTop(SelectedThread);

                        /* save to disk */
                        await Task.Run(() =>
                        {
                            SignalDBContext.SaveMessageLocked(message);
                        });

                        /* add to OutgoingCache */
                        View.Thread.AddToOutgoingMessagesCache(container);

                        /* send */
                        OutgoingQueue.Add(message);
                    }
                    Debug.WriteLine("keydown lock released");
                }
                return(true);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                Debug.WriteLine(ex.Message);
                Debug.WriteLine(ex.StackTrace);
                return(false);
            }
        }
        private void RemotePublish(ref PublishingQueue queueItem, PublishingAction action)
        {
            var site = queueItem.Site;

            if (site != null)
            {
                switch (queueItem.PublishingObject)
                {
                case PublishingObject.Page:
                    if (queueItem.RemoteEndpoints != null)
                    {
                        var page = new Page(site, queueItem.ObjectUUID).AsActual();
                        if (page != null)
                        {
                            foreach (var remote in queueItem.RemoteEndpoints)
                            {
                                var outgoingQueue = new OutgoingQueue(queueItem.Site, Kooboo.UniqueIdGenerator.GetInstance().GetBase32UniqueId(10));
                                outgoingQueue.PublishingObject = queueItem.PublishingObject;
                                outgoingQueue.ObjectUUID       = queueItem.ObjectUUID;
                                outgoingQueue.RemoteEndpoint   = remote;
                                outgoingQueue.UtcCreationDate  = DateTime.UtcNow;
                                outgoingQueue.Status           = QueueStatus.Pending;
                                outgoingQueue.RetryTimes       = 0;
                                outgoingQueue.Action           = action;
                                outgoingQueue.PublishDraft     = queueItem.PublishDraft;
                                _outgoingQueueProvider.Add(outgoingQueue);
                            }
                        }
                        else
                        {
                            NoSuchObjectMessage(ref queueItem);
                        }
                    }
                    NoAnyEndPoint(ref queueItem);
                    break;

                case PublishingObject.TextContent:
                    if (queueItem.PublishingMappings != null)
                    {
                        var contentIntegrateId = new ContentIntegrateId(queueItem.ObjectUUID);
                        var repository         = new Repository(contentIntegrateId.Repository).AsActual();;
                        if (repository != null)
                        {
                            var textFolder = new TextFolder(repository, contentIntegrateId.FolderName).AsActual();
                            if (textFolder != null)
                            {
                                var contentUUID = contentIntegrateId.ContentUUID;

                                foreach (var mappingName in queueItem.PublishingMappings)
                                {
                                    var mapping = new RemoteTextFolderMapping();    //todo:AsActual
                                    if (mapping != null)
                                    {
                                        var outgoingQueue = new OutgoingQueue(queueItem.Site, Kooboo.UniqueIdGenerator.GetInstance().GetBase32UniqueId(10));
                                        outgoingQueue.PublishingObject = queueItem.PublishingObject;
                                        outgoingQueue.ObjectUUID       = queueItem.ObjectUUID;
                                        outgoingQueue.RemoteEndpoint   = mapping.RemoteEndpoint;
                                        outgoingQueue.RemoteFolderId   = mapping.RemoteFolderId;
                                        outgoingQueue.UtcCreationDate  = DateTime.UtcNow;
                                        outgoingQueue.Status           = QueueStatus.Pending;
                                        outgoingQueue.RetryTimes       = 0;
                                        outgoingQueue.Action           = action;
                                        outgoingQueue.PublishDraft     = queueItem.PublishDraft;
                                        _outgoingQueueProvider.Add(outgoingQueue);
                                    }
                                }
                            }
                            else
                            {
                                NoSuchObjectMessage(ref queueItem);
                            }
                        }
                        else
                        {
                            NoSuchObjectMessage(ref queueItem);
                        }
                    }
                    NoAnyEndPoint(ref queueItem);
                    break;

                default:
                    NoSuchPublishingObject(ref queueItem);
                    break;
                }
            }
        }