Beispiel #1
0
 /// <summary>
 /// Creates a new instance of the inter-role communication event with the specified payload and deployment ID, role name and role instance ID that identify the recipient.
 /// </summary>
 /// <param name="payload">The event payload.</param>
 /// <param name="deploymentID">The deployment ID identifying a hosted service in which the recipients for the inter-role communication event are deployed.</param>
 /// <param name="roleName">The name identifying a role to which inter-role communication event recipient belong.</param>
 /// <param name="roleInstanceID">The role instance ID uniquely identifying a particular recipient of the inter-role communication event.</param>
 public InterRoleCommunicationEvent(object payload, string deploymentID = null, string roleName = null, string roleInstanceID = null) : this(payload)
 {
     // Check of role instance ID was specified.
     if (!String.IsNullOrEmpty(roleInstanceID))
     {
         // If role instance ID is specified, use a combination of deployment ID and role instance ID to determine where to send.
         To = FrameworkUtility.GetHashedValue(deploymentID ?? CloudEnvironment.DeploymentId, roleInstanceID);
     }
     else if (!String.IsNullOrEmpty(roleName))
     {
         // If role instance ID is not provided but name was specified instead, assume that the event is to be sent to all instances of a particular role.
         To = FrameworkUtility.GetHashedValue(deploymentID ?? CloudEnvironment.DeploymentId, roleName);
     }
     // Otherwise, treat this event as a multicast event and do not set the To property.
 }
Beispiel #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="InterRoleCommunicationExtension"/> object with default settings.
 /// </summary>
 public InterRoleCommunicationExtension()
 {
     // Initialize internal fields.
     this.settings         = InterRoleCommunicationSettings.Default;
     this.senderInstanceID = FrameworkUtility.GetHashedValue(CloudEnvironment.DeploymentId, CloudEnvironment.CurrentRoleInstanceId);
 }
Beispiel #3
0
        /// <summary>
        /// Initializes a new instance of a <see cref="InterRoleCommunicationExtension"/> object with the specified Service Bus topic endpoint and custom settings.
        /// </summary>
        /// <param name="serviceBusEndpoint">The Service Bus topic endpoint using which this component will be providing inter-role communication.</param>
        /// <param name="settings">The <see cref="InterRoleCommunicationSettings"/> object containing behavioral and runtime settings for the inter-role communication component.</param>
        public InterRoleCommunicationExtension(ServiceBusEndpointInfo serviceBusEndpoint, InterRoleCommunicationSettings settings)
        {
            Guard.ArgumentNotNull(serviceBusEndpoint, "serviceBusEndpoint");
            Guard.ArgumentNotNull(settings, "settings");
            Guard.ArgumentNotNullOrEmptyString(serviceBusEndpoint.TopicName, "serviceBusEndpoint.TopicName");

            // Initialize internal fields.
            this.settings           = settings;
            this.serviceBusEndpoint = serviceBusEndpoint;
            this.retryPolicy        = this.settings.RetryPolicy ?? RetryPolicy.NoRetry;
            this.senderRoleID       = FrameworkUtility.GetHashedValue(CloudEnvironment.DeploymentId, CloudEnvironment.CurrentRoleName);
            this.senderInstanceID   = FrameworkUtility.GetHashedValue(CloudEnvironment.DeploymentId, CloudEnvironment.CurrentRoleInstanceId);

            // Configure Service Bus credentials and service namespace URI.
            var credentials = TokenProvider.CreateSharedSecretTokenProvider(serviceBusEndpoint.IssuerName, serviceBusEndpoint.IssuerSecret);
            var address     = ServiceBusEnvironment.CreateServiceUri("sb", serviceBusEndpoint.ServiceNamespace, String.Empty);

            // Configure Service Bus messaging factory and namespace client which is required for subscription management.
            this.messagingFactory = MessagingFactory.Create(address, credentials);
            this.nsManager        = new NamespaceManager(address, credentials);

            // Figure out the name of the subscription. If subscription name was specified in the endpoint definition, treat it as static.
            // If no subscription name was specified, assign a globally unique name based on hashed deployment ID and role instance ID values.
            this.useStaticSubscription = !String.IsNullOrEmpty(serviceBusEndpoint.SubscriptionName);
            this.ircSubscriptionName   = this.useStaticSubscription ? serviceBusEndpoint.SubscriptionName : (this.settings.UseCompetingConsumers ? String.Concat(SubscriptionNamePrefix, this.senderRoleID) : String.Concat(SubscriptionNamePrefix, this.senderInstanceID));

            // Configure the underlying messaging entities such as topic and subscription.
            ConfigureTopicClient(this.serviceBusEndpoint.TopicName);
            ConfigureSubscriptionClient(this.ircSubscriptionName);

            // Configure a fault handler for the receive action.
            this.receiveFaultAction = ((msg, ex) =>
            {
                // Log an error.
                TraceManager.ServiceComponent.TraceError(ex);

                try
                {
                    if (msg != null)
                    {
                        // Abandons a brokered message. This will cause Service Bus to unlock the message and make it available to be received again,
                        // either by the same consumer or by another completing consumer.
                        msg.Abandon(this.retryPolicy);
                    }
                }
                catch (MessageLockLostException)
                {
                    // It's too late to compensate the loss of a message lock. Should just ignore it so that it does not break the receive loop.
                }
                catch (CommunicationObjectAbortedException)
                {
                    // There is nothing we can do as connection might have been lost or underlying topic/subscription might have been removed.
                }
                catch (CommunicationObjectFaultedException)
                {
                    // If Abandon fail with this exception, the only recourse is to Receive another message (possibly the same one).
                }
            });

            // Configure event receive action.
            this.receiveAction = (() =>
            {
                BrokeredMessage msg = null;
                bool completedAsync = false;

                this.retryPolicy.ExecuteAction(() =>
                {
                    // Make sure we are not told to stop receiving while we are retrying.
                    if (!cts.IsCancellationRequested)
                    {
#if PERF_TEST
                        Stopwatch watch = Stopwatch.StartNew();
#endif
                        if ((msg = this.subscriptionClient.Receive(this.settings.EventWaitTimeout)) != null)
                        {
#if PERF_TEST
                            watch.Stop();
                            TraceManager.ServiceComponent.TraceDetails("Waited for a new event for {0}ms", watch.ElapsedMilliseconds);
#endif
                            try
                            {
                                // Make sure we are not told to stop receiving while we were waiting for a new message.
                                if (!this.cts.IsCancellationRequested)
                                {
                                    if (this.settings.EnableAsyncDispatch)
                                    {
                                        // Invoke the dispatch action asynchronously.
                                        this.dispatchAction.BeginInvoke(msg, this.endDispatch, msg);

                                        completedAsync = true;
                                    }
                                    else
                                    {
                                        // Invoke the dispatch action synchronously.
                                        this.dispatchAction(msg);

                                        // Mark brokered message as complete.
                                        msg.Complete(this.retryPolicy);
                                    }
                                }
                                else
                                {
                                    // If we were told to stop processing, the current message needs to be unlocked and return back to the queue.
                                    msg.Abandon(this.retryPolicy);
                                }
                            }
                            catch (Exception ex)
                            {
                                this.receiveFaultAction(msg, ex);
                            }
                            finally
                            {
                                // Do not attempt to dispose a BrokeredMessage instance if it was dispatched for processing asynchronously.
                                if (msg != null && !completedAsync)
                                {
                                    // Ensure that any resources allocated by a BrokeredMessage instance are released.
                                    msg.Dispose();
                                }
                            }
                        }
                    }
                });
            });

            // Configure event receive complete action.
            this.endReceive = ((ar) =>
            {
                try
                {
                    this.receiveAction.EndInvoke(ar);
                }
                catch (Exception ex)
                {
                    // Log this error. Do not allow an unhandled exception to kill the current process.
                    TraceManager.ServiceComponent.TraceError(ex);
                }

                if (!cts.IsCancellationRequested)
                {
                    this.receiveHandle = this.receiveAction.BeginInvoke(this.endReceive, null);
                }
            });

            // Configure event dispatch action. This action is performed when notifying subscribers about a new IRC event.
            this.dispatchAction = ((msg) =>
            {
                // Extract the event data from brokered message.
                InterRoleCommunicationEvent e = msg.GetBody <InterRoleCommunicationEvent>(this.serializer);

                // Notify all registered subscribers.
                NotifySubscribers(e);
            });

            this.endDispatch = ((ar) =>
            {
                BrokeredMessage msg = null;

                try
                {
                    msg = ar.AsyncState as BrokeredMessage;
                    this.dispatchAction.EndInvoke(ar);

                    if (msg != null)
                    {
                        // Mark brokered message as complete.
                        msg.Complete(this.retryPolicy);
                    }
                }
                catch (Exception ex)
                {
                    this.receiveFaultAction(msg, ex);
                }
                finally
                {
                    if (msg != null)
                    {
                        // Ensure that any resources allocated by a BrokeredMessage instance are released.
                        msg.Dispose();
                    }
                }
            });
        }
Beispiel #4
0
 /// <summary>
 /// Creates a new instance of the multicast inter-role communication event with the specified payload.
 /// </summary>
 /// <param name="payload">The event payload.</param>
 public InterRoleCommunicationEvent(object payload)
 {
     From       = FrameworkUtility.GetHashedValue(CloudEnvironment.DeploymentId, CloudEnvironment.CurrentRoleInstanceId);
     Properties = new Dictionary <string, object>();
     Payload    = payload;
 }
Beispiel #5
0
        /// <summary>
        /// Constructs and returns a queue name that is unique for the specified instance ID and is safe to be used as a name for the Windows Azure Service Bus Message Buffer.
        /// </summary>
        /// <param name="instanceId">A string that uniquely and reliably identifies the process in which the OnPremisesBufferedTraceListener trace listener is running.</param>
        /// <returns>The constructed queue name.</returns>
        private static string GetServiceBusQueueName(string instanceId)
        {
            Guard.ArgumentNotNullOrEmptyString(instanceId, "instanceId");

            return(CloudUtility.CleanupContainerName(String.Concat(Resources.OnPremisesBufferedTraceListenerQueueName, "-", FrameworkUtility.GetHashedValue(instanceId)).ToLowerInvariant()));
        }