コード例 #1
0
 public BrokerResponseServiceClient(IController controller, IResponseServiceCallback callback, bool useAzureQueue, AzureQueueProxy azureQueueProxy)
 {
     this.controller = controller;
     this.callback   = callback;
     if (useAzureQueue)
     {
         this.useAzureQueue   = useAzureQueue;
         this.azureQueueProxy = azureQueueProxy;
         this.sessionHash     = azureQueueProxy.SessionHash;
     }
 }
コード例 #2
0
        /// <summary>
        /// Initializes a new instance of the ControllerFrontendProvider class
        /// </summary>
        /// <param name="isSingleton">indicating whether a singleton controller class is required</param>
        /// <param name="clientManager">indicating the client manager</param>
        /// <param name="brokerAuth">indicating the broker authorization</param>
        /// <param name="observer">indicating broker observer</param>
        /// <param name="azureQueueProxy">indicating the Azure storage proxy</param>
        public ControllerFrontendProvider(bool isSingleton, BrokerClientManager clientManager, BrokerAuthorization brokerAuth, BrokerObserver observer, AzureQueueProxy azureQueueProxy)
        {
            if (isSingleton && azureQueueProxy != null)
            {
                this.singletonInstance = new BrokerController(true, clientManager, brokerAuth, observer, azureQueueProxy);
                this.cloudQueueWatcher = new BrokerWorkerControllerQueueWatcher(this.singletonInstance, azureQueueProxy.AzureStorageConnectionString, azureQueueProxy.SessionId);
            }

            this.clientManager   = clientManager;
            this.brokerAuth      = brokerAuth;
            this.observer        = observer;
            this.azureQueueProxy = azureQueueProxy;
        }
コード例 #3
0
        /// <summary>
        /// Initializes a new instance of the BrokerFrontendFactory class
        /// </summary>
        /// <param name="clientId">indicating the client id</param>
        /// <param name="binding">indicating the binding</param>
        /// <param name="info">indicating the session info</param>
        /// <param name="scheme">indicating the scheme</param>
        /// <param name="responseCallback">indicating the response callback</param>
        public HttpBrokerFrontendFactory(string clientId, Binding binding, SessionBase session, TransportScheme scheme, IResponseServiceCallback responseCallback) : base(clientId, responseCallback)
        {
            this.info    = session.Info as SessionInfo;
            this.binding = binding;
            this.scheme  = scheme;
            if (this.info.UseAzureStorage == true)
            {
                this.useAzureQueue   = true;
                this.azureQueueProxy = session.AzureQueueProxy;
            }

            if (this.info.UseInprocessBroker)
            {
                this.brokerFrontend         = this.info.InprocessBrokerAdapter.GetBrokerFrontend(responseCallback);
                this.sendRequestClient      = new SendRequestAdapter(this.brokerFrontend);
                this.brokerControllerClient = this.brokerFrontend;
                this.responseServiceClient  = this.brokerFrontend;
            }
        }
コード例 #4
0
        /// <summary>
        /// Get response from the Azure storage
        /// </summary>
        /// <param name="action">indicating the action</param>
        /// <param name="clientData">indicating the client data</param>
        /// <param name="resetToBegin">indicating the position</param>
        /// <param name="count">indicating the count</param>
        /// <param name="clientId">indicating the client id</param>
        /// <param name="sessionHash">specifying the session object hash</param>
        /// <param name="azureResponseQueueUri">return the Azure storage queue SAS Uri</param>
        /// <param name="azureResponseBlobUri">return the Azure storage blob container SAS Uri</param>
        public void GetResponsesAQ(string action, string clientData, GetResponsePosition resetToBegin, int count, string clientId, int sessionHash, out string azureResponseQueueUri, out string azureResponseBlobUri)
        {
            //create the azure response queue if not exist
            AzureQueueProxy queueProxy = this.callbackInstance as AzureQueueProxy;

            if (queueProxy == null)
            {
                BrokerTracing.TraceEvent(System.Diagnostics.TraceEventType.Error, 0, "[BrokerController] The callback instance is not AzureQueueProxy");
                azureResponseQueueUri = null;
                azureResponseBlobUri  = null;
                return;
            }

            queueProxy.AddResponseQueues(clientData, sessionHash);

            azureResponseQueueUri = queueProxy.ResponseClientUris[sessionHash].Item1;
            azureResponseBlobUri  = queueProxy.ResponseClientUris[sessionHash].Item2;

            this.GetResponses(action, clientData, resetToBegin, count, clientId);
        }
コード例 #5
0
                public AzureQueueResponseHandler(
                    AzureQueueProxy azureQueueProxy,
                    string action,
                    string clientData,
                    GetResponsePosition resetToBegin,
                    int count,
                    string clientId,
                    IResponseServiceCallback callback,
                    BrokerResponseServiceClient responseClient)
                {
                    this.action          = action;
                    this.clientData      = clientData;
                    this.resetToBegin    = resetToBegin;
                    this.count           = count;
                    this.clientId        = clientId;
                    this.callback        = callback;
                    this.responseClient  = responseClient;
                    this.azureQueueProxy = azureQueueProxy;

                    this.AzureQueueResponseThread = new Thread(new ThreadStart(this.GetResponseThread));

                    this.AzureQueueResponseThread.IsBackground = true;
                    this.AzureQueueResponseThread.Start();
                }
コード例 #6
0
        /// <summary>
        /// Build the frontend
        /// </summary>
        /// <param name="sharedData">indicating the shared data</param>
        /// <param name="observer">indicating the broker observer</param>
        /// <param name="clientManager">indicating the client manager</param>
        /// <param name="brokerAuth">indicating the broker authorization</param>
        /// <param name="bindings">indicating the bindings</param>
        /// <param name="azureQueueProxy">indicating the Azure storage proxy</param>
        /// <returns>frontend result</returns>
        public static FrontendResult BuildFrontEnd(SharedData sharedData, BrokerObserver observer, BrokerClientManager clientManager, BrokerAuthorization brokerAuth, BindingsSection bindings, AzureQueueProxy azureQueueProxy)
        {
            FrontendResult result = new FrontendResult();

            // Bug 9514: Do not open frontend for inprocess broker
            if (sharedData.StartInfo.UseInprocessBroker)
            {
                return(result);
            }

            bool flag = false;

            // Open frontend for different scheme

            // TODO: Separate HTTP frontend and Queue frontend
            if (azureQueueProxy != null)
            {
                flag = true;
                result.SetFrontendInfo(BuildHttpFrontend(sharedData, observer, clientManager, brokerAuth, bindings, azureQueueProxy), TransportScheme.Http);
            }
            else
            {
                if ((sharedData.StartInfo.TransportScheme & TransportScheme.Custom) == TransportScheme.Custom)
                {
                    flag = true;
                    result.SetFrontendInfo(BuildCustomFrontend(sharedData, observer, clientManager, brokerAuth, bindings), TransportScheme.Custom);
                }

                if ((sharedData.StartInfo.TransportScheme & TransportScheme.Http) == TransportScheme.Http)
                {
                    flag = true;
                    result.SetFrontendInfo(BuildHttpFrontend(sharedData, observer, clientManager, brokerAuth, bindings, azureQueueProxy), TransportScheme.Http);
                }

                if ((sharedData.StartInfo.TransportScheme & TransportScheme.NetTcp) == TransportScheme.NetTcp)
                {
                    flag = true;
                    result.SetFrontendInfo(BuildNetTcpFrontend(sharedData, observer, clientManager, brokerAuth, bindings), TransportScheme.NetTcp);
                }

                if ((sharedData.StartInfo.TransportScheme & TransportScheme.NetHttp) == TransportScheme.NetHttp)
                {
                    flag = true;
                    result.SetFrontendInfo(BuildNetHttpFrontend(sharedData, observer, clientManager, brokerAuth, bindings), TransportScheme.NetHttp);
                }
            }

            if (!flag)
            {
                BrokerTracing.TraceEvent(TraceEventType.Critical, 0, "[FrontEndBuilder] Invalid transport scheme: {0}", sharedData.StartInfo.TransportScheme);
                ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_NotSupportedTransportScheme, SR.NotSupportedTransportScheme, sharedData.StartInfo.TransportScheme.ToString());
            }

            return(result);
        }
コード例 #7
0
        /// <summary>
        /// Build the http frontend
        /// </summary>
        /// <param name="sharedData">indicating the shared data</param>
        /// <param name="observer">indicating the broker observer</param>
        /// <param name="clientManager">indicating the client manager</param>
        /// <param name="brokerAuth">indicating the broker authorization</param>
        /// <param name="bindings">indicating the bindings</param>
        /// <returns>frontend info</returns>
        private static FrontendInfo BuildHttpFrontend(SharedData sharedData, BrokerObserver observer, BrokerClientManager clientManager, BrokerAuthorization brokerAuth, BindingsSection bindings, AzureQueueProxy azureQueueProxy)
        {
            FrontendInfo result = new FrontendInfo();

            BrokerTracing.TraceVerbose("[FrontEndBuilder] Start building http frontend...");

            // Get binding from configuration file
            Binding binding = BindingHelper.GetBinding(TransportScheme.Http, sharedData.StartInfo.Secure, bindings);

            // Sync frontend binding.receiveTimeout with loadBalancing.ServiceOperationTimeout if its enabled (>0)
            int serviceOperationTimeout = sharedData.Config.LoadBalancing.ServiceOperationTimeout;

            if (serviceOperationTimeout > 0)
            {
                binding.SendTimeout = TimeSpan.FromMilliseconds(serviceOperationTimeout);
            }

            // Set frontend binding.ReceiveTimeout to max
            binding.ReceiveTimeout = TimeSpan.MaxValue;

            // Get message size and reader quotas
            int maxMessageSize = sharedData.ServiceConfig.MaxMessageSize;

            if (maxMessageSize > 0)
            {
                BindingHelper.ApplyMaxMessageSize(binding, maxMessageSize);
                result.MaxMessageSize = maxMessageSize;
                BrokerTracing.TraceVerbose("[FrontEndBuilder] Build frontend: Step 1: Apply global MaxMessageSize:{0}\n", result.MaxMessageSize);
            }
            else
            {
                BindingElementCollection collection = binding.CreateBindingElements();
                result.MaxMessageSize = collection.Find <TransportBindingElement>().MaxReceivedMessageSize;
                result.ReaderQuotas   = binding.GetProperty <XmlDictionaryReaderQuotas>(new BindingParameterCollection());

                StringBuilder sb = new StringBuilder();
                BrokerTracing.WriteProperties(sb, result.ReaderQuotas, 3, typeof(int));
                BrokerTracing.TraceVerbose("[FrontEndBuilder] Build frontend: Step 1: Load binding data:\nMaxMessageSize = {0}\n[ReaderQuotas]\n{1}", result.MaxMessageSize, sb.ToString());
            }

            result.Binding = binding;
            BrokerTracing.EtwTrace.LogFrontendBindingLoaded(
                sharedData.BrokerInfo.SessionId,
                "Http",
                result.MaxMessageSize,
                binding.ReceiveTimeout.Ticks,
                binding.SendTimeout.Ticks,
                binding.MessageVersion.ToString(),
                binding.Scheme);

            // Generate the http uri
            Uri basehttpUri = sharedData.Config.Services.GetBrokerBaseAddress(sharedData.StartInfo.Secure ? HttpsScheme : HttpScheme);

            if (basehttpUri == null)
            {
                basehttpUri = new Uri(sharedData.StartInfo.Secure ? DefaultHttpsFrontEndServiceUri : DefaultHttpFrontEndServiceUri);
            }

            BrokerTracing.TraceVerbose("[FrontEndBuilder] Build frontend: Step 2: Load base address: {0}", basehttpUri);

            Uri brokerHttpUri = ApplySessionId(basehttpUri, sharedData.BrokerInfo.SessionId, "Http", sharedData.BrokerInfo.EnableFQDN);

            BrokerTracing.TraceVerbose("[FrontEndBuilder] Build frontend: Step 3: Generate broker uri: {0}", brokerHttpUri);

            // Build the frontend
            if (sharedData.StartInfo.UseAzureStorage == true)
            {
                BrokerTracing.TraceVerbose("[FrontEndBuilder] Build frontend: AzureQueueFrontEnd");
                result.FrontEnd = new AzureQueueFrontEnd(azureQueueProxy, brokerHttpUri, observer, clientManager, brokerAuth, sharedData);
            }
            else
            {
                BrokerTracing.TraceVerbose("[FrontEndBuilder] Build frontend: HttpFrontEnd");
                result.FrontEnd = new RequestReplyFrontEnd <IReplyChannel>(brokerHttpUri, binding, observer, clientManager, brokerAuth, sharedData);
                //result.FrontEnd = new OutputInputFrontEnd<IInputChannel>(brokerHttpUri, binding, observer, clientManager, brokerAuth, sharedData);
            }
            BrokerTracing.TraceVerbose("[FrontEndBuilder] Build frontend: Step 4: Build broker frontend succeeded.");
            BrokerTracing.EtwTrace.LogFrontendCreated(
                sharedData.BrokerInfo.SessionId,
                "Http",
                result.FrontEnd.ListenUri);

            Uri controllerHttpUri = ApplySessionId(basehttpUri, sharedData.BrokerInfo.SessionId, "Http", sharedData.BrokerInfo.EnableFQDN);

            BrokerTracing.TraceVerbose("[FrontEndBuilder] Build frontend: Step 5: Generate controller base address: {0}", controllerHttpUri);

            // Bug 3012: Force the http frontend using the singleton instance
            result.ControllerFrontend = new ServiceHost(typeof(BrokerController), controllerHttpUri);
            BindingHelper.ApplyDefaultThrottlingBehavior(result.ControllerFrontend);
            ServiceBehaviorAttribute behavior = result.ControllerFrontend.Description.Behaviors.Find <ServiceBehaviorAttribute>();

            Debug.Assert(behavior != null, "BrokerController must have a behavior.");
            behavior.InstanceContextMode = InstanceContextMode.Single;
            ServiceEndpoint endpoint = result.ControllerFrontend.AddServiceEndpoint(typeof(IController), binding, DefaultControllerPostfix);

            if (sharedData.StartInfo.UseAzureStorage == true)
            {
                endpoint.Behaviors.Add(new ControllerFrontendProvider(true, clientManager, brokerAuth, observer, azureQueueProxy));
            }
            else
            {
                endpoint.Behaviors.Add(new ControllerFrontendProvider(true, clientManager, brokerAuth, observer, null));
            }
            result.ControllerUri = endpoint.ListenUri.AbsoluteUri;
            BrokerTracing.TraceVerbose("[FrontEndBuilder] Build frontend: Step 6: Build controller frontend succeeded: ControllerUri = {0}", result.ControllerUri);

            result.GetResponseUri = null;

            BrokerTracing.TraceVerbose("[FrontEndBuilder] Building http frontend succeeded.");
            BrokerTracing.EtwTrace.LogFrontendControllerCreated(
                sharedData.BrokerInfo.SessionId,
                "Http",
                result.ControllerUri,
                String.Empty);
            return(result);
        }
コード例 #8
0
        /// <summary>
        /// Run the broker
        /// </summary>
        /// <param name="startInfo">session start info</param>
        /// <param name="brokerInfo">indicate the broker start info</param>
        /// <returns>initialization result</returns>
        public BrokerInitializationResult Run(SessionStartInfoContract startInfo, BrokerStartInfo brokerInfo)
        {
            BrokerTracing.TraceEvent(System.Diagnostics.TraceEventType.Information, 0, "[BrokerEntry] Broker is starting initialization, ID = {0}", brokerInfo.SessionId);

            try
            {
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: ClusterTopology is {0}", brokerInfo.NetworkTopology);

                // Step 1: Initialize configuration and shared data
                ServiceConfiguration serviceConfig;
                BrokerConfigurations brokerConfig;
                BindingsSection      bindings;
                SoaCommonConfig.WithoutSessionLayer = startInfo.IsNoSession; // TODO: this is a hack. Working mode should be decided by something like a *SchedulerType* filed.

                ConfigurationHelper.LoadConfiguration(startInfo, brokerInfo, out brokerConfig, out serviceConfig, out bindings);
                this.sharedData = new SharedData(brokerInfo, startInfo, brokerConfig, serviceConfig);
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 1: Loading configuration and shared data succeeded.");
                Debug.WriteLine($"[BrokerEntry](Debug) UseAad:{startInfo.UseAad}");

                // Step 2: Initialize broker queue
                ClientInfo[] clientInfo;
                this.brokerQueueFactory = BrokerEntry.InitBrokerQueue(this.sharedData, out clientInfo);
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 2: Initialize broker queue succeeded.");

                // Step 3: Initialize observer
                this.observer            = new BrokerObserver(this.sharedData, clientInfo);
                this.sharedData.Observer = this.observer;
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 3: Initialize broker observer succeeded.");

                // Step 4: Initialize state manager
                this.stateManager = new BrokerStateManager(this.sharedData, clientInfo.Length != 0);
                this.stateManager.UnloadBroker += this.UnloadBroker;
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 4: Initialize broker state manager succeeded.");

                // Step 5: Initialize service job monitor
                var context = TelepathyContext.GetOrAdd(this.sharedData.BrokerInfo.Headnode);

                if (SoaCommonConfig.WithoutSessionLayer)
                {
                    this.monitor = new DummyServiceJobMonitor(this.sharedData, this.stateManager, this.nodeMappingData, context);
                }
                else
                {
                    this.monitor = new ServiceJobMonitor.ServiceJobMonitor(this.sharedData, this.stateManager, this.nodeMappingData, context);
                }
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 5: Initialize service job monitor succeeded.");

                // Step 6: Initalize broker authorization
                this.brokerAuth = BrokerEntry.BuildBrokerAuthorization(this.sharedData);
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 6: Initialize broker authorization succeeded.");

                // Step 7: Initialize dispatcher manager
                DispatcherManager dispatcherManager = new DispatcherManager(bindings, this.sharedData, this.observer, this.monitor, this.brokerQueueFactory, context);
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 7: Initialize dispatcher manager succeeded.");

                // Step 8: Start service job monitor
                this.monitor.Start(startInfo, dispatcherManager, this.observer).GetAwaiter().GetResult();
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 8: Start service job monitor succeeded.");

                // Step 9: Initailize client manager
                this.clientManager = new BrokerClientManager(clientInfo, this.brokerQueueFactory, this.observer, this.stateManager, this.monitor, this.sharedData);
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 9: Initialize client manager succeeded.");

                // if using AzureQueue, retrieve the connection string and build the request and response message queues if not exist
                string[] requestQueueUris           = { };
                string   requestBlobUri             = string.Empty;
                string   controllerRequestQueueUri  = string.Empty;
                string   controllerResponseQueueUri = string.Empty;
                if (startInfo.UseAzureStorage)
                {
                    int clusterHash = 0;
                    if (!string.IsNullOrEmpty(brokerInfo.ClusterId))
                    {
                        string clusterIdString = brokerInfo.ClusterId.ToLowerInvariant();
                        clusterHash = clusterIdString.GetHashCode();
                    }
                    else if (!string.IsNullOrEmpty(brokerInfo.ClusterName))
                    {
                        string clusterNameString = brokerInfo.ClusterName.ToLowerInvariant();
                        clusterHash = clusterNameString.GetHashCode();
                    }
                    else
                    {
                        throw new InvalidOperationException($"Both {nameof(brokerInfo.ClusterId)} and {nameof(brokerInfo.ClusterName)} are null or empty. No {nameof(clusterHash)} can be determined.");
                    }

                    if (!string.IsNullOrEmpty(brokerInfo.AzureStorageConnectionString))
                    {
                        this.azureQueueProxy = new AzureQueueProxy(brokerInfo.ClusterName, clusterHash, this.SessionId, brokerInfo.AzureStorageConnectionString);
                        requestQueueUris     = this.azureQueueProxy.RequestQueueUris;
                        requestBlobUri       = this.azureQueueProxy.RequestBlobUri;
                        var requestQName  = CloudQueueConstants.GetBrokerWorkerControllerRequestQueueName(this.SessionId);
                        var responseQName = CloudQueueConstants.GetBrokerWorkerControllerResponseQueueName(this.SessionId);
                        controllerRequestQueueUri = CloudQueueCreationModule.CreateCloudQueueAndGetSas(
                            brokerInfo.AzureStorageConnectionString,
                            requestQName,
                            CloudQueueCreationModule.AddMessageSasPolicy).GetAwaiter().GetResult();
                        controllerResponseQueueUri = CloudQueueCreationModule.CreateCloudQueueAndGetSas(
                            brokerInfo.AzureStorageConnectionString,
                            responseQName,
                            CloudQueueCreationModule.ProcessMessageSasPolicy).GetAwaiter().GetResult();
                        if (this.SessionId == SessionStartInfo.StandaloneSessionId)
                        {
                            CloudQueueCreationModule.ClearCloudQueuesAsync(brokerInfo.AzureStorageConnectionString, new[] { requestQName, responseQName });
                        }
                    }
                    else
                    {
                        BrokerTracing.TraceError("[BrokerEntry] Initialization: Use Azure Queue is specified, however the Azure connection string is not set.");
                        ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_AzureConnectionStringNotAvailable, SR.Broker_AzureConnectionStringNotAvailable);
                    }
                }

                // Step 10: Initialize frontend
                this.frontendResult = FrontEndBuilder.BuildFrontEnd(this.sharedData, this.observer, this.clientManager, this.brokerAuth, bindings, this.azureQueueProxy);
                ////this.maxMessageSize = (int)this.frontendResult.MaxMessageSize;
                ////this.readerQuotas = this.frontendResult.ReaderQuotas;
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 10: Initialize frontend succeeded.");

                // Step 11: Start frontend, Initialization finished after this step
                this.OpenFrontend();
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 11: Open frontend succeeded.");

                // Step 12: Build initialization result and retrun to client
                BrokerInitializationResult result = BrokerEntry.BuildInitializationResult(
                    this.frontendResult,
                    dispatcherManager,
                    this.sharedData.Config.LoadBalancing.ServiceOperationTimeout,
                    this.sharedData.Config.Monitor.ClientBrokerHeartbeatInterval,
                    this.sharedData.Config.Monitor.ClientBrokerHeartbeatRetryCount,
                    requestQueueUris,
                    requestBlobUri,
                    controllerRequestQueueUri,
                    controllerResponseQueueUri,
                    startInfo.UseAzureStorage);
                BrokerTracing.TraceVerbose("[BrokerEntry] Initialization: Step 12: Build initialization result suceeded.");
                BrokerTracing.TraceInfo("[BrokerEntry] Initialization succeeded.");
                return(result);
            }
            catch (Exception ex)
            {
                BrokerTracing.TraceError(ex.ToString());
                throw;
            }
            finally
            {
                if (this.sharedData != null)
                {
                    this.sharedData.InitializationFinished();
                }
            }
        }
コード例 #9
0
 /// <summary>
 /// Initializes a new instance of the BrokerController class
 /// </summary>
 /// <param name="isSingleton">indicating whether the BrokerController is a singleton</param>
 /// <param name="clientManager">indicating the client manager</param>
 /// <param name="brokerAuth">indicating the broker authorization</param>
 /// <param name="observer">indicating broker observer</param>
 /// <param name="azureQueueProxy">the Azure storage proxy</param>
 public BrokerController(bool isSingleton, BrokerClientManager clientManager, BrokerAuthorization brokerAuth, BrokerObserver observer, AzureQueueProxy azureQueueProxy)
 {
     this.isSingleton      = isSingleton;
     this.clientManager    = clientManager;
     this.brokerAuth       = brokerAuth;
     this.observer         = observer;
     this.callbackInstance = azureQueueProxy;
 }
コード例 #10
0
 /// <summary>
 /// Initializes a new instance of the AzureQueueFrontEnd class
 /// </summary>
 /// <param name="listenUri">uri the frontend listen to</param>
 /// <param name="binding">binding that the frontend uses</param>
 public AzureQueueFrontEnd(AzureQueueProxy proxy, Uri listenUri, BrokerObserver observer, BrokerClientManager clientManager, BrokerAuthorization brokerAuth, SharedData sharedData)
     : base(listenUri.AbsoluteUri, observer, clientManager, brokerAuth, sharedData)
 {
     this.azureQueueProxy = proxy;
     this.receiveRequest  = new BasicCallbackReferencedThreadHelper <IAsyncResult>(this.ReceiveRequest, this).CallbackRoot;
 }