コード例 #1
0
        private IStanConnection Connect(string clusterId, string clientId, StanOptions opts = null)
        {
            try
            {
                if (String.IsNullOrEmpty(clusterId) || String.IsNullOrEmpty(clientId))
                {
                    return(null);
                }

                if (stanConnection == null || stanConnection.NATSConnection == null)
                {
                    if (opts == null)
                    {
                        stanConnection = new StanConnectionFactory().CreateConnection(clusterId, clientId);
                    }
                    else
                    {
                        stanConnection = new StanConnectionFactory().CreateConnection(clusterId, clientId, opts);
                    }
                }
            }
            catch (STAN.Client.StanConnectionException ex)
            {
                InternalLogger.Error(ex, $"NATS connection exception.");
            }
            catch (STAN.Client.StanConnectRequestTimeoutException ex)
            {
                InternalLogger.Error(ex, $"NATS connection request timeout exception.");
            }

            return(stanConnection);
        }
コード例 #2
0
        public StanMessageReceiverService(
            IConfiguration configuration,
            ILogger <StanMessageReceiverService> logger,
            MessagingEvent messagingEvent,
            IServiceProvider serviceProvider)
        {
            _configuration   = configuration;
            _logger          = logger;
            _serviceProvider = serviceProvider;
            _messagingEvent  = messagingEvent;

            var opts = StanOptions.GetDefaultOptions();

            opts.NatsURL = _configuration.GetValue <string>("Messaging:Stan:Servers");
            string clusterID = _configuration.GetValue <string>("Messaging:Stan:ClusterId");

            qGroup = _configuration.GetValue <string>("Messaging:Group");
            try
            {
                _connection = new StanConnectionFactory().CreateConnection(clusterID, qGroup, opts);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error messaging connection");
                //throw ex;
            }
        }
コード例 #3
0
        public void Start()
        {
            // connect to STAN
            var cf          = new StanConnectionFactory();
            var natsOptions = StanOptions.GetDefaultOptions();

            natsOptions.NatsURL = "nats://localhost:4223";
            _stanConnection     = cf.CreateConnection("test-cluster", "ShippingService", natsOptions);

            // create events subscription
            StanSubscriptionOptions stanOptions = StanSubscriptionOptions.GetDefaultOptions();

            stanOptions.DurableName = "ShippingService";

            // determine where to start reading in the event-stream
            ulong?lastSeqNr = GetLastSequenceNumber();

            if (lastSeqNr != null)
            {
                lastSeqNr++;
                stanOptions.StartAt(lastSeqNr.Value);

                Console.WriteLine($"Replaying from seq# {lastSeqNr}");
            }
            else
            {
                stanOptions.DeliverAllAvailable();

                Console.WriteLine("Replaying all messages.");
            }

            _stanConnection.Subscribe("store.events", stanOptions, EventReceived);
        }
コード例 #4
0
ファイル: Program.cs プロジェクト: dream-stream/PlayGround
        private TimeSpan ReceiveAsyncSubscriber(IStanConnection c)
        {
            var sw = new Stopwatch();
            var ev = new AutoResetEvent(false);

            EventHandler <StanMsgHandlerArgs> msgHandler = (sender, args) =>
            {
                if (_received == 0)
                {
                    sw.Start();
                }

                _received++;

                if (Verbose)
                {
                    Console.WriteLine("Received seq # {0}: {1}",
                                      args.Message.Sequence,
                                      System.Text.Encoding.UTF8.GetString(args.Message.Data));
                }

                if (_received >= Count)
                {
                    sw.Stop();
                    ev.Set();
                }
            };

            using (var s = c.Subscribe(Subject, _sOpts, msgHandler))
            {
                ev.WaitOne();
            }

            return(sw.Elapsed);
        }
コード例 #5
0
        //---------------------------------------------------------------------
        // IStanConnection extensions

        /// <summary>
        /// Publish publishes the data argument to the given subject. The data
        /// argument is left untouched and needs to be correctly interpreted on
        /// the receiver.  This API is synchronous and waits for the acknowledgement
        /// or error from the NATS streaming server.
        /// </summary>
        /// <typeparam name="TMessage">The message type.</typeparam>
        /// <param name="connection">The conmnection.</param>
        /// <param name="subject">Subject to publish the message to.</param>
        /// <param name="data">Message payload.</param>
        /// <exception cref="StanException">When an error occurs locally or on the NATS streaming server.</exception>
        public static void Publish <TMessage>(this IStanConnection connection, string subject, TMessage data)
            where TMessage : class, IRoundtripData, new()
        {
            Covenant.Requires <ArgumentNullException>(data != null);

            connection.Publish(subject, data.ToBytes());
        }
コード例 #6
0
        /// <summary>
        /// Publish publishes the data argument to the given subject. The data
        /// argument is left untouched and needs to be correctly interpreted on
        /// the receiver.  This API is asynchronous and handles the acknowledgement
        /// or error from the NATS streaming server in the provided handler.  An exception is thrown when
        /// an error occurs during the send, the handler will process acknowledgments and errors.
        /// </summary>
        /// <typeparam name="TMessage">The message type.</typeparam>
        /// <param name="connection">The conmnection.</param>
        /// <param name="subject">Subject to publish the message to.</param>
        /// <param name="data"></param>
        /// <returns>The task object representing the asynchronous operation, containing the guid.</returns>
        public static async Task <string> PublishAsync <TMessage>(this IStanConnection connection, string subject, TMessage data)
            where TMessage : class, IRoundtripData, new()
        {
            Covenant.Requires <ArgumentNullException>(data != null);

            return(await connection.PublishAsync(subject, data.ToBytes()));
        }
コード例 #7
0
        public async Task StartAsync(string consumerId)
        {
            StanOptions options = StanOptions.GetDefaultOptions();

            options.NatsURL = _natsOptions.Url;

            var stanSubOptions = StanSubscriptionOptions.GetDefaultOptions();

            stanSubOptions.DurableName = _natsOptions.DurableName;

            _stanConnection = new StanConnectionFactory()
                              .CreateConnection(_natsOptions.ClusterId, consumerId, options);

            try
            {
                _stanConnection
                .Subscribe(_natsOptions.Subject, stanSubOptions, (obj, args) =>
                {
                    string messageData = Encoding.UTF8.GetString(args.Message.Data);
                    Console.WriteLine($"[#{args.Message.Sequence}] {messageData}");

                    var message    = JsonSerializer.Deserialize <Message>(messageData);
                    message.Number = args.Message.Sequence;
                    _messageRepository.AddAsync(message).GetAwaiter().GetResult();
                });
            }
            catch (Exception e)
            {
                _logger.LogError($"Ошибка подписки на сообщения: {e.ToString()}");
                CloseConnection();
            }

            await Task.CompletedTask;
        }
コード例 #8
0
        /// <summary>
        /// Publish publishes the data argument to the given subject. The data
        /// argument is left untouched and needs to be correctly interpreted on
        /// the receiver.  This API is asynchronous and handles the acknowledgement
        /// or error from the NATS streaming server in the provided handler.  An exception is thrown when
        /// an error occurs during the send, the handler will process acknowledgments and errors.
        /// </summary>
        /// <typeparam name="TMessage">The message type.</typeparam>
        /// <param name="connection">The conmnection.</param>
        /// <param name="subject">Subject to publish the message to.</param>
        /// <param name="data">Message payload.</param>
        /// <param name="handler">Event handler to process message acknowledgements.</param>
        /// <returns>The GUID of the published message.</returns>
        /// <exception cref="StanException">Thrown when an error occurs publishing the message.</exception>
        public static string Publish <TMessage>(this IStanConnection connection, string subject, TMessage data, EventHandler <StanAckHandlerArgs> handler)
            where TMessage : class, IRoundtripData, new()
        {
            Covenant.Requires <ArgumentNullException>(data != null);

            return(connection.Publish(subject, data.ToBytes(), handler));
        }
コード例 #9
0
                internal void ProcessMsgs(string url, string clusterID)
                {
                    IStanConnection sc = null;

                    try
                    {
                        sc = CreateConnection(url, clusterID, "synadia-rel-sub");

                        var opts = StanSubscriptionOptions.GetDefaultOptions();
                        opts.AckWait     = 60000;
                        opts.ManualAcks  = true;
                        opts.MaxInflight = 32;
                        opts.DurableName = "synadia-restest";

                        sc.Subscribe("synadia.restest", "qg", opts, ProcessMsg);

                        FeV.WaitOne();
                    }
                    catch (Exception e)
                    {
                        Log("Create Subscriber failed: " + e);
                    }
                    finally
                    {
                        sc?.Close();
                    }

                    Log("Subscriber is finished.");
                }
コード例 #10
0
        static void TestSTAN(IStanConnection conn)
        {
            Task.Run(async() =>
            {
                var i = 0;
                while (true)
                {
                    try
                    {
                        string guid = conn.Publish("stest", UTF8Encoding.UTF8.GetBytes(i.ToString()), null);

                        await Task.Delay(1000);
                        i++;
                    }
                    catch (Exception err)
                    {
                        Console.WriteLine(err);
                    }
                }
            });

            var sOpts = StanSubscriptionOptions.GetDefaultOptions();

            sOpts.AckWait = 60000;
            var s = conn.Subscribe("stest", sOpts, (obj, msgArs) =>
            {
                Console.WriteLine(UTF8Encoding.UTF8.GetString(msgArs.Message.Data));
            });
        }
コード例 #11
0
                internal void SendMessages(string url, string clusterID)
                {
                    IStanConnection sc = null;

                    sc = CreateConnection(url, clusterID, "synadia-rel-publisher");
                    for (int i = 0; !IsFinished(); i++)
                    {
                        try
                        {
                            sc.Publish("synadia.restest", payload, (obj, args) => { /* NOOP */ });
                            // sync publish for long running stability
                            // sc.Publish("synadia.restest", payload); ;
                        }
                        catch (Exception e)
                        {
                            Log("Publish Exception: " + e.Message);
                            Thread.Sleep(250);
                        }

                        if (i % 500 == 0)
                        {
                            Log("Publisher Sent {0} messages to the streaming server.", i);
                            PrintResourceStats();
                        }
                    }
                    sc?.Close();

                    Log("Publisher is finished.");
                }
コード例 #12
0
 // Convenience method to create a queue or standard subscriber
 private IStanSubscription CreateSubscriber(IStanConnection c, EventHandler <StanMsgHandlerArgs> msgHandler)
 {
     if (qGroup != null)
     {
         return(c.Subscribe(subject, qGroup, sOpts, msgHandler));
     }
     return(c.Subscribe(subject, sOpts, msgHandler));
 }
コード例 #13
0
        private StanObservableSubscription(IStanConnection cn, string subject)
        {
            if (cn == null)
            {
                throw new ArgumentNullException(nameof(cn));
            }

            subscription = cn.Subscribe(subject, OnIncomingMessage);
        }
コード例 #14
0
 /// <summary>
 /// Subscribe will create an Asynchronous Subscriber with
 /// interest in a given subject, assign the handler, and immediately
 /// start receiving messages.
 /// </summary>
 /// <typeparam name="TMessage">The message type.</typeparam>
 /// <param name="connection">The conmnection.</param>
 /// <param name="subject">Subject of interest.</param>
 /// <param name="qgroup">Name of the queue group.</param>
 /// <param name="options">SubscriptionOptions used to create the subscriber.</param>
 /// <param name="handler">A message handler to process messages.</param>
 /// <returns>A new subscription.</returns>
 public static IStanSubscription Subscribe <TMessage>(this IStanConnection connection, string subject, string qgroup, StanSubscriptionOptions options, EventHandler <StanMsgHandlerArgs <TMessage> > handler)
     where TMessage : class, IRoundtripData, new()
 {
     return(connection.Subscribe(subject, qgroup, options,
                                 (sender, args) =>
     {
         handler?.Invoke(sender, args.Message.ToHandler <TMessage>());
     }));
 }
コード例 #15
0
ファイル: QuantObserver.cs プロジェクト: ArseniySavin/Quant
        void InitStanClient()
        {
            var stanConnectionFactory = new StanConnectionFactory();

            _stanClient = stanConnectionFactory.CreateConnection(_options.ClusterId, _options.ClientId, _stanOptions);

            _stanSubscriptionOptions             = StanSubscriptionOptions.GetDefaultOptions();
            _stanSubscriptionOptions.DurableName = _options.StanSubscriptionOptions.DurableName;
        }
コード例 #16
0
        public Test_NatsStreamingFixture(NatsStreamingFixture fixture)
        {
            if (fixture.Start() == TestFixtureStatus.AlreadyRunning)
            {
                fixture.Restart();
            }

            this.fixture    = fixture;
            this.connection = fixture.Connection;
        }
コード例 #17
0
        /// <summary>
        /// This method completely resets the fixture by removing and recreating
        /// the NATS-STREAMING container.
        /// </summary>
        public override void Reset()
        {
            if (Connection != null)
            {
                Connection.Dispose();
                Connection = null;
            }

            base.Reset();
        }
コード例 #18
0
        /// <summary>
        /// Establishes the server connection.
        /// </summary>
        private void Connect()
        {
            var factory = new StanConnectionFactory();
            var retry   = new LinearRetryPolicy(exception => true, 20, TimeSpan.FromSeconds(0.5));

            retry.Invoke(
                () =>
            {
                Connection = factory.CreateConnection("test-cluster", nameof(NatsStreamingFixture));
            });
        }
コード例 #19
0
        public Test_NatsStreamingFixture(NatsStreamingFixture fixture)
        {
            TestHelper.ResetDocker(this.GetType());

            if (fixture.Start() == TestFixtureStatus.AlreadyRunning)
            {
                fixture.Restart();
            }

            this.fixture    = fixture;
            this.connection = fixture.Connection;
        }
コード例 #20
0
        public Program(string[] args)
        {
            var clientId = "";
            var topic    = "sample";

            if (args.Length > 1)
            {
                topic = args[1];
            }
            if (args.Length > 2)
            {
                clientId = args[2];
            }
            var cf      = new StanConnectionFactory();
            var options = StanOptions.GetDefaultOptions();

            options.ConnectTimeout = 1000;
            options.NatsURL        = "nats://*****:*****@localhost:4222";
            IStanConnection connection = cf.CreateConnection("test-cluster", clientId, options);

            if (args.Length > 0 && args[0] == "send")
            {
                while (true)
                {
                    connection.Publish(topic, Encoding.UTF8.GetBytes("Hello NATS " + Guid.NewGuid().ToString()));
                    Console.WriteLine("Message sent to topic: " + topic);
                    Thread.Sleep(500);
                }
            }
            else
            {
                var subName = "subscription-1";
                if (args.Length > 0)
                {
                    subName = args[0];
                }
                EventHandler <StanMsgHandlerArgs> eh = (sender, argsMsg) =>
                {
                    var body = Encoding.UTF8.GetString(argsMsg.Message.Data);
                    // TODO: Handle headers in right way
                    Console.WriteLine(body);
                    Thread.Sleep(1000);
                    argsMsg.Message.Ack();
                };

                var opts = StanSubscriptionOptions.GetDefaultOptions();
                opts.DurableName = subName;
                opts.ManualAcks  = true;
                opts.AckWait     = 60000;
                opts.MaxInflight = 1;
                IStanSubscription subscription = subscription = connection.Subscribe(topic, subName, opts, eh);
            }
        }
コード例 #21
0
 /// <summary>
 /// Initializes a new <see cref="EventChannel"/>
 /// </summary>
 /// <param name="logger">The service used to perform logging</param>
 /// <param name="stanConnection">The underlying NATS Streaming connection</param>
 /// <param name="httpClientFactory">The service used to create new <see cref="System.Net.Http.HttpClient"/> instances</param>
 public EventChannel(ILogger <EventChannel> logger, IStanConnection stanConnection, IHttpClientFactory httpClientFactory)
 {
     this.Logger               = logger;
     this.StanConnection       = stanConnection;
     this.EventFormatter       = new JsonEventFormatter();
     this.HttpClient           = httpClientFactory.CreateClient(typeof(EventChannel).Name);
     this.SubscriptionRegistry = new HashFile();
     this.SubscriptionRegistry.Initialize(Path.Combine(AppContext.BaseDirectory, "sub"), 128, (ushort)JsonConvert.SerializeObject(new SubscriptionOptionsDto()
     {
         Id = StringExtensions.GenerateRandomString(128), Subject = StringExtensions.GenerateRandomString(128), DurableName = StringExtensions.GenerateRandomString(128), StreamPosition = 999999
     }).Length);
     this.Subscriptions = new ConcurrentDictionary <string, IStanSubscription>();
 }
コード例 #22
0
        public void Start()
        {
            _connection = _connectionProvider.GetConnection();
            _cancellationTokenSource = new CancellationTokenSource();

            Task.Run(() =>
            {
                var opts         = StanSubscriptionOptions.GetDefaultOptions();
                opts.DurableName = $"{_config.Value.NatsConnection.ClientId}.Durable";

                _subscription = _connection.Subscribe("PostTechnology.EventBus", opts, MessageReceived);
            }, _cancellationTokenSource.Token);
        }
コード例 #23
0
        IStanConnection getConnection()
        {
            IStanConnection conn = null;

            try
            {
                conn = StanConnectionFactory.CreateConnection(clusterID, clientID, cOpts);
            }
            catch (Exception ex)
            {
                NLog.LogManager.GetCurrentClassLogger().Warn(ex, "Creat nats connection fail!");
            }
            return(conn);
        }
コード例 #24
0
        /// <summary>
        /// Restarts the NATS container to clear any previous state and returns the
        /// new client connection.
        /// </summary>
        /// <returns>The new connection.</returns>
        public new IStanConnection Restart()
        {
            base.Restart();

            if (Connection != null)
            {
                Connection.Dispose();
                Connection = null;
            }

            Connect();

            return(Connection);
        }
コード例 #25
0
        public void Setup(string appname)
        {
            var cf = new StanConnectionFactory();

            _connection = cf.CreateConnection("test-cluster", appname);

            _connection.NATSConnection.Opts.DisconnectedEventHandler += (sender, args) =>
            {
                OnDisconnected?.Invoke(this, new OnDisconnectedHandlerArgs(args.Conn.State));
            };

            _connection.NATSConnection.Opts.ClosedEventHandler += (sender, args) =>
            {
                OnClosed?.Invoke(this, new OnClosedHandlerArgs(args.Conn.State));
            };
        }
コード例 #26
0
        public NATSOrderRepository()
        {
            try
            {
                var cf      = new StanConnectionFactory();
                var options = StanOptions.GetDefaultOptions();
                options.NatsURL = "nats://localhost:4223";
                _stanConnection = cf.CreateConnection("test-cluster", CLIENTID, options);
                var subOptions = StanSubscriptionOptions.GetDefaultOptions();
                subOptions.DeliverAllAvailable();
                _stanConnection.Subscribe(EVENTSTREAM_SUBJECT, subOptions, (obj, args) =>
                {
                    try
                    {
                        string message        = Encoding.UTF8.GetString(args.Message.Data);
                        string[] messageParts = message.Split('#');

                        string eventTypeDescriptor =
                            $"Store.OrderProcessingService.Domain.Events.{messageParts[0]}";
                        Type eventType   = Type.GetType(eventTypeDescriptor);
                        string eventData = message.Substring(message.IndexOf('#') + 1);
                        dynamic e        = JsonSerializer.Deserialize(eventData, eventType);
                        if (_eventStreams.ContainsKey(e.OrderNumber))
                        {
                            _eventStreams[e.OrderNumber].Add(e);
                        }
                        else
                        {
                            _eventStreams.Add(e.OrderNumber, new List <BusinessEvent>()
                            {
                                e
                            });

                            Console.WriteLine($"Order #{e.OrderNumber} found during replay.");
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Error: {ex.Message}");
                    }
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }
コード例 #27
0
        public NatsTarget(string natsUrl, string natsClusterId, string natsClientId, int natsConnectionTimeout = 10000, int natsPubAckWait = 5000)
        {
            cache                      = new ConcurrentDictionary <string, IpObj>();
            this.NatsUrl               = natsUrl;
            this.NatsClusterId         = natsClusterId;
            this.NatsClientId          = natsClientId;
            this.NatsConnectionTimeout = natsConnectionTimeout;
            this.NatsPubAckWait        = natsPubAckWait;

            opts.NatsURL = this.NatsUrl;
            opts.ConnectionLostEventHandler = (obj, args) =>
            {
                InternalLogger.Error($"NATS connection lost. {args.ConnectionException}");
            };

            stanConnection = Connect(this.NatsClusterId, this.NatsClientId, opts);
        }
コード例 #28
0
        public StanMessageSenderService(
            IConfiguration configuration,
            ILogger <StanMessageSenderService> logger)
        {
            _configuration = configuration;
            _logger        = logger;

            cOpts.NatsURL = _configuration.GetValue <string>("Messaging:Stan:Servers");
            string clusterID = _configuration.GetValue <string>("Messaging:Stan:ClusterId");

            //if testing for local loop send error, 'coz clientID already used when listen
            string clientID = _configuration.GetValue <string>("Messaging:Group");

            // string clientID = "TEST";

            _connection = new StanConnectionFactory().CreateConnection(clusterID, clientID, cOpts);
        }
コード例 #29
0
        private static IStanConnection Connect(string clusterId, string clientId, StanOptions opts = null)
        {
            int connectionRetryCounter = 0;
            int connectionRetryMax     = 3;

            while (connectionRetryMax > 0 && stanConnection == null)
            {
                try
                {
                    if (stanConnection == null || stanConnection.NATSConnection == null)
                    {
                        if (opts == null)
                        {
                            stanConnection = new StanConnectionFactory().CreateConnection(clusterId, clientId);
                        }
                        else
                        {
                            stanConnection = new StanConnectionFactory().CreateConnection(clusterId, clientId, opts);
                        }
                    }
                }
                catch (STAN.Client.StanConnectionException ex)
                {
                    connectionRetryMax--;
                    Console.WriteLine($"NATS connection exception. {ex}");
                    Thread.Sleep(1000 * connectionRetryCounter);
                }
                catch (STAN.Client.StanConnectRequestTimeoutException ex)
                {
                    connectionRetryMax--;
                    Console.WriteLine($"NATS connection request timeout exception. {ex}");
                    Thread.Sleep(1000 * connectionRetryCounter);
                }
                catch (STAN.Client.StanConnectRequestException ex)
                {
                    connectionRetryMax--;
                    Console.WriteLine($"NATS connection request exception. {ex}");
                    Thread.Sleep(1000 * connectionRetryCounter);
                }

                connectionRetryCounter++;
            }

            return(stanConnection);
        }
コード例 #30
0
        public void Start()
        {
            _repo = new SQLServerOrderRepository();

            // connect to NATS
            var natsConnectionFactory = new ConnectionFactory();

            _natsConnection = natsConnectionFactory.CreateConnection("nats://localhost:4222");

            // connect to STAN
            var cf      = new StanConnectionFactory();
            var options = StanOptions.GetDefaultOptions();

            options.NatsURL = "nats://localhost:4223";
            _stanConnection = cf.CreateConnection("test-cluster", "OrderProcessingService", options);

            // create commands subscription
            _commandsSubscription = _natsConnection.SubscribeAsync("store.commands.*", CommandReceived);
        }