public AzureDiscoveryFetcher()
 {
     _discovery = new AzureDiscovery(
         CloudConfiguration.SubscriptionId,
         CloudConfiguration.GetManagementCertificate());
 }
        public Task<DeploymentReference> Discover(CancellationToken cancellationToken)
        {
            var client = HttpClientFactory.Create(_subscriptionId, _certificate);
            var completionSource = new TaskCompletionSource<DeploymentReference>();
            Task<DeploymentReference> previousTask;
            var discovery = new AzureDiscovery(_subscriptionId, _certificate, _observer);

            // If we have already succeeded, just pass on the result from the last time (shortcut)
            lock (_currentDeploymentDiscoveryLock)
            {
                if (_currentDeployment != null)
                {
                    completionSource.TrySetResult(_currentDeployment);
                    return completionSource.Task;
                }

                previousTask = _currentDeploymentDiscoveryTask;
                _currentDeploymentDiscoveryTask = completionSource.Task;
            }

            // If this is the first time this is called, create a new query and return
            if (previousTask == null)
            {
                discovery.DoDiscoverDeploymentAsync(client, _deploymentPrivateId, completionSource, cancellationToken);
                completionSource.Task.ContinueRaiseSystemEventOnFault(_observer, AzureDiscovery.EventForFailedOperation);
                return completionSource.Task;
            }

            // We have already called but have not got the result yet.
            // In case there is already a task running (this is likely in our scenarios) wait for the result.
            // Retry once in case it will fail, or, more importantly, if it has already failed (the last time).
            previousTask.ContinueWith(task =>
            {
                try
                {
                    if (task.IsFaulted || (task.IsCanceled && !cancellationToken.IsCancellationRequested))
                    {
                        discovery.DoDiscoverDeploymentAsync(client, _deploymentPrivateId, completionSource, cancellationToken);
                        completionSource.Task.ContinueRaiseSystemEventOnFault(_observer, AzureDiscovery.EventForFailedOperation);
                        return;
                    }

                    if (task.IsCanceled)
                    {
                        completionSource.TrySetCanceled();
                        return;
                    }

                    completionSource.TrySetResult(task.Result);
                }
                catch (Exception exception)
                {
                    // this should never happen, so forward but do not try to handle/retry here.
                    completionSource.TrySetException(exception);
                }
            }, TaskContinuationOptions.ExecuteSynchronously);

            // NOTE: _currentDeployment may not be available yet in other continuations. This is ok.
            completionSource.Task.ContinueWith(t =>
            {
                lock (_currentDeploymentDiscoveryLock)
                {
                    _currentDeployment = t.Result;
                }
            }, TaskContinuationOptions.OnlyOnRanToCompletion);

            return completionSource.Task;
        }