public void TestAddSusbcribtionNew()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var handler = pinkoContainer.Resolve<RoleUserSubscriptionHandler>().Register();
            var expression = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            expression.MsgAction = PinkoMessageAction.UserSubscription;  // Set to subscription
            var envelop = new PinkoServiceMessageEnvelop() { Message = expression, ReplyTo = "UniteTestReplyQueue" };

            // process request
            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, expression);

            Assert.IsTrue(handler.ClientSubscriptions.Count() == 1);

            // Make sure they have the same content
            var chekExp = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            Assert.IsFalse(string.IsNullOrEmpty(handler.ClientSubscriptions[chekExp.DataFeedIdentifier.SubscribtionId].CalcExpression.DataFeedIdentifier.SubscribtionId));
            Assert.IsFalse(string.IsNullOrEmpty(handler.ClientSubscriptions[chekExp.DataFeedIdentifier.SubscribtionId].CalcExpression.DataFeedIdentifier.SignalRId));
            Assert.IsFalse(string.IsNullOrEmpty(handler.ClientSubscriptions[chekExp.DataFeedIdentifier.SubscribtionId].CalcExpression.DataFeedIdentifier.MaketEnvId));
            Assert.IsFalse(string.IsNullOrEmpty(handler.ClientSubscriptions[chekExp.DataFeedIdentifier.SubscribtionId].CalcExpression.DataFeedIdentifier.ClientId));
            Assert.IsFalse(string.IsNullOrEmpty(handler.ClientSubscriptions[chekExp.DataFeedIdentifier.SubscribtionId].CalcExpression.DataFeedIdentifier.ClientCtx));
            Assert.IsTrue(handler.ClientSubscriptions[chekExp.DataFeedIdentifier.SubscribtionId].CalcExpression.IsEqual(chekExp));

            // Assure Runtime Id is assigned properly
            var formulaId = handler.RuntimeIdStart + 1;
            handler.ClientSubscriptions[chekExp.DataFeedIdentifier.SubscribtionId]
                .CalcExpression
                .ExpressionFormulas
                .ForEach(x =>
                    {
                        Assert.IsTrue(x.RuntimeId == formulaId);
                        formulaId++;
                    });
        }
        /// <summary>
        /// FactorWebEnvelop
        /// </summary>
        public static PinkoServiceMessageEnvelop FactorWebEnvelop(this IPinkoApplication obj, string clientId, string webRoleId)
        {
            var envelop = new PinkoServiceMessageEnvelop(obj);

            envelop.PinkoProperties[PinkoMessagePropTag.ClientId] = clientId;
            envelop.PinkoProperties[PinkoMessagePropTag.WebRoleId] = webRoleId;

            return envelop;
        }
        public void TestRoleCalculateExpressionSnapshotHandlerIsSubscribtionFail()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();
            var handler = pinkoContainer.Resolve<WebRoleBusListenerCalculateExpressionResultHandler>().Register();

            var msgObj = SampleMockData.GetPinkoMsgCalculateExpressionResult(1)[0];

            // Test formula
            var envelop = new PinkoServiceMessageEnvelop() { Message = msgObj, ReplyTo = "UniteTestReplyQueue" };

            // Process request
            handler.PinkoMsgCalculateExpressionResultRouter.HandlerAction(envelop, msgObj);

            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 1);
        }
        public void TestPinkoPingMessageHandler()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();

            pinkoContainer.RegisterInstance(pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgPing>>().Register());
            var pinkoPingMessageHandler = pinkoContainer.Resolve<RoleBusListenerPinkoPingMessageHandle>().Register();

            var pm = new PinkoMsgPing { SenderMachine = "UnitTestClientMachine" };
            var pme = new PinkoServiceMessageEnvelop() { Message = pm, QueueName = "QueueNameRquest", ReplyTo = "QueueNameResponse" };

            pinkoPingMessageHandler.PinkoMsgPingReactiveListener.HandlerAction(pme, pm);

            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 1);
            Assert.IsNotNull(outboundMessages.OutboundMessages.First().Message is PinkoMsgPing);
        }
        public void TestCheckFields()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var webRoleConnectManager = pinkoContainer.Resolve<IWebRoleConnectManager>();
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();
            var handler = pinkoContainer.Resolve<RoleCalculateExpressionSnapshotHandler>().Register();

            var msgObj = new PinkoMsgCalculateExpression
            {
                ResultType = PinkoCalculateExpressionDaoExtensions.ResultDouble,
                ExpressionFormulas = SampleMockData.GetPinkoUserExpressionFormula(3),
                DataFeedIdentifier =
                {
                    MaketEnvId = PinkoMarketEnvironmentMock.MockMarketEnvId,
                    SignalRId = "SignalRId",
                    ClientCtx = "ClientCtx",
                    WebRoleId = "WebRoleId",
                    ClientId = "ClientId"
                }
            };

            // Test formula
            var envelop = new PinkoServiceMessageEnvelop() { Message = msgObj };
            envelop.PinkoProperties[PinkoMessagePropTag.RoleId] = webRoleConnectManager.WebRoleId;

            // Process request
            var outboundMsg = handler.ProcessSubscribe(envelop, msgObj);

            Assert.IsNotNull(outboundMsg);
            Assert.IsTrue(outboundMsg.ErrorCode == PinkoErrorCode.Success);
            Assert.IsTrue(outboundMsg.WebRoleId == msgObj.DataFeedIdentifier.WebRoleId);
            Assert.IsFalse(string.IsNullOrEmpty(outboundMsg.WebRoleId));

            // needs a response role id to route to a specific web role
            Assert.IsFalse(string.IsNullOrEmpty(webRoleConnectManager.WebRoleId));
            Assert.IsTrue(outboundMsg.PinkoProperties[PinkoMessagePropTag.RoleId] == webRoleConnectManager.WebRoleId);

            var resultMsg = (PinkoMsgCalculateExpressionResult)outboundMsg.Message;
            Assert.IsTrue(resultMsg.DataFeedIdentifier.SignalRId.Equals("SignalRId"));
            Assert.IsTrue(resultMsg.DataFeedIdentifier.ClientCtx.Equals("ClientCtx"));
            Assert.IsTrue(resultMsg.DataFeedIdentifier.WebRoleId.Equals("WebRoleId"));
            Assert.IsTrue(resultMsg.DataFeedIdentifier.ClientId.Equals("ClientId"));
            Assert.IsTrue(resultMsg.DataFeedIdentifier.MaketEnvId.Equals(PinkoMarketEnvironmentMock.MockMarketEnvId));
        }
        public void TestBusListenerCalculateExpressionSnapshotHandlerIsSubscribtionFail()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var webRoleConnectManager = pinkoContainer.Resolve<IWebRoleConnectManager>();
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();
            var handler = pinkoContainer.Resolve<RoleUserSubscriptionHandler>().Register();

            var msgObj = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            msgObj.MsgAction = PinkoMessageAction.UserSnapshot;  // Set to snapshot

            // Test formula
            var envelop = new PinkoServiceMessageEnvelop() { Message = msgObj, ReplyTo = "UniteTestReplyQueue" };
            envelop.PinkoProperties[PinkoMessagePropTag.RoleId] = webRoleConnectManager.WebRoleId;

            // Process request
            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, msgObj);

            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 0);
        }
        /// <summary>
        /// Process real time data subscription
        /// </summary>
        public void CheckClientTimeout(DateTime now)
        {
            ClientSubscriptions
                .GetEnumerator()
                //.ForEach(x => Debug.WriteLine(now.Subtract(x.LastPing).TotalMilliseconds))
                .Where(x => now.Subtract(x.LastPing).TotalMilliseconds > PinkoConfiguration.ClientTimeoutThresholdMs)
                .Select(x => x.CalcExpression)
                .ForEach(expression =>
                    {
                        Trace.TraceInformation("Expression Timed out: {0}", expression.Verbose());

                        // Update Runtime storage
                        PinkoStorage.RemoveExpression(PinkoStorageCode.SubsribeBucketName, HandlerPartitionId, expression.DataFeedIdentifier.SubscribtionId, expression);

                        // Remove from list
                        ClientSubscriptions.Remove(expression.DataFeedIdentifier.SubscribtionId);

                        // Broadcast to Calc engines to unsubscribe
                        //expression.MsgAction = PinkoMessageAction.ManagerUnsubscribe;
                        var outboundEnvelop = new PinkoServiceMessageEnvelop()
                        {
                            Message = new PinkoMsgClientTimeout
                                {
                                    DataFeedIdentifier = expression.DataFeedIdentifier.DeepClone()
                                },
                            ReplyTo = string.Empty,
                            WebRoleId = expression.DataFeedIdentifier.WebRoleId,
                            QueueName = PinkoConfiguration.PinkoMessageBusToWorkerCalcEngineAllTopic
                        };

                        // publish
                        TopicPublisher.Publish(outboundEnvelop);
                    });
        }
        /// <summary>
        /// Connect to Azure Server amd semd message
        /// </summary>
        //[TestMethod]
        public void RealAzureMessageLoop()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var pinkoApplication = pinkoContainer.Resolve<IPinkoApplication>();
            var pinkoConfiguration = pinkoContainer.Resolve<IPinkoConfiguration>();
            var ev = new ManualResetEvent(false);
            Tuple<IBusMessageInbound, PinkoMsgPing> receiveMessageInbound = null;

            // Connect to service
            var server = pinkoContainer.Resolve<AzureBusMessageServer>();
            pinkoContainer.RegisterInstance<IBusMessageServer>(server);
            server.Initialize();

            // Connect to queue
            const string queuName = "UnitTestQueueName";
            pinkoConfiguration.QueueConfiguration[queuName] = new Tuple<string, bool>(queuName, false);
            var queue = server.ConnectToQueue(queuName);

            // Listen to messages
            Task.Factory.StartNew(queue.Listen);
            ev.WaitOne(1000);

            // hook  listener (no natureal C3 event). use RReactive Extensions (Rx)
            var listener = pinkoApplication.GetSubscriber<Tuple<IBusMessageInbound, PinkoMsgPing>>();
            listener.Subscribe(x =>
            {
                receiveMessageInbound = x;
                ev.Set();
            });

            // Create sample message
            var outboundMsg = new PinkoServiceMessageEnvelop()
            {
                Message = new PinkoMsgPing { SenderMachine = "ClientMachine", ResponderMachine = "ServerMachine" },
                QueueName = queuName
            };
            outboundMsg.PinkoProperties["key1"] = "key1Value1";
            outboundMsg.PinkoProperties["key2"] = "key1Value2";

            // simulate incoming message to teh WebRole
            pinkoApplication
                .GetBus<IBusMessageOutbound>()
                .Publish(outboundMsg);
            ev.WaitOne(20000);

            server.Deinitialize();
            queue.Close();

            Assert.IsNotNull(receiveMessageInbound);
            Assert.IsTrue(receiveMessageInbound.Item2.GetType() == typeof(PinkoMsgPing));

            // Assure properties were serialize by Azure layer
            Assert.IsTrue(receiveMessageInbound.Item1.PinkoProperties.ContainsKey("key1"));
            Assert.IsTrue(receiveMessageInbound.Item1.PinkoProperties.ContainsKey("key2"));
            Assert.IsTrue(receiveMessageInbound.Item1.PinkoProperties["key1"].Equals("key1Value1"));
            Assert.IsTrue(receiveMessageInbound.Item1.PinkoProperties["key2"].Equals("key1Value2"));
        }
        public void TestSubscribeException()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var webRoleConnectManager = pinkoContainer.Resolve<IWebRoleConnectManager>();
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();
            var handler = pinkoContainer.Resolve<RoleCalculateExpressionSnapshotHandler>().Register();
            var expEngine = pinkoContainer.Resolve<IPinkoExpressionEngine>() as PinkoExpressionEngineMock;

            //var msgObj = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            //msgObj.MsgAction = PinkoMessageAction.UserSnapshot;  // Set to snapshot

            // Test formula
            var msgObj = new PinkoMsgCalculateExpression
                             {
                                 ResultType = PinkoCalculateExpressionDaoExtensions.ResultDouble,
                                 ExpressionFormulas = SampleMockData.GetPinkoUserExpressionFormula(3),
                                 MsgAction = PinkoMessageAction.UserSnapshot,
                                 DataFeedIdentifier = { MaketEnvId = PinkoMarketEnvironmentMock.MockMarketEnvId }
                             };
            var envelop = new PinkoServiceMessageEnvelop() { Message = msgObj, ReplyTo = "UniteTestReplyQueue" };
            envelop.PinkoProperties[PinkoMessagePropTag.RoleId] = webRoleConnectManager.WebRoleId;

            // Test formula - should exception
            expEngine.ExceptionParseAction = () =>
                                          {
                                              throw new Exception("MockException");
                                          };

            // Process request
            handler.PinkoMsgCalculateExpressionReactiveListener.HandlerAction(envelop, msgObj);

            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 1);
            Assert.IsTrue(outboundMessages.OutboundMessages.ElementAt(0).ErrorCode == PinkoErrorCode.UnexpectedException);

            //var resultMsg = (PinkoMsgCalculateExpressionResult)outboundMessages.OutboundMessages.ElementAt(0).Message;
            //Assert.IsTrue(resultMsg.ResultType == PinkoErrorCode.UnexpectedException);
        }
예제 #10
0
        /// <summary>
        /// Get resulting tuple with envelop and expression
        /// </summary>
        public static Tuple<PinkoMsgCalculateExpressionResult, PinkoServiceMessageEnvelop, PinkoMsgCalculateExpression> GetResultTuple()
        {
            var expression = GetPinkoMsgCalculateExpression()[0];
            var resultMsg = new PinkoMsgCalculateExpressionResult().FromRequest(expression);
            var envelop = new PinkoServiceMessageEnvelop() { Message = expression };

            return new Tuple<PinkoMsgCalculateExpressionResult, PinkoServiceMessageEnvelop, PinkoMsgCalculateExpression>(resultMsg, envelop, expression);
        }
        public void TestBusListenerSubscribeExpressionHandlerFail()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var webRoleConnectManager = pinkoContainer.Resolve<IWebRoleConnectManager>();
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();
            var handler = pinkoContainer.Resolve<RoleUserSubscriptionHandler>().Register();

            var msgObj = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            msgObj.MsgAction = PinkoMessageAction.MaxActions;  // Invalid

            // Test formula
            var envelop = new PinkoServiceMessageEnvelop() { Message = msgObj };
            envelop.PinkoProperties[PinkoMessagePropTag.RoleId] = webRoleConnectManager.WebRoleId;

            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, msgObj);

            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 0);
        }
        public void TestUpdateSubscription()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();
            var handler = pinkoContainer.Resolve<RoleUserSubscriptionHandler>().Register();
            var pinkoConfiguration = pinkoContainer.Resolve<IPinkoConfiguration>();
            var pinkoStorage = pinkoContainer.Resolve<IPinkoStorage>() as PinkoStorageMock;

            //
            // process request #1
            //
            var expression = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            expression.MsgAction = PinkoMessageAction.UserSubscription;  // Set to subscription
            var envelop = new PinkoServiceMessageEnvelop() { Message = expression, ReplyTo = "UniteTestReplyQueue" };

            // Process request
            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, expression);

            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 1);
            Assert.IsTrue(outboundMessages.OutboundMessages.ElementAt(0).Message is PinkoMsgCalculateExpression);
            Assert.IsTrue(outboundMessages.OutboundMessages.ElementAt(0).QueueName.Equals(pinkoConfiguration.PinkoMessageBusToCalcEngineQueue));
            //Assert.IsTrue(outboundMessages.OutboundMessages.ElementAt(1).Message is PinkoMsgCalculateExpression);

            var outToCalcEnv = outboundMessages.OutboundMessages.ElementAt(0);
            var outToCalcEng = (PinkoMsgCalculateExpression)outToCalcEnv.Message;

            // subscription message sent out to calc engine
            Assert.IsTrue(outToCalcEnv.QueueName.Equals(pinkoConfiguration.PinkoMessageBusToCalcEngineQueue));
            Assert.IsTrue(outToCalcEnv.ReplyTo.Equals("UniteTestReplyQueue"));
            Assert.IsTrue(handler.ClientSubscriptions[expression.DataFeedIdentifier.SubscribtionId].CalcExpression.IsEqual(outToCalcEng));

            // Assure storage was updated
            Assert.IsTrue(pinkoStorage.MockStorage.Count == 1);
            Assert.IsTrue(pinkoStorage.MockStorage.Values.First().Equals(outToCalcEng));
            Assert.IsTrue(pinkoStorage.MockStorage.Values.First().MsgAction == PinkoMessageAction.ManagerSubscription);

            //
            // process request #2 - update to same. A wash.
            //
            expression = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            expression.MsgAction = PinkoMessageAction.UserSubscription;  // Set to subscription
            envelop = new PinkoServiceMessageEnvelop() { Message = expression, ReplyTo = "UniteTestReplyQueue" };
            outboundMessages.Clear();

            // Process request
            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, expression);

            //var outToCalcEnv2 = outboundMessages.OutboundMessages.ElementAt(0);
            //var outToCalcEng2 = (PinkoMsgCalculateExpression)outToCalcEnv.Message;

            // subscription message sent out to calc engine
            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 1);
            Assert.IsTrue(outboundMessages.OutboundMessages.First().Message is PinkoMsgCalculateExpressionResult);
            Assert.IsTrue(handler.ClientSubscriptions[expression.DataFeedIdentifier.SubscribtionId].CalcExpression.IsEqual(outToCalcEng));

            // Must be equal

            // Assure storage was updated
            Assert.IsTrue(pinkoStorage.MockStorage.Count == 1); // Should stay the same
            Assert.IsTrue(pinkoStorage.MockStorage.Values.First().Equals(outToCalcEng));
            Assert.IsTrue(pinkoStorage.MockStorage.Values.First().MsgAction == PinkoMessageAction.ManagerSubscription);

            //
            // process request update #3
            //
            expression = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            expression.DataFeedIdentifier.SignalRId = "new signal id";
            expression.MsgAction = PinkoMessageAction.UserSubscription;  // Set to subscription
            envelop = new PinkoServiceMessageEnvelop() { Message = expression, ReplyTo = "UniteTestReplyQueue" };
            outboundMessages.Clear();

            // Process request
            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, expression);

            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 1);

            var outToCalcEnv3 = outboundMessages.OutboundMessages.ElementAt(0);
            Assert.IsTrue(outToCalcEnv3.Message is PinkoMsgCalculateExpression);

            var outToCalcEng3 = (PinkoMsgCalculateExpression)outToCalcEnv3.Message;

            // subscription message sent out to calc engine
            Assert.IsTrue(outToCalcEnv3.QueueName.Equals(pinkoConfiguration.PinkoMessageBusToWorkerCalcEngineTopic));
            Assert.IsTrue(outToCalcEnv3.ReplyTo.Equals("UniteTestReplyQueue"));
            Assert.IsFalse(string.IsNullOrEmpty(outToCalcEnv3.WebRoleId));
            Assert.IsTrue(outToCalcEnv3.WebRoleId.Equals(outToCalcEng3.DataFeedIdentifier.WebRoleId));
            Assert.IsTrue(handler.ClientSubscriptions[outToCalcEng3.DataFeedIdentifier.SubscribtionId].CalcExpression.IsEqual(outToCalcEng3));

            // Assure storage was updated
            Assert.IsTrue(pinkoStorage.MockStorage.Count == 1);
            Assert.IsTrue(pinkoStorage.MockStorage.Values.First().Equals(outToCalcEng3));
            Assert.IsTrue(pinkoStorage.MockStorage.Values.First().MsgAction == PinkoMessageAction.ManagerSubscription);
        }
        public void TestTimer()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var pinkoConfiguration = pinkoContainer.Resolve<IPinkoConfiguration>() as PinkoConfiguration;
            pinkoConfiguration._clientTimeoutThresholdMs = 3000;

            var pinkoApplication = pinkoContainer.RegisterInstance<IPinkoApplication>(pinkoContainer.Resolve<PinkoApplication>()) as PinkoApplication;
            var handler = pinkoContainer.Resolve<RoleUserSubscriptionHandler>().Register();

            // Add subscription
            var expression = SampleMockData.GetPinkoMsgCalculateExpression(1)[0];
            var envelop = new PinkoServiceMessageEnvelop() { Message = expression };
            handler.ProcessSubscribe(envelop, expression);

            Assert.IsTrue(handler.ClientSubscriptions.Count() == 1);
            var expressiontoTimeout = handler.ClientSubscriptions.GetEnumerator().ToList()[0];      // Get the record that should be deleted
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();

            // Mock a new timeout on one item
            expressiontoTimeout.LastPing = expressiontoTimeout.LastPing.AddMilliseconds(pinkoConfiguration.ClientTimeoutThresholdMs * -2);

            // Wait for worker to remove record
            Thread.Sleep(pinkoConfiguration._clientTimeoutThresholdMs + 1000);

            // REcord should have been removed
            Assert.IsTrue(handler.ClientSubscriptions.Count() == 0);

            // Assure message was sent out
            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 1);
            Assert.IsTrue(outboundMessages.OutboundMessages.First().QueueName.Equals(pinkoConfiguration.PinkoMessageBusToWorkerCalcEngineAllTopic));
        }
        /// <summary>
        /// Process real time data subscription
        /// </summary>
        public IBusMessageOutbound ProcessSubscribe(IBusMessageInbound envelop, PinkoMsgCalculateExpression expression)
        {
            var response = (IBusMessageOutbound)envelop;
            var resultMsg = new PinkoMsgCalculateExpressionResult().FromRequest(expression);

            response.Message = resultMsg;
            response.WebRoleId = expression.DataFeedIdentifier.WebRoleId;

            PinkoMsgCalculateExpression updatedExpMsg = null;
            var isNew = false;

            //  - Do check for current existence
            //  - look for Id changes.
            var clientSubscription =
                ClientSubscriptions.ReplaceCondition(expression.DataFeedIdentifier.SubscribtionId,
                                                     // only replace if null, or expressions are not equal.
                                                     x => (isNew = (null == x)) || !x.CalcExpression.IsEqual(expression),
                                                     x =>
                                                     {
                                                         // create new Runtime ids if formula was changed
                                                         if (null == x || x.CalcExpression.IsFormulaChanged(expression))
                                                             foreach (var formula in expression.ExpressionFormulas)
                                                                 formula.RuntimeId = Interlocked.Increment(ref _runtimeIdSequenceStart);

                                                         return new ClientSubscription() {CalcExpression = expression};
                                                     });

            if (clientSubscription.IsNotNull())
                updatedExpMsg = clientSubscription.CalcExpression;

            // Expression was either replaced, or added
            if (updatedExpMsg.IsNotNull())
            {
                // Update Runtime storage
                PinkoStorage.SaveExpression(PinkoStorageCode.SubsribeBucketName, HandlerPartitionId, expression.DataFeedIdentifier.SubscribtionId, expression);

                // Broadcast to Calc engines that a change happened. They need to update their ids.
                expression.MsgAction = PinkoMessageAction.ManagerSubscription;
                var outboundEnvelop = new PinkoServiceMessageEnvelop()
                {
                    WebRoleId = updatedExpMsg.DataFeedIdentifier.WebRoleId,
                    Message = updatedExpMsg,
                    ReplyTo = envelop.ReplyTo, // string.Empty,  //PinkoConfiguration.PinkoMessageBusToWebRoleCalcResultTopic,
                    //                               New Calc Engine                                             Subscription update to specific role
                    QueueName = isNew ? PinkoConfiguration.PinkoMessageBusToCalcEngineQueue : PinkoConfiguration.PinkoMessageBusToWorkerCalcEngineTopic
                };

                // publish
                TopicPublisher.Publish(outboundEnvelop);

                // do not reply.  The Calc engine will repond to client.
                return null;
            }

            //
            // Unsubscribe
            //  -   remove from storage
            //  -   Tell the calc engines to unsubscribe

            // Calc Engine monitor
            //  -   Monitor calc engines heart beat
            //  -   If failed, the re-subscribe the client

            // Monitor siblings
            //  -   If sibling missing, the take over its subscriptions
            //  -   Load from storage and re-subscribe the client formulas

            return response;
        }
        public void TestPinkoMsgClientConnectSuccess()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var webRoleConnectManager = pinkoContainer.Resolve<IWebRoleConnectManager>();
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();
            var handler = pinkoContainer.Resolve<RoleUserSubscriptionHandler>().Register();

            var msgObj = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            msgObj.MsgAction = PinkoMessageAction.UserSubscription;  // Set to subscription

            // Test formula
            var envelop = new PinkoServiceMessageEnvelop() { Message = msgObj };
            envelop.PinkoProperties[PinkoMessagePropTag.RoleId] = webRoleConnectManager.WebRoleId;

            var originalIdentifier = msgObj.DataFeedIdentifier.DeepClone();

            // Add subscription
            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, msgObj);

            var outMsg = outboundMessages.OutboundMessages.First().Message as PinkoMsgCalculateExpression;
            Assert.IsTrue(outMsg.MsgAction == PinkoMessageAction.ManagerSubscription);
            Assert.IsTrue(outMsg.DataFeedIdentifier.IsEqual(originalIdentifier));
            Assert.IsTrue(handler.ClientSubscriptions.Count() == 1);
            Assert.IsTrue(handler.ClientSubscriptions[originalIdentifier.SubscribtionId].CalcExpression.DataFeedIdentifier.IsEqual(originalIdentifier));

            // Send change
            var clientConn = SampleMockData.GetPinkoMsgClientConnect(2)[1];
            var envelopClientConn = new PinkoServiceMessageEnvelop() { Message = clientConn };
            outboundMessages.Clear();

            var changedIdentifier = clientConn.DataFeedIdentifier;
            changedIdentifier.SubscribtionId = originalIdentifier.SubscribtionId;  // AMke it the same as original
            var newCloned = originalIdentifier.PartialClone(changedIdentifier);

            // Send Id change
            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgClientConnect>>().HandlerAction(envelopClientConn, clientConn);

            Assert.IsTrue(outMsg.MsgAction == PinkoMessageAction.ManagerSubscription);
            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 0);  // No outbound messages
            Assert.IsTrue(handler.ClientSubscriptions.Count() == 1);
            Assert.IsTrue(handler.ClientSubscriptions[originalIdentifier.SubscribtionId].CalcExpression.DataFeedIdentifier.IsEqual(newCloned));
            Assert.IsFalse(handler.ClientSubscriptions[originalIdentifier.SubscribtionId].CalcExpression.DataFeedIdentifier.IsEqual(originalIdentifier));
        }
        public void TestClienttimeout()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var webRoleConnectManager = pinkoContainer.Resolve<IWebRoleConnectManager>();
            var pinkoConfiguration = pinkoContainer.Resolve<IPinkoConfiguration>();
            var handler = pinkoContainer.Resolve<RoleUserSubscriptionHandler>().Register();

            // Add subscribers
            SampleMockData
                .GetPinkoMsgCalculateExpression(10)
                .ForEach(msgObj =>
                    {
                        msgObj.MsgAction = PinkoMessageAction.UserSubscription; // Set to subscription

                        // Test formula
                        var envelop = new PinkoServiceMessageEnvelop() {Message = msgObj};
                        envelop.PinkoProperties[PinkoMessagePropTag.RoleId] = webRoleConnectManager.WebRoleId;

                        // Add subscription
                        handler.ProcessSubscribe(envelop, msgObj);
                    });

            Assert.IsTrue(handler.ClientSubscriptions.Count() == 10);

            // Mock a new timeout on one item
            var now = handler.ClientSubscriptions.GetEnumerator().ToList()[0].LastPing;             // pick a now date
            var expressiontoTimeout = handler.ClientSubscriptions.GetEnumerator().ToList()[3];      // Get the record that should be deleted

            // Manually set timeout to before
            expressiontoTimeout.LastPing = expressiontoTimeout.LastPing.AddMilliseconds(pinkoConfiguration.ClientTimeoutThresholdMs * -2);

            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();

            // Remove expressiontoTimeout
            handler.CheckClientTimeout(now);

            Assert.IsTrue(handler.ClientSubscriptions.Count() == 9);
            Assert.IsNull(handler.ClientSubscriptions[expressiontoTimeout.CalcExpression.DataFeedIdentifier.SubscribtionId]);

            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 1);

            Assert.IsTrue(outboundMessages.OutboundMessages.First().QueueName.Equals(pinkoConfiguration.PinkoMessageBusToWorkerCalcEngineAllTopic));

            // Web role Id
            Assert.IsFalse(string.IsNullOrEmpty(outboundMessages.OutboundMessages.First().WebRoleId));
            Assert.IsTrue(outboundMessages.OutboundMessages.First().WebRoleId.Equals(expressiontoTimeout.CalcExpression.DataFeedIdentifier.WebRoleId));

            // Check identifiers
            var outMsg = (PinkoMsgClientTimeout)outboundMessages.OutboundMessages.First().Message;
            Assert.IsTrue(outMsg.DataFeedIdentifier.IsEqual(expressiontoTimeout.CalcExpression.DataFeedIdentifier));
        }
        public void TestCahngeSusbcribtionNew()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var handler = pinkoContainer.Resolve<RoleUserSubscriptionHandler>().Register();

            var expression = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            expression.MsgAction = PinkoMessageAction.UserSubscription;  // Set to subscription
            var envelop = new PinkoServiceMessageEnvelop() { Message = expression, ReplyTo = "UniteTestReplyQueue" };

            // Change expression
            var expressionNew = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            expressionNew.MsgAction = PinkoMessageAction.UserSubscription;  // Set to subscription
            expressionNew.ExpressionFormulasStr = "new formula";

            // process request
            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, expression);
            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, expressionNew);

            Assert.IsTrue(handler.ClientSubscriptions.Count() == 1);

            Assert.IsFalse(handler.ClientSubscriptions[expressionNew.DataFeedIdentifier.SubscribtionId].CalcExpression.IsEqual(expression));  // Must not be equal
            Assert.IsTrue(handler.ClientSubscriptions[expressionNew.DataFeedIdentifier.SubscribtionId].CalcExpression.IsEqual(expressionNew));         // Must be equal
            Assert.AreSame(handler.ClientSubscriptions[expressionNew.DataFeedIdentifier.SubscribtionId].CalcExpression, expressionNew);         // Must be equal
        }
        public void TestBusListenerSubscribeExpressionHandlerSuccess()
        {
            var pinkoContainer = PinkoContainerMock.GetMockContainer();
            var webRoleConnectManager = pinkoContainer.Resolve<IWebRoleConnectManager>();
            var outboundMessages = pinkoContainer.Resolve<OutbountListener<IBusMessageOutbound>>();
            var pinkoConfiguration = pinkoContainer.Resolve<IPinkoConfiguration>();
            var handler = pinkoContainer.Resolve<RoleUserSubscriptionHandler>().Register();

            var msgObj = SampleMockData.GetPinkoMsgCalculateExpression()[0];
            msgObj.MsgAction = PinkoMessageAction.UserSubscription;  // Set to subscription

            // Test formula
            var envelop = new PinkoServiceMessageEnvelop() { Message = msgObj };
            envelop.PinkoProperties[PinkoMessagePropTag.RoleId] = webRoleConnectManager.WebRoleId;

            pinkoContainer.Resolve<InboundMessageReactiveListener<PinkoMsgCalculateExpression>>().HandlerAction(envelop, msgObj);

            Assert.IsTrue(outboundMessages.OutboundMessages.Count == 1);
            Assert.IsTrue(outboundMessages.OutboundMessages.First().ErrorCode == PinkoErrorCode.Success);
            Assert.IsTrue(outboundMessages.OutboundMessages.First().QueueName.Equals(pinkoConfiguration.PinkoMessageBusToCalcEngineQueue));
        }