Beispiel #1
0
        /// <summary>
        /// Initializes a new instance of the type
        /// </summary>
        /// <param name="logger">The logger to write debugging and diagnostics information to</param>
        /// <param name="metricFactory">The factory to create metric recorders from</param>
        /// <param name="consumerGroupName">The name of the consumer group that the processor is associated with</param>
        /// <param name="storageAccount">The storage account used to access the Azure BLOB store</param>
        /// <param name="containerName">The name of the container that the BLOBs are contained in</param>
        /// <param name="subContainerPrefix">The prefix for the BLOB container</param>
        public AzureStorageEpochRecorder(ILogger logger, IMetricFactory metricFactory, string consumerGroupName, CloudStorageAccount storageAccount, string containerName, string subContainerPrefix)
        {
            Guard.NotNullOrWhitespace(nameof(consumerGroupName), consumerGroupName);
            Guard.NotNull(nameof(storageAccount), storageAccount);
            Guard.NotNull(nameof(logger), logger);
            AzureBlobCommon.ValidContainerName(nameof(containerName), containerName);

            _logger = logger;

            using (_logger.BeginScope("Azure Storage Lease Manager::ctor"))
            {
                _logger.LogInformation("Creating Azure lease manager for consumer group {consumerGroupName}, container {containerName}", containerName, consumerGroupName);

                subContainerPrefix = (subContainerPrefix != null) ? subContainerPrefix.Trim() : "";

                var storageClient = storageAccount.CreateCloudBlobClient();

                storageClient.DefaultRequestOptions = new BlobRequestOptions {
                    MaximumExecutionTime = TimeSpan.FromSeconds(60)
                };
                _epochStoreContainer    = storageClient.GetContainerReference(containerName);
                _consumerGroupDirectory = _epochStoreContainer.GetDirectoryReference($"{subContainerPrefix}{consumerGroupName}");

                _epochReadCounter          = metricFactory.CreateCounter("aer-checkpoint-read", "The number of times that the Azure Storage epoch recorder has read the epoch", false, new string[0]);
                _epochUpdateCounter        = metricFactory.CreateCounter("aer-checkpoint-update", "The number of times that the Azure Storage epoch recorder has updated the epoch", false, new string[0]);
                _epochErrorCounter         = metricFactory.CreateCounter("aer-checkpoint-error", "The number of times that the Azure Storage epoch recorder has errors raised", false, new string[0]);
                _storagePerformanceSummary = metricFactory.CreateSummary("aer-storage-timing", "The duration taken to access Azure Storage to perform checkpoint recorder operations", 10, false, new string[0]);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Renews the lease
        /// </summary>
        /// <param name="lease">The lease to renew</param>
        /// <returns>True if the lease is renewed successfully</returns>
        private async Task <bool> RenewLeaseCoreAsync(AzureBlobLease lease)
        {
            CloudBlockBlob leaseBlob   = lease.Blob;
            string         partitionId = lease.PartitionId;

            using (_logger.BeginScope("Renew Lease Core"))
            {
                try
                {
                    _logger.LogDebug("Core renewal for partition {partitionId}", lease.PartitionId);

                    using (_storagePerformanceSummary.Time())
                    {
                        await leaseBlob.RenewLeaseAsync(AccessCondition.GenerateLeaseCondition(lease.Token), _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                    }

                    _logger.LogDebug("Core renewal completed for partition {partitionId}", lease.PartitionId);
                }
                catch (StorageException e)
                {
                    var se = AzureBlobCommon.CheckForLeaseLostException(partitionId, e, _logger);

                    _logger.LogError(se, "Renewing lease failed for partition {partitionId}", lease.PartitionId);
                    throw se;
                }
            }

            return(true);
        }
Beispiel #3
0
        /// <inheritdoc />
        public async Task <bool> ReleaseLeaseAsync(Lease lease)
        {
            using (_logger.BeginScope("Renew Lease"))
            {
                _logger.LogInformation("Releasing lease: Partition Id: {partitionId}", lease.PartitionId);

                AzureBlobLease azureLease  = lease as AzureBlobLease;
                CloudBlockBlob leaseBlob   = azureLease.Blob;
                string         partitionId = azureLease.PartitionId;

                try
                {
                    string         leaseId      = lease.Token;
                    AzureBlobLease releasedCopy = new AzureBlobLease(azureLease, leaseBlob)
                    {
                        Token = string.Empty,
                        Owner = string.Empty
                    };

                    leaseBlob.Metadata.Remove(MetaDataOwnerName);
                    _logger.LogDebug("Setting metadata for partition {partitionId}", partitionId);

                    using (_storagePerformanceSummary.Time())
                    {
                        await leaseBlob.SetMetadataAsync(AccessCondition.GenerateLeaseCondition(leaseId), _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                    }

                    _logger.LogDebug("Uploading lease data for partition {partitionId}", partitionId);

                    using (_storagePerformanceSummary.Time())
                    {
                        await leaseBlob.UploadTextAsync(JsonConvert.SerializeObject(releasedCopy), _leaseEncoding, AccessCondition.GenerateLeaseCondition(leaseId), _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                    }

                    _logger.LogDebug("Release the lease for for partition {partitionId}", partitionId);

                    using (_storagePerformanceSummary.Time())
                    {
                        await leaseBlob.ReleaseLeaseAsync(AccessCondition.GenerateLeaseCondition(leaseId), _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                    }
                }
                catch (StorageException e)
                {
                    var se = AzureBlobCommon.CheckForLeaseLostException(partitionId, e, _logger);

                    _logger.LogError(se, "Error releasing lease for partition {partitionId}", lease.PartitionId);
                    throw se;
                }
            }

            return(true);
        }
Beispiel #4
0
        /// <summary>
        /// Updates the lease
        /// </summary>
        /// <param name="lease">The lease to update</param>
        /// <returns>True if updated successfully</returns>
        private async Task <bool> UpdateLeaseCoreAsync(AzureBlobLease lease)
        {
            var success = false;

            if (lease != null && !string.IsNullOrEmpty(lease.Token))
            {
            }
            else
            {
                success = true;

                _logger.LogInformation("Updating lease: Partition Id: {partitionId}", lease.PartitionId);

                string partitionId = lease.PartitionId;
                string token       = lease.Token;

                CloudBlockBlob leaseBlob = lease.Blob;

                try
                {
                    string jsonToUpload = JsonConvert.SerializeObject(lease);
                    _logger.LogInformation("Updating lease: Partition Id: {partitionId}, RawJson: {json}", lease.PartitionId, jsonToUpload);

                    using (_storagePerformanceSummary.Time())
                    {
                        await leaseBlob.UploadTextAsync(jsonToUpload, _leaseEncoding, AccessCondition.GenerateLeaseCondition(token), _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                    }

                    _logger.LogDebug("Updated lease: Partition Id: {partitionId}", lease.PartitionId);
                }
                catch (StorageException e)
                {
                    var se = AzureBlobCommon.CheckForLeaseLostException(partitionId, e, _logger);

                    _logger.LogError(se, "Updating lease for partition {partitionId}", lease.PartitionId);

                    throw se;
                }
            }

            return(success);
        }
        /// <summary>
        /// Initializes a new instance of the type
        /// </summary>
        /// <param name="logger">The logger to write debugging and diagnostics information to</param>
        /// <param name="metricFactory">The factory to create metric recorders from</param>
        /// <param name="storageAccount">The storage account used to access the Azure BLOB store</param>
        /// <param name="containerName">The name of the container that the BLOBs are contained in</param>
        /// <param name="subContainerPrefix">The prefix for the BLOB container</param>
        public AzureStorageCheckpointManager(ILogger logger, IMetricFactory metricFactory, CloudStorageAccount storageAccount, string containerName, string subContainerPrefix)
        {
            Guard.NotNull(nameof(storageAccount), storageAccount);
            Guard.NotNull(nameof(logger), logger);
            AzureBlobCommon.ValidContainerName(nameof(containerName), containerName);

            _logger = logger;

            using (_logger.BeginScope("Azure Storage Checkpoint Manager::ctor"))
            {
                _logger.LogInformation("Creating Azure storage checkpoint manager for container {containerName}", containerName);
                _containerName      = containerName;
                _subContainerPrefix = (subContainerPrefix != null) ? subContainerPrefix.Trim() : "";

                _client = storageAccount.CreateCloudBlobClient();

                _checkpointReadCounter     = metricFactory.CreateCounter("acm-checkpoint-read", "The number of times that the Azure Storage checkpoint manager has read the checkpoint", false, new string[0]);
                _checkpointUpdateCounter   = metricFactory.CreateCounter("acm-checkpoint-update", "The number of times that the Azure Storage checkpoint manager has updated the checkpoint", false, new string[0]);
                _checkpointErrorCounter    = metricFactory.CreateCounter("acm-checkpoint-error", "The number of times that the Azure Storage checkpoint manager has errors raised", false, new string[0]);
                _storagePerformanceSummary = metricFactory.CreateSummary("acm-storage-timing", "The duration taken to access Azure Storage to perform checkpoint manager operations", 10, false, new string[0]);
            }
        }
Beispiel #6
0
        /// <inheritdoc />
        public async Task <bool> AcquireLeaseAsync(Lease lease)
        {
            var azureLease = (AzureBlobLease)lease;

            CloudBlockBlob leaseBlob   = azureLease.Blob;
            bool           retval      = true;
            string         newLeaseId  = Guid.NewGuid().ToString();
            string         partitionId = lease.PartitionId;

            _leaseUpdateCounter.Increment();

            using (_logger.BeginScope("Acquire Lease"))
            {
                _logger.LogInformation("Acquiring lease for partition {partitionId}", lease.PartitionId);

                try
                {
                    bool   renewLease = false;
                    string newToken;

                    using (_storagePerformanceSummary.Time())
                    {
                        await leaseBlob.FetchAttributesAsync(_defaultAccessCondition, _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                    }

                    if (leaseBlob.Properties.LeaseState == LeaseState.Leased)
                    {
                        if (string.IsNullOrEmpty(lease.Token))
                        {
                            return(false);
                        }

                        _logger.LogInformation("Need to ChangeLease: Partition Id: {partitionId}", lease.PartitionId);
                        renewLease = true;

                        using (_storagePerformanceSummary.Time())
                        {
                            newToken = await leaseBlob.ChangeLeaseAsync(newLeaseId, AccessCondition.GenerateLeaseCondition(lease.Token), _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        _logger.LogInformation("Need to AcquireLease: Partition Id: {partitionId}", lease.PartitionId);

                        using (_storagePerformanceSummary.Time())
                        {
                            newToken = await leaseBlob.AcquireLeaseAsync(LeaseDuration, newLeaseId, _defaultAccessCondition, _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                        }
                    }

                    lease.Token = newToken;
                    lease.Owner = _eventProcessorHostName;
                    lease.IncrementEpoch(); // Increment epoch each time lease is acquired or stolen by a new host

                    if (renewLease)
                    {
                        await RenewLeaseCoreAsync(azureLease).ConfigureAwait(false);
                    }
                    leaseBlob.Metadata[MetaDataOwnerName] = lease.Owner;

                    using (_storagePerformanceSummary.Time())
                    {
                        await leaseBlob.SetMetadataAsync(AccessCondition.GenerateLeaseCondition(lease.Token), _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                    }

                    using (_storagePerformanceSummary.Time())
                    {
                        await leaseBlob.UploadTextAsync(JsonConvert.SerializeObject(lease), _leaseEncoding, AccessCondition.GenerateLeaseCondition(lease.Token), _defaultRequestOptions, _operationContext).ConfigureAwait(false);
                    }
                }
                catch (StorageException e)
                {
                    _leaseErrorCounter.Increment();
                    var se = AzureBlobCommon.CheckForLeaseLostException(partitionId, e, _logger);

                    _logger.LogError(se, "Error acquiring lease for partition {partitionId}", lease.PartitionId);
                    throw se;
                }
            }

            return(retval);
        }