예제 #1
0
        private void OnPackageReceived(Connection typedTcpConnection, TcpPackage package)
        {
            WorkItem workItem;
            ITaskCompletionWrapper wrapper;

            if (RemoveInProgressItem(package.CorrelationId, "PR", out workItem, out wrapper))
            {
            }
            else
            {
                if (!_outstandingOperations.TryGetValue(package.CorrelationId, out wrapper))
                {
                    // "SKIPPED [[ "
                    return;
                }
            }

            var result = wrapper.Process(package);

            switch (result.Status)
            {
            case ProcessResultStatus.Success:
                wrapper.Complete();
                break;

            case ProcessResultStatus.Retry:
                if (wrapper.UpdateForNextAttempt())
                {
                    RegisterHandler(wrapper.SentPackage.CorrelationId, wrapper);
                    EnqueueForSend(wrapper.SentPackage);
                }
                else
                {
                    wrapper.Fail(new Exception(string.Format("Retry is not supported in wrapper {0}.", wrapper.GetType())));
                }
                break;

            case ProcessResultStatus.NotifyError:
                wrapper.Fail(result.Exception);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #2
0
        public EventStoreConnection(IPEndPoint tcpEndPoint)
        {
            Ensure.NotNull(tcpEndPoint, "tcpEndPoint");

            _tcpEndPoint           = tcpEndPoint;
            _connector             = new TcpConnector(_tcpEndPoint);
            _outstandingOperations = new ConcurrentDictionary <Guid, ITaskCompletionWrapper>();

            _lastReconnectionTimestamp = DateTime.UtcNow;
            _connection = _connector.CreateTcpConnection(OnPackageReceived, ConnectionEstablished, ConnectionClosed);
            _timeoutCheckStopwatch.Start();

            _monitoringThread = new Thread(MonitoringLoop)
            {
                IsBackground = true,
                Name         = string.Format("Monitoring thread")
            };
            _monitoringThread.Start();
        }
예제 #3
0
        public Connection CreateTcpConnection(Action <Connection, TcpPackage> handlePackage,
                                              Action <Connection> connectionEstablished,
                                              Action <Connection, IPEndPoint, SocketError> connectionClosed)
        {
            var        connectionCreatedEvent = new AutoResetEvent(false);
            Connection typedConnection        = null;

            var connection = _connector.ConnectTo(
                _tcpEndpoint,
                tcpConnection =>
            {
                Log.Info("Connected to [{0}].", tcpConnection.EffectiveEndPoint);
                connectionCreatedEvent.WaitOne(500);
                connectionEstablished(typedConnection);
            },
                (conn, error) =>
            {
                var message = string.Format("Connection to [{0}] failed. Error: {1}.", conn.EffectiveEndPoint, error);
                Log.Error(message);

                connectionClosed(null, conn.EffectiveEndPoint, error);
            });

            typedConnection = new Connection(connection);
            typedConnection.ConnectionClosed +=
                (conn, error) =>
            {
                Log.Info("Connection [{0}] was closed {1}",
                         conn.EffectiveEndPoint,
                         error == SocketError.Success ? "cleanly." : "with error: " + error + ".");

                connectionClosed(conn, conn.EffectiveEndPoint, error);
            };

            connectionCreatedEvent.Set();

            typedConnection.ReceiveAsync((conn, pkg) =>
            {
                var package = new TcpPackage();
                var valid   = false;
                try
                {
                    package = TcpPackage.FromArraySegment(new ArraySegment <byte>(pkg));
                    valid   = true;

                    if (package.Command == TcpCommand.HeartbeatRequestCommand)
                    {
                        var response = new TcpPackage(TcpCommand.HeartbeatResponseCommand, Guid.NewGuid(), null);
                        conn.EnqueueSend(response.AsByteArray());
                        return;
                    }

                    handlePackage(conn, package);
                }
                catch (Exception e)
                {
                    var effectiveEndPoint = conn.EffectiveEndPoint;
                    var message           = string.Format("[{0}] ERROR for {1}. Connection will be closed.",
                                                          effectiveEndPoint,
                                                          valid ? package.Command as object : "<invalid package>");

                    Log.Info(e, message);
                    conn.Close();
                }
            });

            return(typedConnection);
        }
예제 #4
0
        public Connection CreateTcpConnection(Action<Connection, TcpPackage> handlePackage,
                                              Action<Connection> connectionEstablished,
                                              Action<Connection, IPEndPoint, SocketError> connectionClosed)
        {
            var connectionCreatedEvent = new AutoResetEvent(false);
            Connection typedConnection = null;

            var connection = _connector.ConnectTo(
                _tcpEndpoint,
                tcpConnection =>
                {
                    Log.Info("Connected to [{0}].", tcpConnection.EffectiveEndPoint);
                    connectionCreatedEvent.WaitOne(500);
                    connectionEstablished(typedConnection);
                },
                (conn, error) =>
                {
                    var message = string.Format("Connection to [{0}] failed. Error: {1}.", conn.EffectiveEndPoint, error);
                    Log.Error(message);

                    connectionClosed(null, conn.EffectiveEndPoint, error);
                });

            typedConnection = new Connection(connection);
            typedConnection.ConnectionClosed +=
                (conn, error) =>
                {
                    Log.Info("Connection [{0}] was closed {1}",
                             conn.EffectiveEndPoint,
                             error == SocketError.Success ? "cleanly." : "with error: " + error + ".");

                    connectionClosed(conn, conn.EffectiveEndPoint, error);
                };

            connectionCreatedEvent.Set();

            typedConnection.ReceiveAsync((conn, pkg) =>
            {
                var package = new TcpPackage();
                var valid = false;
                try
                {
                    package = TcpPackage.FromArraySegment(new ArraySegment<byte>(pkg));
                    valid = true;

                    if (package.Command == TcpCommand.HeartbeatRequestCommand)
                    {
                        var response = new TcpPackage(TcpCommand.HeartbeatResponseCommand, Guid.NewGuid(), null);
                        conn.EnqueueSend(response.AsByteArray());
                        return;
                    }

                    handlePackage(conn, package);
                }
                catch (Exception e)
                {
                    var effectiveEndPoint = conn.EffectiveEndPoint;
                    var message = string.Format("[{0}] ERROR for {1}. Connection will be closed.",
                                      effectiveEndPoint,
                                      valid ? package.Command as object : "<invalid package>");

                    Log.Info(e, message);
                    conn.Close();
                }
            });

            return typedConnection;
        }
예제 #5
0
        private void MonitoringLoop()
        {
            while (!_monitoringThreadStop)
            {
                TcpPackage nextPackage;
                if (_inProgressCount < TcpSentReceiveWindow && _sendQueue.TryDequeue(out nextPackage))
                {
                    Interlocked.Increment(ref _inProgressCount);

                    var workItem = new WorkItem(nextPackage);

                    Send(workItem, null);
                }
                else
                {
                    Thread.Sleep(1);
                }

                lock (_connectionLock)
                {
                    if (_reconnectionStopwatch.IsRunning && _reconnectionStopwatch.Elapsed >= ReconnectionDelay)
                    {
                        _reconnectionsCount       += 1;
                        _lastReconnectionTimestamp = DateTime.UtcNow;
                        _connection = _connector.CreateTcpConnection(OnPackageReceived,
                                                                     ConnectionEstablished,
                                                                     ConnectionClosed);
                        _reconnectionStopwatch.Stop();
                    }
                }

                if (_timeoutCheckStopwatch.Elapsed > EventTimeoutCheckPeriod)
                {
                    var now = DateTime.UtcNow;
                    foreach (var kvp in _inProgress)
                    {
                        var correlationId = kvp.Key;
                        var workerItem    = kvp.Value;

                        var lastUpdated = new DateTime(Interlocked.Read(ref workerItem.LastUpdatedTicks));
                        if (now - lastUpdated > EventTimeoutDelay || _reconnectionsCount > 10)
                        {
                            if (lastUpdated > _lastReconnectionTimestamp || _reconnectionsCount > 10)
                            {
                                WorkItem workItem;
                                ITaskCompletionWrapper completionWrapper;
                                if (RemoveInProgressItem(correlationId, " -ML timeout", out workItem, out completionWrapper))
                                {
                                    completionWrapper.Fail(
                                        new Exception(
                                            string.Format("Timed out event {0} which "
                                                          + "never got response from server was discovered. "
                                                          + "Last state update: {1}, last reconnect: {2}, now: {3}.",
                                                          workerItem.TcpPackage.CorrelationId,
                                                          lastUpdated,
                                                          _lastReconnectionTimestamp,
                                                          now)));
                                }
                            }
                            else
                            {
                                Retry(correlationId);
                            }
                        }
                    }
                    _timeoutCheckStopwatch.Restart();
                }
            }
        }
예제 #6
0
 private void ConnectionEstablished(Connection tcpTypedConnection)
 {
 }
예제 #7
0
 private void ConnectionClosed(Connection tcpTypedConnection, IPEndPoint endPoint, SocketError socketError)
 {
     lock (_connectionLock)
         _reconnectionStopwatch.Restart();
 }
        public EventStoreConnection(IPEndPoint tcpEndPoint)
        {
            Ensure.NotNull(tcpEndPoint, "tcpEndPoint");

            _tcpEndPoint = tcpEndPoint;
            _connector = new TcpConnector(_tcpEndPoint);
            _outstandingOperations = new ConcurrentDictionary<Guid, ITaskCompletionWrapper>();

            _lastReconnectionTimestamp = DateTime.UtcNow;
            _connection = _connector.CreateTcpConnection(OnPackageReceived, ConnectionEstablished, ConnectionClosed);
            _timeoutCheckStopwatch.Start();

            _monitoringThread = new Thread(MonitoringLoop)
            {
                IsBackground = true,
                Name = string.Format("Monitoring thread")
            };
            _monitoringThread.Start();
        }
        private void OnPackageReceived(Connection typedTcpConnection, TcpPackage package)
        {
            WorkItem workItem;
            ITaskCompletionWrapper wrapper;

            if (RemoveInProgressItem(package.CorrelationId, "PR", out workItem, out wrapper))
            {
            }
            else
            {
                if (!_outstandingOperations.TryGetValue(package.CorrelationId, out wrapper))
                {
                    // "SKIPPED [[ "
                    return;
                }
            }

            var result = wrapper.Process(package);
            switch (result.Status)
            {
                case ProcessResultStatus.Success:
                    wrapper.Complete();
                    break;
                case ProcessResultStatus.Retry:
                        if (wrapper.UpdateForNextAttempt())
                        {
                            RegisterHandler(wrapper.SentPackage.CorrelationId, wrapper);
                            EnqueueForSend(wrapper.SentPackage);
                        }
                        else
                            wrapper.Fail(new Exception(string.Format("Retry is not supported in wrapper {0}.", wrapper.GetType())));
                    break;
                case ProcessResultStatus.NotifyError:
                    wrapper.Fail(result.Exception);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
예제 #10
0
        private void MonitoringLoop()
        {
            while (!_monitoringThreadStop)
            {
                TcpPackage nextPackage;
                if (_inProgressCount < TcpSentReceiveWindow && _sendQueue.TryDequeue(out nextPackage))
                {
                    Interlocked.Increment(ref _inProgressCount);

                    var workItem = new WorkItem(nextPackage);

                    Send(workItem, null);
                }
                else
                    Thread.Sleep(1);

                lock (_connectionLock)
                {
                    if (_reconnectionStopwatch.IsRunning && _reconnectionStopwatch.Elapsed >= ReconnectionDelay)
                    {
                        _reconnectionsCount += 1;
                        _lastReconnectionTimestamp = DateTime.UtcNow;
                        _connection = _connector.CreateTcpConnection(OnPackageReceived,
                                                                     ConnectionEstablished,
                                                                     ConnectionClosed);
                        _reconnectionStopwatch.Stop();
                    }
                }

                if (_timeoutCheckStopwatch.Elapsed > EventTimeoutCheckPeriod)
                {
                    var now = DateTime.UtcNow;
                    foreach (var kvp in _inProgress)
                    {
                        var correlationId = kvp.Key;
                        var workerItem = kvp.Value;

                        var lastUpdated = new DateTime(Interlocked.Read(ref workerItem.LastUpdatedTicks));
                        if (now - lastUpdated > EventTimeoutDelay || _reconnectionsCount > 10)
                        {
                            if (lastUpdated > _lastReconnectionTimestamp || _reconnectionsCount > 10)
                            {
                                WorkItem workItem;
                                ITaskCompletionWrapper completionWrapper;
                                if (RemoveInProgressItem(correlationId, " -ML timeout", out workItem, out completionWrapper))
                                {
                                    completionWrapper.Fail(
                                        new Exception(
                                                string.Format("Timed out event {0} which "
                                                            + "never got response from server was discovered. "
                                                            + "Last state update: {1}, last reconnect: {2}, now: {3}.",
                                                            workerItem.TcpPackage.CorrelationId,
                                                            lastUpdated,
                                                            _lastReconnectionTimestamp,
                                                            now)));
                                }

                            }
                            else
                                Retry(correlationId);
                        }
                    }
                    _timeoutCheckStopwatch.Restart();
                }
            }
        }
예제 #11
0
 private void ConnectionEstablished(Connection tcpTypedConnection)
 {
 }
예제 #12
0
 private void ConnectionClosed(Connection tcpTypedConnection, IPEndPoint endPoint, SocketError socketError)
 {
     lock (_connectionLock)
         _reconnectionStopwatch.Restart();
 }