internal async Task ValidateHostIdUsageAsync(string hostId)
        {
            try
            {
                if (!_azureBlobStorageProvider.TryCreateHostingBlobContainerClient(out var blobContainerClient))
                {
                    return;
                }

                HostIdInfo hostIdInfo = await ReadHostIdInfoAsync(hostId, blobContainerClient);

                if (hostIdInfo != null)
                {
                    // an existing record exists for this host ID
                    CheckForCollision(hostId, hostIdInfo);
                }
                else
                {
                    // no existing record, so write one, claiming this host ID for this host name
                    // in this storage account
                    hostIdInfo = new HostIdInfo
                    {
                        Hostname = _hostNameProvider.Value
                    };
                    await WriteHostIdAsync(hostId, hostIdInfo, blobContainerClient);
                }
            }
            catch (Exception ex)
            {
                // best effort - log error and continue
                _logger.LogError(ex, "Error validating host ID usage.");
            }
        }
        internal async Task WriteHostIdAsync(string hostId, HostIdInfo hostIdInfo, BlobContainerClient blobContainerClient)
        {
            try
            {
                string     blobPath   = string.Format(BlobPathFormat, hostId);
                BlobClient blobClient = blobContainerClient.GetBlobClient(blobPath);
                BinaryData data       = BinaryData.FromObjectAsJson(hostIdInfo);
                await blobClient.UploadAsync(data);

                _logger.LogDebug($"Host ID record written (ID:{hostId}, HostName:{hostIdInfo.Hostname})");
            }
            catch (RequestFailedException rfex) when(rfex.Status == 409)
            {
                // Another instance wrote the blob between the time when we initially
                // checked and when we attempted to write. Read the blob and validate it.
                hostIdInfo = await ReadHostIdInfoAsync(hostId, blobContainerClient);

                if (hostIdInfo != null)
                {
                    CheckForCollision(hostId, hostIdInfo);
                }
            }
            catch (Exception ex)
            {
                // best effort
                _logger.LogError(ex, "Error writing host ID info");
            }
        }
        internal async Task <HostIdInfo> ReadHostIdInfoAsync(string hostId, BlobContainerClient blobContainerClient)
        {
            HostIdInfo hostIdInfo = null;

            try
            {
                // check storage to see if a record already exists for this host ID
                string     blobPath         = string.Format(BlobPathFormat, hostId);
                BlobClient blobClient       = blobContainerClient.GetBlobClient(blobPath);
                var        downloadResponse = await blobClient.DownloadAsync();

                string content;
                using (StreamReader reader = new StreamReader(downloadResponse.Value.Content))
                {
                    content = reader.ReadToEnd();
                }

                if (!string.IsNullOrEmpty(content))
                {
                    hostIdInfo = JsonConvert.DeserializeObject <HostIdInfo>(content);
                }
            }
            catch (RequestFailedException exception) when(exception.Status == 404)
            {
                // no record stored for this host ID
            }
            catch (Exception ex)
            {
                // best effort
                _logger.LogError(ex, "Error reading host ID info");
            }

            return(hostIdInfo);
        }
 private void CheckForCollision(string hostId, HostIdInfo hostIdInfo)
 {
     // verify the host name is the same as our host name
     if (!string.Equals(_hostNameProvider.Value, hostIdInfo.Hostname, StringComparison.OrdinalIgnoreCase))
     {
         HandleCollision(hostId);
     }
 }