OfficeDev / ews-managed-api

Other
585 stars 317 forks source link

Subscribe to Push Notifications Error #250

Open tylersriver opened 4 years ago

tylersriver commented 4 years ago

I've been digging around the internet and the information surrounding push notifications is sparse. I experienced the below error when attempting to Subscribe to push notifications. This happens after a timer elapsed and no notification is yet to be received to subscribe operation is tried again. Any direction at all would be helpful. We have over 1400 subscriptions running each one is an instance of a class that uses the code below.

The Exception: Message : There were not enough free threads in the ThreadPool to complete the operation.

Inner Exception: Trace : at System.Net.HttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state) at Microsoft.Exchange.WebServices.Data.EwsHttpWebRequest.Microsoft.Exchange.WebServices.Data.IEwsHttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state) in \REDMOND\EXCHANGE\BUILD\E15\15.00.0913.015\SOURCES\sources\dev\EwsManagedApi\src\EwsManagedApi\Core\EwsHttpWebRequest.cs:line 54 at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.EmitRequest(IEwsHttpWebRequest request) in \REDMOND\EXCHANGE\BUILD\E15\15.00.0913.015\SOURCES\sources\dev\EwsManagedApi\src\EwsManagedApi\Core\Requests\ServiceRequestBase.cs:line 413

at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.BuildEwsHttpWebRequest() in \REDMOND\EXCHANGE\BUILD\E15\15.00.0913.015\SOURCES\sources\dev\EwsManagedApi\src\EwsManagedApi\Core\Requests\ServiceRequestBase.cs:line 790 at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest(IEwsHttpWebRequest& request) in \REDMOND\EXCHANGE\BUILD\E15\15.00.0913.015\SOURCES\sources\dev\EwsManagedApi\src\EwsManagedApi\Core\Requests\ServiceRequestBase.cs:line 687

at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute() in \REDMOND\EXCHANGE\BUILD\E15\15.00.0913.015\SOURCES\sources\dev\EwsManagedApi\src\EwsManagedApi\Core\Requests\MultiResponseServiceRequest.cs:line 157 at Microsoft.Exchange.WebServices.Data.ExchangeService.SubscribeToPushNotificationsOnAllFolders(Uri url, Int32 frequency, String watermark, EventType[] eventTypes) in \REDMOND\EXCHANGE\BUILD\E15\15.00.0913.015\SOURCES\sources\dev\EwsManagedApi\src\EwsManagedApi\Core\ExchangeService.cs:line 2103

at ExchangeSubscriptionManager.Services.SubscriptionService.Subscribe() in C:\TeamCity\TC04_OPS_Agent_40\work\7ede183819f1d2a4\ExchangeSubscriptionManager\Services\SubscriptionService.cs:line 507

Note: notificationFrequency=4

Code Snippet:

        /// <summary>
        /// Subscribes the user to push notifications
        /// </summary>
        private void Subscribe()
        {
            try
            {
                PushSubscription sub;
                if (user.TrackEmails)
                {
                    sub =
                        service.GetConn().SubscribeToPushNotificationsOnAllFolders(
                            new Uri(uri),
                            notificationFrequency,
                            subscription.Watermark,
                            user.GetEventTypes()
                    );
                }
                else
                {
                    sub =
                        service.GetConn().SubscribeToPushNotifications(
                            user.GetFolders(),
                            new Uri(uri),
                            notificationFrequency,
                            subscription.Watermark,
                            user.GetEventTypes()
                    );
                }
                logger.Log("Push Subscription started to track : " + (user.TrackEmails ? "Emails " : " ") + (user.SyncAppointments ? "Appointments" : ""));
                subscription.SubId = sub.Id;
                subscription.Watermark = sub.Watermark;
            }
            catch (Exception ex)
            {
                logger.Error("FAILED TO SUBSCRIBE", ex);
            }
            _subscriptionEstablished = DateTime.Now;

            // Setup timer
            timer = new Timer
            {
                Interval = (notificationFrequency * 60000) + 10000
            };
            timer.Elapsed += Timer_Elapsed;
            timer.Start();
        }

        /// <summary>
        /// Handles re-subscribing on timeout
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            logger.Log("Timer Elapsed, checking subscription...");

            // Make sure listener is active
            if(listener == null || !listener.IsListening)
            {
                SetupListener();
            }

            TimeSpan maxRetry = new TimeSpan(0, notificationFrequency * 6, 0);
            DateTime eventTimeout = DateTime.Now.Subtract(maxRetry);
            if (_lastNotificationReceived == DateTime.MaxValue)
            {
                // We've never received a notification, so check when we subscribed
                if (_subscriptionEstablished > eventTimeout) return;
            }
            else if (_lastNotificationReceived > eventTimeout)
            {
                return;
            }

            // Subscription has timed out or otherwise failed
            timer.Stop();
            logger.Log(string.Format("Attempting to resubscribe (last event received at {0})", _lastNotificationReceived));
            Subscribe();
        }