예제 #1
0
        public async Task OneTimeSetUp()
        {
            _eventIdProvider = new InMemoryEventIdProvider();
            _serializer      = new JsonNetSerializer();
            _eventSerializer = new EventSerializer(_serializer);
            _eventCache      = new InMemoryEventCache(_eventIdProvider, _eventSerializer);

            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOfTheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            _broker = new BrokerageService(brokerConfiguration, LoggerForTests <BrokerageService> .Default(), _eventCache, _serializer);

            await _broker.Run();

            JsonConvert.DefaultSettings = () =>
            {
                var settings = new JsonSerializerSettings
                {
                    Formatting       = Formatting.Indented,
                    TypeNameHandling = TypeNameHandling.Objects,
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                };

                return(settings);
            };

            await Task.Delay(1000);
        }
예제 #2
0
        public async Task ShouldCheckMinimumPerformance()
        {
            var eventIdProvider = new InMemoryEventIdProvider();
            var serializer      = new JsonNetSerializer();
            var eventSerializer = new EventSerializer(serializer);

            var eventCache = new InMemoryEventCache(eventIdProvider, eventSerializer);

            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOftheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = new BrokerageService(brokerConfiguration, eventCache, serializer);

            var marketConfiguration = new ProducerConfiguration()
            {
                RouterEndpoint   = ToPublishersEndpoint,
                HearbeatEndpoint = HeartbeatEndpoint
            };

            var market = new Market("FxConnect", marketConfiguration, eventSerializer, TimeSpan.FromMilliseconds(10));

            await router.Run();

            await market.Run();

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject          = string.Empty,
                HeartbeatDelay   = TimeSpan.FromSeconds(10),
                HeartbeatTimeout = TimeSpan.FromSeconds(2)
            };

            var cache = new DynamicCache <string, CurrencyPair>(cacheConfiguration, eventSerializer);

            await cache.Run();

            //fire a little less than 300 events
            await Task.Delay(3000);

            await Task.WhenAll(new[] { router.Destroy(), market.Destroy(), cache.Destroy() });

            var cacheItems       = cache.GetItems().ToList();
            var cacheItemsEvents = cacheItems.SelectMany(items => items.AppliedEvents).ToList();

            //At least 3/4 events should be processed
            Assert.Greater((double)cacheItemsEvents.Count / (double)market.Prices.Count, 0.75);
        }
예제 #3
0
        public static DynamicCacheServiceBuilder <TKey, TAggregate> AddBroker <TKey, TAggregate>(this DynamicCacheServiceBuilder <TKey, TAggregate> builder, Action <IBrokerageServiceConfiguration> brokerConfigurationBuilder)
            where TAggregate : class, IAggregate <TKey>, new()
        {
            var configuration = new BrokerageServiceConfiguration();

            brokerConfigurationBuilder(configuration);

            builder.Options.ServiceCollection.AddSingleton <IBrokerageServiceConfiguration>(configuration);

            builder.Options.ServiceCollection.AddSingleton <IBrokerageService, BrokerageService>();

            return(builder);
        }
        public async Task ShouldCheckMinimumPerformance()
        {
            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOfTheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = GetBrokerageService(brokerConfiguration);

            var marketConfiguration = new MarketConfiguration("FxConnect")
            {
                BrokerEndpoint       = ToPublishersEndpoint,
                HeartbeatEndpoint    = HeartbeatEndpoint,
                PriceGenerationDelay = TimeSpan.FromMilliseconds(20)
            };

            var market = GetMarket(marketConfiguration);

            await router.Run();

            await market.Run();

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject          = string.Empty,
                HeartbeatDelay   = TimeSpan.FromMilliseconds(500),
                HeartbeatTimeout = TimeSpan.FromSeconds(1)
            };

            var cache = GetCache(cacheConfiguration);

            await cache.Run();

            await WaitForCachesToCaughtUp(cache);

            await Task.Delay(2000);

            var cacheItemsEvents = cache.Items
                                   .SelectMany(items => items.AppliedEvents)
                                   .ToList();


            //when run as standalone test, we should expect 100%
            //when run in a test batch, the result is less deterministic, thus we lower to 70%
            Assert.Greater((double)cacheItemsEvents.Count / (double)market.Prices.Count, 0.70);
        }
        public async Task ShouldSubscribeToSubject()
        {
            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOfTheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = GetBrokerageService(brokerConfiguration);

            var marketConfigurationFxConnect = new MarketConfiguration("FxConnect")
            {
                BrokerEndpoint       = ToPublishersEndpoint,
                HeartbeatEndpoint    = HeartbeatEndpoint,
                PriceGenerationDelay = TimeSpan.FromMilliseconds(500)
            };

            var marketConfigurationHarmony = new MarketConfiguration("Harmony")
            {
                BrokerEndpoint       = ToPublishersEndpoint,
                HeartbeatEndpoint    = HeartbeatEndpoint,
                PriceGenerationDelay = TimeSpan.FromMilliseconds(500)
            };

            var market1 = GetMarket(marketConfigurationFxConnect);
            var market2 = GetMarket(marketConfigurationHarmony);

            var cacheConfigurationEuroDol = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject = "EUR/USD"
            };

            var cacheConfigurationEuroDolFxConnect = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject = "EUR/USD.FxConnect"
            };

            var cacheEuroDol          = GetCache(cacheConfigurationEuroDol);
            var cacheEuroDolFxConnect = GetCache(cacheConfigurationEuroDolFxConnect);

            await router.Run();

            await Task.Delay(1000);

            await market1.Run();

            await market2.Run();

            await Task.Delay(2000);

            await cacheEuroDol.Run();

            await cacheEuroDolFxConnect.Run();

            await WaitForCachesToCaughtUp(cacheEuroDol, cacheEuroDolFxConnect);

            var routerEventCacheItems = (await _eventCache.GetStreamBySubject(string.Empty)).ToList();

            Assert.Greater(routerEventCacheItems.Count(), 0);

            var ccyPairsCacheEuroDol = cacheEuroDol.Items
                                       .SelectMany(item => item.AppliedEvents)
                                       .Select(item => item.Subject)
                                       .Distinct()
                                       .ToList();

            var ccyPairsCacheEuroDolFxConnect = cacheEuroDolFxConnect.Items
                                                .SelectMany(item => item.AppliedEvents)
                                                .Select(item => item.Subject)
                                                .Distinct()
                                                .ToList();

            while (market1.Prices.GroupBy(p => p.EventStreamId).Count() != 2)
            {
                await Task.Delay(500);
            }

            // EUR/USD.FxConnect & EUR/USD.Harmony
            Assert.AreEqual(2, ccyPairsCacheEuroDol.Count());
            Assert.IsTrue(ccyPairsCacheEuroDol.All(subject => subject.EndsWith("FxConnect") || subject.EndsWith("Harmony")));
            Assert.IsTrue(ccyPairsCacheEuroDol.All(subject => subject.StartsWith(cacheConfigurationEuroDol.Subject)));

            var cacheEvents = cacheEuroDol.Items
                              .SelectMany(item => item.AppliedEvents)
                              .Cast <IEvent <string, CurrencyPair> >()
                              .GroupBy(ev => ev.EventStreamId)
                              .ToList();

            foreach (var grp in cacheEvents)
            {
                var index = 0;

                foreach (var ev in grp)
                {
                    Assert.AreEqual(index++, ev.Version);
                }
            }

            // EUR/USD.FxConnect
            Assert.AreEqual(1, ccyPairsCacheEuroDolFxConnect.Count());
            Assert.AreEqual(cacheConfigurationEuroDolFxConnect.Subject, ccyPairsCacheEuroDolFxConnect.First());
        }
        public async Task ShouldRetrievedEventsSequentially()
        {
            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOfTheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var marketConfigurationFxConnect = new MarketConfiguration("FxConnect")
            {
                BrokerEndpoint    = ToPublishersEndpoint,
                HeartbeatEndpoint = HeartbeatEndpoint
            };

            var marketConfigurationHarmony = new MarketConfiguration("Harmony")
            {
                BrokerEndpoint    = ToPublishersEndpoint,
                HeartbeatEndpoint = HeartbeatEndpoint
            };

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject          = string.Empty,
                HeartbeatDelay   = TimeSpan.FromSeconds(10),
                HeartbeatTimeout = TimeSpan.FromSeconds(2)
            };

            var router = GetBrokerageService(brokerConfiguration);

            var market1 = GetMarket(marketConfigurationFxConnect);
            var market2 = GetMarket(marketConfigurationHarmony);

            var cache      = GetCache(cacheConfiguration);
            var cacheProof = GetCache(cacheConfiguration);

            await router.Run();

            await market1.Run();

            await market2.Run();

            await cache.Run();

            await cacheProof.Run();

            await WaitForCachesToCaughtUp(cache, cacheProof);

            var cacheEvents = cache.Items
                              .SelectMany(item => item.AppliedEvents)
                              .Cast <IEvent <string, CurrencyPair> >()
                              .GroupBy(ev => ev.EventStreamId)
                              .ToList();

            foreach (var grp in cacheEvents)
            {
                var index = 0;

                foreach (var ev in grp)
                {
                    Assert.AreEqual(index++, ev.Version);
                }
            }


            var cacheProofEvents = cache.Items
                                   .SelectMany(item => item.AppliedEvents)
                                   .Cast <IEvent <string, CurrencyPair> >()
                                   .GroupBy(ev => ev.EventStreamId)
                                   .ToList();

            foreach (var grp in cacheProofEvents)
            {
                var index = 0;

                foreach (var ev in grp)
                {
                    Assert.AreEqual(index++, ev.Version);
                }
            }
        }
예제 #7
0
        public async Task ShouldCheckMaxPerformance()
        {
            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOfTheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = GetBrokerageService(brokerConfiguration);

            var marketConfigurationFxConnect = new MarketConfiguration("FxConnect")
            {
                BrokerEndpoint       = ToPublishersEndpoint,
                HeartbeatEndpoint    = HeartbeatEndpoint,
                HeartbeatDelay       = TimeSpan.FromSeconds(1),
                HeartbeatTimeout     = TimeSpan.FromSeconds(1),
                PriceGenerationDelay = TimeSpan.FromMilliseconds(50)
            };

            var marketConfigurationHarmony = new MarketConfiguration("Harmony")
            {
                BrokerEndpoint       = ToPublishersEndpoint,
                HeartbeatEndpoint    = HeartbeatEndpoint,
                HeartbeatDelay       = TimeSpan.FromSeconds(1),
                HeartbeatTimeout     = TimeSpan.FromSeconds(1),
                PriceGenerationDelay = TimeSpan.FromMilliseconds(50)
            };

            var market1 = GetMarket(marketConfigurationFxConnect);
            var market2 = GetMarket(marketConfigurationHarmony);

            await router.Run();

            await Task.Delay(1000);

            await market1.Run();

            await market2.Run();

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject          = string.Empty,
                HeartbeatDelay   = TimeSpan.FromSeconds(1),
                HeartbeatTimeout = TimeSpan.FromSeconds(1)
            };

            var cache = GetCache(cacheConfiguration);

            await cache.Run();

            await WaitForCachesToCaughtUp(cache);

            var cacheEvents = cache.Items
                              .SelectMany(item => item.AppliedEvents)
                              .Cast <IEvent <string, CurrencyPair> >()
                              .GroupBy(ev => ev.EventStreamId)
                              .ToList();


            Assert.Greater(cacheEvents.Count, 0);

            Assert.IsTrue(cacheEvents.All(c => c.Count() > 0));

            foreach (var grp in cacheEvents)
            {
                var index = 0;

                foreach (var ev in grp)
                {
                    Assert.AreEqual(index++, ev.Version);
                }
            }
        }
        public async Task ShouldSubscribeToEventFeed()
        {
            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOfTheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = GetBrokerageService(brokerConfiguration);

            var marketConfigurationFxConnect = new MarketConfiguration("FxConnect")
            {
                BrokerEndpoint    = ToPublishersEndpoint,
                HeartbeatEndpoint = HeartbeatEndpoint,
                HeartbeatDelay    = TimeSpan.FromSeconds(1),
                HeartbeatTimeout  = TimeSpan.FromSeconds(1)
            };

            var marketConfigurationHarmony = new MarketConfiguration("Harmony")
            {
                BrokerEndpoint    = ToPublishersEndpoint,
                HeartbeatEndpoint = HeartbeatEndpoint,
                HeartbeatDelay    = TimeSpan.FromSeconds(1),
                HeartbeatTimeout  = TimeSpan.FromSeconds(1)
            };

            var market1 = GetMarket(marketConfigurationFxConnect);
            var market2 = GetMarket(marketConfigurationHarmony);

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                HeartbeatDelay   = TimeSpan.FromSeconds(1),
                HeartbeatTimeout = TimeSpan.FromSeconds(1)
            };

            var cache = GetCache(cacheConfiguration);

            await router.Run();

            await market1.Run();

            await market2.Run();

            //create an event cache
            await Task.Delay(2000);

            var routerEventCacheItems = await _eventCache.GetStreamBySubject(string.Empty);

            Assert.Greater(routerEventCacheItems.Count(), 0);

            var counter = 0;

            var cleanup = cache.OnItemChanged
                          .Connect()
                          .Subscribe(changes =>
            {
                counter += changes.Count;
            });

            await cache.Run();

            await WaitForCachesToCaughtUp(cache);

            var eventCacheItems = cache.Items.SelectMany(item => item.AppliedEvents).ToList();

            Assert.AreEqual(eventCacheItems.Count(), counter);

            var markets = cache.Items
                          .SelectMany(item => item.AppliedEvents)
                          .Cast <ChangeCcyPairPrice>()
                          .Select(ev => ev.Market)
                          .Distinct();

            //fxconnext & harmony
            Assert.AreEqual(2, markets.Count());

            cleanup.Dispose();
        }
예제 #9
0
        public async Task ShouldConnectAndDisconnectFromBroker()
        {
            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOfTheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var marketConfiguration = new MarketConfiguration("FxConnect")
            {
                BrokerEndpoint    = ToPublishersEndpoint,
                HeartbeatEndpoint = HeartbeatEndpoint,
                HeartbeatDelay    = TimeSpan.FromMilliseconds(500),
                HeartbeatTimeout  = TimeSpan.FromSeconds(1)
            };

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject          = string.Empty,
                HeartbeatDelay   = TimeSpan.FromMilliseconds(500),
                HeartbeatTimeout = TimeSpan.FromSeconds(1)
            };

            var router = GetBrokerageService(brokerConfiguration);
            var market = GetMarket(marketConfiguration);
            var cache  = GetCache(cacheConfiguration);

            var cacheStates = new List <DynamicCacheState>();

            var stateObservable = cache.OnStateChanged
                                  .Subscribe(state =>
            {
                cacheStates.Add(state);
            });


            await market.Run();

            await cache.Run();

            Assert.AreEqual(ProducerState.NotConnected, market.ProducerState);
            Assert.AreEqual(DynamicCacheState.NotConnected, cache.CacheState);

            await router.Run();

            await Task.Delay(1000);

            await WaitForCachesToCaughtUp(cache);

            Assert.AreEqual(DynamicCacheState.Connected, cache.CacheState);
            Assert.AreEqual(ProducerState.Connected, market.ProducerState);

            await router.Destroy();

            await Task.Delay(2000);

            Assert.AreEqual(DynamicCacheState.Disconnected, cache.CacheState);
            Assert.AreEqual(ProducerState.Disconnected, market.ProducerState);

            router = GetBrokerageService(brokerConfiguration);

            await router.Run();

            await WaitForCachesToCaughtUp(cache);

            await Task.Delay(2000);

            Assert.AreEqual(5, cacheStates.Count);
            Assert.AreEqual(DynamicCacheState.NotConnected, cacheStates.ElementAt(0));
            Assert.AreEqual(DynamicCacheState.Connected, cacheStates.ElementAt(1));
            Assert.AreEqual(DynamicCacheState.Disconnected, cacheStates.ElementAt(2));
            Assert.AreEqual(DynamicCacheState.Reconnected, cacheStates.ElementAt(3));
            Assert.AreEqual(DynamicCacheState.Connected, cacheStates.ElementAt(4));

            Assert.AreEqual(DynamicCacheState.Connected, cache.CacheState);
            Assert.AreEqual(ProducerState.Connected, market.ProducerState);

            stateObservable.Dispose();
        }
예제 #10
0
        public void SetUp()
        {
            _eventIdProvider = new InMemoryEventIdProvider();
            _serializer      = new JsonNetSerializer();
            _eventSerializer = new EventSerializer(_serializer);
            _eventCache      = new InMemoryEventCache(_eventIdProvider, _eventSerializer);

            JsonConvert.DefaultSettings = () =>
            {
                var settings = new JsonSerializerSettings
                {
                    Formatting       = Formatting.Indented,
                    TypeNameHandling = TypeNameHandling.Objects,
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                };

                return(settings);
            };

            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOfTheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = GetBrokerageService(brokerConfiguration);

            var marketConfigurationFxConnect = new MarketConfiguration("FxConnect")
            {
                IsAutoGen         = false,
                BrokerEndpoint    = ToPublishersEndpoint,
                HeartbeatEndpoint = HeartbeatEndpoint,
                HeartbeatDelay    = TimeSpan.FromSeconds(5),
                HeartbeatTimeout  = TimeSpan.FromSeconds(5)
            };

            _market1 = GetMarket(marketConfigurationFxConnect);

            router.Run().Wait();

            Task.Delay(1000).Wait();

            _market1.Run().Wait();

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject          = string.Empty,
                HeartbeatDelay   = TimeSpan.FromSeconds(5),
                HeartbeatTimeout = TimeSpan.FromSeconds(5),
                ZmqHighWatermark = 1000,
                UseEventBatching = UseEventBatch,
                DoStoreEvents    = false
            };

            _cache = GetCache(cacheConfiguration);

            _cache.Run().Wait();

            WaitForCachesToCaughtUp(_cache).Wait();
        }
예제 #11
0
        public async Task ShouldHandleDisconnectAndCacheRebuild()
        {
            var eventIdProvider = new InMemoryEventIdProvider();
            var serializer      = new JsonNetSerializer();
            var eventSerializer = new EventSerializer(serializer);

            var eventCache = new InMemoryEventCache(eventIdProvider, eventSerializer);

            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOftheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = new BrokerageService(brokerConfiguration, eventCache, serializer);

            var marketConfiguration = new ProducerConfiguration()
            {
                RouterEndpoint   = ToPublishersEndpoint,
                HearbeatEndpoint = HeartbeatEndpoint
            };

            var market1 = new Market("FxConnect", marketConfiguration, eventSerializer, TimeSpan.FromMilliseconds(100));
            var market2 = new Market("Harmony", marketConfiguration, eventSerializer, TimeSpan.FromMilliseconds(100));

            await router.Run();


            await Task.Delay(1000);

            await market1.Run();

            await market2.Run();

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject          = string.Empty,
                HeartbeatDelay   = TimeSpan.FromMilliseconds(500),
                HeartbeatTimeout = TimeSpan.FromSeconds(1)
            };

            var cache      = new DynamicCache <string, CurrencyPair>(cacheConfiguration, eventSerializer);
            var cacheProof = new DynamicCache <string, CurrencyPair>(cacheConfiguration, eventSerializer);

            await cacheProof.Run();

            await cache.Run();

            Assert.AreEqual(DynamicCacheState.NotConnected, cache.CacheState);
            Assert.AreEqual(DynamicCacheState.NotConnected, cacheProof.CacheState);

            await Task.Delay(2000);

            Assert.AreEqual(DynamicCacheState.Connected, cache.CacheState);
            Assert.AreEqual(DynamicCacheState.Connected, cacheProof.CacheState);

            await Task.Delay(3000);

            Assert.AreEqual(cache.GetItems()
                            .SelectMany(item => item.AppliedEvents)
                            .Count(),
                            cacheProof.GetItems()
                            .SelectMany(item => item.AppliedEvents)
                            .Count());

            await router.Destroy();

            await Task.Delay(cacheConfiguration.HeartbeatDelay);

            Assert.AreEqual(DynamicCacheState.Disconnected, cache.CacheState);
            Assert.AreEqual(DynamicCacheState.Disconnected, cacheProof.CacheState);

            router = new BrokerageService(brokerConfiguration, eventCache, serializer);

            await router.Run();

            await Task.Delay(TimeSpan.FromSeconds(3));

            Assert.AreEqual(DynamicCacheState.Connected, cache.CacheState);
            Assert.AreEqual(DynamicCacheState.Connected, cacheProof.CacheState);

            await router.Destroy();

            var cacheCCyPair      = cache.GetItems().ToList();
            var cacheProofCcyPair = cacheProof.GetItems().ToList();

            Assert.AreEqual(cacheCCyPair.Count(), cacheProofCcyPair.Count());
            Assert.AreEqual(cacheCCyPair.Count(), cacheProofCcyPair.Count());

            foreach (var ccyPair in cacheCCyPair)
            {
                var proof = cacheProofCcyPair.First(ccy => ccy.Id == ccyPair.Id);

                Assert.AreEqual(ccyPair.Ask, proof.Ask);
                Assert.AreEqual(ccyPair.Bid, proof.Bid);
                Assert.AreEqual(ccyPair.Mid, proof.Mid);
                Assert.AreEqual(ccyPair.Spread, proof.Spread);
            }

            var brokerCacheEvents = (await eventCache.GetStreamBySubject(cacheConfiguration.Subject)).ToList();
            var cacheEvents       = cacheCCyPair.SelectMany(item => item.AppliedEvents).ToList();
            var cacheProofEvents  = cacheProofCcyPair.SelectMany(item => item.AppliedEvents).ToList();


            Assert.AreEqual(cacheEvents.Count(), cacheProofEvents.Count());
            Assert.AreEqual(cacheEvents.Count(), cacheProofEvents.Count());
            Assert.AreEqual(cacheEvents.Count(), cacheProofEvents.Count());

            await Task.WhenAll(new[] { market1.Destroy(), market2.Destroy(), cache.Destroy() });
        }
예제 #12
0
        public async Task ShouldSubscribeToEventFeed()
        {
            var eventIdProvider = new InMemoryEventIdProvider();
            var serializer      = new JsonNetSerializer();
            var eventSerializer = new EventSerializer(serializer);
            var eventCache      = new InMemoryEventCache(eventIdProvider, eventSerializer);

            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOftheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = new BrokerageService(brokerConfiguration, eventCache, serializer);

            var marketConfiguration = new ProducerConfiguration()
            {
                RouterEndpoint   = ToPublishersEndpoint,
                HearbeatEndpoint = HeartbeatEndpoint
            };

            var market1 = new Market("FxConnect", marketConfiguration, eventSerializer, TimeSpan.FromMilliseconds(750));
            var market2 = new Market("Harmony", marketConfiguration, eventSerializer, TimeSpan.FromMilliseconds(750));

            await router.Run();

            await market1.Run();

            await market2.Run();

            //create an event cache
            await Task.Delay(2000);

            //Assert.Greater(router.Cache.Count(), 0);

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint);

            var cache = new DynamicCache <string, CurrencyPair>(cacheConfiguration, eventSerializer);

            var counter = 0;

            var cleanup = cache.OnItemChanged()
                          .Connect()
                          .Subscribe(_ =>
            {
                counter++;
            });

            await cache.Run();

            await Task.Delay(2000);

            // Assert.AreEqual(router.Cache.Count(), counter);
            Assert.AreEqual(cache.GetItems().SelectMany(item => item.AppliedEvents).Count(), counter);

            //fxconnext & harmony
            Assert.AreEqual(2, cache.GetItems()
                            .SelectMany(item => item.AppliedEvents)
                            .Cast <ChangeCcyPairPrice>()
                            .Select(ev => ev.Market)
                            .Distinct()
                            .Count());


            cleanup.Dispose();

            await Task.WhenAll(new[] { router.Destroy(), market1.Destroy(), market2.Destroy(), cache.Destroy() });
        }
예제 #13
0
        public async Task ShouldSubscribeToSubject()
        {
            //todo .NET COre MVC implem
            var eventIdProvider = new InMemoryEventIdProvider();
            var serializer      = new JsonNetSerializer();
            var eventSerializer = new EventSerializer(serializer);

            var eventCache = new InMemoryEventCache(eventIdProvider, eventSerializer);

            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOftheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = new BrokerageService(brokerConfiguration, eventCache, serializer);

            var marketConfiguration = new ProducerConfiguration()
            {
                RouterEndpoint   = ToPublishersEndpoint,
                HearbeatEndpoint = HeartbeatEndpoint
            };

            var market1 = new Market("FxConnect", marketConfiguration, eventSerializer, TimeSpan.FromMilliseconds(750));
            var market2 = new Market("Harmony", marketConfiguration, eventSerializer, TimeSpan.FromMilliseconds(750));

            await router.Run();

            await market1.Run();

            await market2.Run();


            var cacheConfigurationEuroDol = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject = "EUR/USD"
            };

            var cacheConfigurationEuroDolFxConnect = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject = "EUR/USD.FxConnect"
            };

            var cacheEuroDol          = new DynamicCache <string, CurrencyPair>(cacheConfigurationEuroDol, eventSerializer);
            var cacheEuroDolFxConnect = new DynamicCache <string, CurrencyPair>(cacheConfigurationEuroDolFxConnect, eventSerializer);

            await cacheEuroDol.Run();

            await cacheEuroDolFxConnect.Run();

            //wait for a substential event stream
            await Task.Delay(5000);

            // Assert.Greater(router.Cache.Count(), 1);

            var ccyPairsCacheEuroDol = cacheEuroDol.GetItems()
                                       .SelectMany(item => item.AppliedEvents)
                                       .Select(item => item.Subject)
                                       .Distinct();

            // EUR/USD.FxConnect & EUR/USD.Harmony
            Assert.AreEqual(2, ccyPairsCacheEuroDol.Count());
            Assert.IsTrue(ccyPairsCacheEuroDol.All(subject => subject.EndsWith("FxConnect") || subject.EndsWith("Harmony")));
            Assert.IsTrue(ccyPairsCacheEuroDol.All(subject => subject.StartsWith(cacheConfigurationEuroDol.Subject)));

            var ccyPairsCacheEuroDolFxConnect = cacheEuroDolFxConnect.GetItems()
                                                .SelectMany(item => item.AppliedEvents)
                                                .Select(item => item.Subject)
                                                .Distinct();

            // EUR/USD.FxConnect
            Assert.AreEqual(1, ccyPairsCacheEuroDolFxConnect.Count());
            Assert.AreEqual(cacheConfigurationEuroDolFxConnect.Subject, ccyPairsCacheEuroDolFxConnect.First());


            await Task.WhenAll(new[] { router.Destroy(), market1.Destroy(), market2.Destroy(), cacheEuroDol.Destroy(), cacheEuroDolFxConnect.Destroy() });
        }
예제 #14
0
        public async Task ShouldHandleDisconnectAndCacheRebuild()
        {
            var brokerConfiguration = new BrokerageServiceConfiguration()
            {
                HeartbeatEndpoint       = HeartbeatEndpoint,
                StateOfTheWorldEndpoint = StateOfTheWorldEndpoint,
                ToSubscribersEndpoint   = ToSubscribersEndpoint,
                ToPublisherEndpoint     = ToPublishersEndpoint
            };

            var router = GetBrokerageService(brokerConfiguration);

            var marketConfiguration = new MarketConfiguration("FxConnect")
            {
                BrokerEndpoint    = ToPublishersEndpoint,
                HeartbeatEndpoint = HeartbeatEndpoint,
                HeartbeatDelay    = TimeSpan.FromSeconds(1),
                HeartbeatTimeout  = TimeSpan.FromSeconds(1),
                IsAutoGen         = false
            };

            var market1 = GetMarket(marketConfiguration);

            var cacheConfiguration = new DynamicCacheConfiguration(ToSubscribersEndpoint, StateOfTheWorldEndpoint, HeartbeatEndpoint)
            {
                Subject          = string.Empty,
                HeartbeatDelay   = TimeSpan.FromSeconds(1),
                HeartbeatTimeout = TimeSpan.FromSeconds(1)
            };

            var cache      = GetCache(cacheConfiguration);
            var cacheProof = GetCache(cacheConfiguration);

            var cacheStates = new List <DynamicCacheState>();

            var stateObservable = cache.OnStateChanged
                                  .Subscribe(state =>
            {
                cacheStates.Add(state);
            });


            await router.Run();

            await market1.Run();

            await cache.Run();

            await cacheProof.Run();

            Assert.AreEqual(DynamicCacheState.NotConnected, cache.CacheState);
            Assert.AreEqual(DynamicCacheState.NotConnected, cacheProof.CacheState);

            await Task.Delay(1000);

            await market1.WaitUntilConnected();

            Assert.AreEqual(ProducerState.Connected, market1.ProducerState);

            market1.PublishNext();
            market1.PublishNext();
            market1.PublishNext();

            await WaitForCachesToCaughtUp(cache, cacheProof);

            Assert.AreEqual(DynamicCacheState.Connected, cache.CacheState);
            Assert.AreEqual(DynamicCacheState.Connected, cacheProof.CacheState);

            var cacheEvents      = cache.Items.SelectMany(item => item.AppliedEvents).ToList();
            var cacheProofEvents = cacheProof.Items.SelectMany(item => item.AppliedEvents).ToList();

            Assert.AreEqual(cacheEvents.Count(), cacheProofEvents.Count());

            await router.Destroy();

            await Task.Delay(2000);

            Assert.AreEqual(DynamicCacheState.Disconnected, cache.CacheState);
            Assert.AreEqual(DynamicCacheState.Disconnected, cacheProof.CacheState);

            router = GetBrokerageService(brokerConfiguration);

            await router.Run();

            await Task.Delay(1000);

            market1.PublishNext();
            market1.PublishNext();
            market1.PublishNext();

            await WaitForCachesToCaughtUp(cache, cacheProof);

            var cacheCCyPair      = cache.Items.ToList();
            var cacheProofCcyPair = cacheProof.Items.ToList();

            Assert.AreEqual(cacheCCyPair.Count(), cacheProofCcyPair.Count());
            Assert.AreEqual(cacheCCyPair.Count(), cacheProofCcyPair.Count());

            foreach (var ccyPair in cacheCCyPair)
            {
                var proof = cacheProofCcyPair.First(ccy => ccy.Id == ccyPair.Id);

                Assert.AreEqual(ccyPair.Ask, proof.Ask);
                Assert.AreEqual(ccyPair.Bid, proof.Bid);
                Assert.AreEqual(ccyPair.Mid, proof.Mid);
                Assert.AreEqual(ccyPair.Spread, proof.Spread);
            }

            cacheEvents      = cacheCCyPair.SelectMany(item => item.AppliedEvents).ToList();
            cacheProofEvents = cacheProofCcyPair.SelectMany(item => item.AppliedEvents).ToList();

            Assert.AreEqual(cacheEvents.Count(), cacheProofEvents.Count());
            Assert.AreEqual(cacheEvents.Count(), cacheProofEvents.Count());
            Assert.AreEqual(cacheEvents.Count(), cacheProofEvents.Count());

            await Task.Delay(1000);

            Assert.AreEqual(5, cacheStates.Count);
            Assert.AreEqual(DynamicCacheState.NotConnected, cacheStates.ElementAt(0));
            Assert.AreEqual(DynamicCacheState.Connected, cacheStates.ElementAt(1));
            Assert.AreEqual(DynamicCacheState.Disconnected, cacheStates.ElementAt(2));
            Assert.AreEqual(DynamicCacheState.Reconnected, cacheStates.ElementAt(3));
            Assert.AreEqual(DynamicCacheState.Connected, cacheStates.ElementAt(4));

            stateObservable.Dispose();
        }