internal void RegisterGlue(Glue42 glue)
        {
            _glue = glue;
            UpdateUI(true);

            _glue.Interop.ConnectionStatusChanged += InteropConnectionStatusChanged;

            // register a streaming endpoint (Glue stream) called GlueDemoTickStream
            stream_ = _glue.Interop.RegisterStreamingEndpoint(smb => smb.SetMethodName("GlueDemoTickStream")
                                                              .SetParameterSignature("bool reject, string symbol"),
                                                              new ServerEventStreamHandler(false)
            {
                // in each of the stream handler events we have the optional cookie parameter
                // that is optionally supplied while registering the stream

                // this lambda is invoked when a new subscription request is received
                SubscriptionRequestHandler = SubscriptionRequestHandler,

                // this lambda is invoked when new subscriber has been connected to a branch
                SubscriberHandler = SubscriberHandler,

                //this lambda is invoked when a subscriber cancels its subscription or has been kicked (banned) by the publisher
                UnsubscribeHandler = UnsubscribeHandler
            });
        }
        public IEventStreamBranch HandleSubscriptionRequest(
            IServerEventStream serverEventStream,
            IEventStreamSubscriptionRequest subscriptionRequest,
            object streamCookie = null)
        {
            string message = null;

            try
            {
                if (!acceptor_(subscriptionRequest, ref message))
                {
                    subscriptionRequest.Reject(
                        reply => reply.SetIsFailed(true).SetMessage(message).Build());
                    return(null);
                }
                return(subscriptionRequest.Accept(
                           reply => reply.SetMessage(message ?? "Subscribed").Build()));
            }
            catch (Exception e)
            {
                subscriptionRequest.Reject(
                    reply => reply.SetIsFailed(true)
                    .SetMessage(string.Format("Unexpected error: {0}", e.Message))
                    .Build());
                return(null);
            }
        }
        private IEventStreamBranch SubscriptionRequestHandler(IServerEventStream stream, IEventStreamSubscriptionRequest request, object cookie)
        {
            // validate the request
            // for demo purposes we have a reject argument sent by the subscriber
            bool   shouldReject = request.SubscriptionContext.Arguments.GetValueByName("reject", v => v.AsBool);
            string symbol       = request.SubscriptionContext.Arguments.GetValueByName("symbol", v => v.AsString());

            LogMessage($"Subscription request from {request.Caller} for symbol {symbol} - {request.SubscriptionContext.Arguments.AsString()}");

            if (shouldReject || string.IsNullOrEmpty(symbol))
            {
                string rejectionReason = shouldReject ? "rejected as requested" : "rejected because symbol is empty";
                string rejectionMsg    = $"Subscription request from {request.Caller} {rejectionReason}";
                LogMessage(rejectionMsg);

                // if we cannot validate the subscription request we can reject it
                request.Reject(smrb =>
                               smrb.SetMessage(rejectionMsg)
                               .SetContext(cb =>
                                           cb.AddValue("RejectionArgument", new[] { 5, 3, 2, 1, 2 })
                                           .AddValue("MoreRejectionArguments", "sdfgsdfg")).Build());

                return(null);
            }

            // when we validate the subscription request, we can assign the subscriber to a branch
            // in this demo we will use the tickMode as a branch (https://docs.glue42.com/glue42-concepts/data-sharing-between-apps/interop/net/index.html#streaming)

            // branches are an optional grouping of multiple subscribers to ease data category segregation - the branches are keyed by
            // 'any' object supplied by the publisher

            // if we don't need a branching mechanism, we then use the 'main' branch by *not* supplying value for branch key.
            return(request.Accept(smrb => smrb.Build(), branchKey: symbol));
        }
 public void HandleSubscriber(
     IServerEventStream serverEventStream,
     IEventStreamSubscriber subscriber,
     IEventStreamBranch branch,
     object streamCookie = null)
 {
     if (subscriberAdded_ != null)
     {
         subscriberAdded_(subscriber);
     }
 }
 public void HandleSubscriberRemoved(
     IServerEventStream serverEventStream,
     IEventStreamSubscriber subscriber,
     EventStreamSubscriberRemovedContext subscriberRemovedContext,
     IEventStreamBranch branch = null,
     object streamCookie       = null)
 {
     if (subscriberRemoved_ != null)
     {
         subscriberRemoved_(subscriber);
     }
 }
        private void UnsubscribeHandler(
            IServerEventStream stream,
            IEventStreamSubscriber subscriber,
            EventStreamSubscriberRemovedContext context,
            IEventStreamBranch branch,
            object cookie)
        {
            IEventStreamSubscriptionRequest request = subscriber.Subscription;

            // log the subscription cancellation
            LogMessage($"Removed subscriber {request.Caller} {request.SubscriptionContext.Arguments.AsString()}");

            // remove subscriptions when cancelled
            var subscriptionItem = $"{request.Caller.ApplicationName} {request.SubscriptionContext.Arguments.AsString()}";

            DispatchAction(() => ListViewSubscriptions.Items.Remove(subscriptionItem));
        }
        private void SubscriberHandler(IServerEventStream stream, IEventStreamSubscriber subscriber, IEventStreamBranch branch, object cookie)
        {
            IEventStreamSubscriptionRequest request = subscriber.Subscription;

            // log the subscriber
            LogMessage($"New subscriber {request.Caller} {request.SubscriptionContext.Arguments.AsString()}");

            // push an 'image' to that subscriber which is received *only* by it (last image pattern)

            // this will be received as an OOB data - see the demo subscriber code
            subscriber.Push(cb =>
                            cb.AddValue("SubscribersAsImage", _glue.AGMObjectSerializer.Serialize(stream.GetBranches()
                                                                                                  .SelectMany(b =>
                                                                                                              b.GetSubscribers().Select(sb => sb.Subscription.Caller)))));

            // e.g. keep the subscriptions in a list
            var subscriptionItem = $"{request.Caller.ApplicationName} {request.SubscriptionContext.Arguments.AsString()}";

            DispatchAction(() =>
            {
                ListViewSubscriptions.Items.Add(subscriptionItem);
                ListViewSubscriptions.ScrollIntoView(subscriptionItem);
            });
        }
        public MainWindow()
        {
            InitializeComponent();

            // create a timer for each of the StoreDepartments (branches)
            // each timer will push to the relevant branch
            timer_.Add(StoreDepartment.Books, new Timer(OnTimerTick, StoreDepartment.Books, 0, 1000));
            timer_.Add(StoreDepartment.Apparel, new Timer(OnTimerTick, StoreDepartment.Apparel, 0, 2500));
            timer_.Add(StoreDepartment.Food, new Timer(OnTimerTick, StoreDepartment.Food, 0, 5000));

            // initialize Glue
            glue_ = new Glue42();

            // give the publisher an application name
            // explicitly turn off Glue Window management, Glue contexts, Glue AppManager, Glue metrics and Glue notifications
            // as they're not used in this example
            glue_.Initialize("GlueStreamsPublisher", useAppManager: false, useStickyWindows: false,
                             useContexts: false, useMetrics: false, useNotifications: false);

            // detect connection status change and log it to the UI
            glue_.Interop.ConnectionStatusChanged += (sender, args) => LogMessage($"Glue is now {args.Status}");

            // register a streaming endpoint (Glue stream) called GlueDemoStoreStream

            stream_ = glue_.Interop.RegisterStreamingEndpoint(smb => smb.SetMethodName("GlueDemoStoreStream")
                                                              .SetParameterSignature("bool reject, int storeDepartment"),
                                                              new ServerEventStreamHandler(false)
            {
                // in each of the stream handler events we have the optional cookie parameter
                // that is optionally supplied while registering the stream

                // this lambda is invoked when a new subscription request is received
                SubscriptionRequestHandler = (stream, request, cookie) =>
                {
                    // validate the request
                    // for demo purposes we have a reject argument sent by the subscriber
                    bool reject = request.SubscriptionContext.Arguments.GetValueByName("reject", v => v.AsBool);

                    StoreDepartment department = request.SubscriptionContext.Arguments.GetValueByName("StoreDepartment",
                                                                                                      v => Enum.TryParse(v, true, out StoreDepartment sd) ? sd : StoreDepartment.None);

                    LogMessage($@"Subscription request from {request.Caller} for StoreDepartment {department}: {request.SubscriptionContext.Arguments.AsString()}");

                    if (reject || department == StoreDepartment.None)
                    {
                        var rejectionMsg = new StringBuilder($"Subscription request from {request.Caller} rejected. Reason(s): ");
                        if (reject)
                        {
                            rejectionMsg.Append("Reject requested;");
                        }
                        if (department == StoreDepartment.None)
                        {
                            rejectionMsg.Append("StoreDepartment invalid");
                        }

                        LogMessage(rejectionMsg.ToString());

                        // if we cannot validate the subscription request we can reject it
                        request.Reject(smrb =>
                                       smrb.SetMessage(rejectionMsg.ToString())
                                       .SetContext(cb =>
                                                   cb.AddValue("RejectionArgument", new[] { 5, 3, 2, 1, 2 })
                                                   .AddValue("MoreRejectionArguments", "sdfgsdfg")).Build());

                        return(null);
                    }

                    // when we validate the subscription request, we can assign the subscriber to a branch
                    // in this demo we will use the StoreDepartment as a branch (https://docs.glue42.com/g4e/net-interop/index.html#interop-streaming)

                    // branches are an optional grouping of multiple subscribers to ease data category segregation - the branches are keyed by
                    // 'any' object supplied by the publisher

                    // if we don't need a branching mechanism, we then use the 'main' branch by *not* supplying value for branch key.
                    return(request.Accept(smrb => smrb.Build(), branchKey: department));
                },

                // this lambda is invoked when new subscriber has been connected to a branch
                SubscriberHandler = (stream, subscriber, branch, cookie) =>
                {
                    IEventStreamSubscriptionRequest request = subscriber.Subscription;
                    // log the subscriber
                    LogMessage(
                        $"New subscriber {request.Caller} {request.SubscriptionContext.Arguments.AsString()}");

                    // push an 'image' to that subscriber which is received *only* by it (last image pattern)

                    // this will be received as an OOB data - see the demo subscriber code
                    subscriber.Push(cb =>
                                    cb.AddValue("SubscribersAsImage", glue_.AGMObjectSerializer.Serialize(stream.GetBranches()
                                                                                                          .SelectMany(b =>
                                                                                                                      b.GetSubscribers().Select(sb => sb.Subscription.Caller)))));

                    // e.g. keep the subscriptions in a list
                    DispatchAction(() => Subscriptions.Items.Add(request.Caller.ApplicationName +
                                                                 " " +
                                                                 request.SubscriptionContext
                                                                 .Arguments
                                                                 .AsString()));
                },

                //this lambda is invoked when a subscriber cancels its subscription or has been kicked (banned) by the publisher
                UnsubscribeHandler = (stream, subscriber, unsubscribeCxt, branch, cookie) =>
                {
                    IEventStreamSubscriptionRequest request = subscriber.Subscription;

                    // log the subscription cancellation
                    LogMessage(
                        $"Removed subscriber {request.Caller} {request.SubscriptionContext.Arguments.AsString()}");

                    // remove subscriptions when cancelled
                    DispatchAction(() =>
                                   Subscriptions.Items.Remove(request.Caller.ApplicationName + " " +
                                                              request.SubscriptionContext.Arguments.AsString()));
                }
            });
 public void HandleStreamClosed(
     IServerEventStream serverEventStream,
     object streamCookie = null)
 {
 }
 public void HandleStreamBranchClosed(
     IServerEventStream serverEventStream,
     IEventStreamBranch branch,
     object streamCookie = null)
 {
 }