Ejemplo n.º 1
0
 internal AzureBlobLease(AzureBlobLease source)
     : base(source)
 {
     this.Offset         = source.Offset;
     this.SequenceNumber = source.SequenceNumber;
     this.Blob           = source.Blob;
 }
        async Task <bool> ReleaseLeaseCoreAsync(AzureBlobLease lease)
        {
            ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.Id, lease.PartitionId, "Releasing lease");

            CloudBlockBlob leaseBlob   = lease.Blob;
            bool           retval      = true;
            string         partitionId = lease.PartitionId;

            try
            {
                string         leaseId      = lease.Token;
                AzureBlobLease releasedCopy = new AzureBlobLease(lease)
                {
                    Token = string.Empty,
                    Owner = string.Empty
                };
                await leaseBlob.UploadTextAsync(JsonConvert.SerializeObject(releasedCopy), null, AccessCondition.GenerateLeaseCondition(leaseId), null, null).ConfigureAwait(false);

                await leaseBlob.ReleaseLeaseAsync(AccessCondition.GenerateLeaseCondition(leaseId)).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                if (WasLeaseLost(partitionId, se))
                {
                    retval = false;
                }
                else
                {
                    throw;
                }
            }

            return(retval);
        }
Ejemplo n.º 3
0
 internal AzureBlobLease(AzureBlobLease source, CloudBlockBlob blob) : base(source)
 {
     this.Offset         = source.Offset;
     this.SequenceNumber = source.SequenceNumber;
     this.Blob           = blob;
     this.isOwned        = blob.Properties.LeaseState == LeaseState.Leased;
 }
Ejemplo n.º 4
0
        public async Task UpdateCheckpointAsync(Lease lease, Checkpoint checkpoint)
        {
            AzureBlobLease newLease = new AzureBlobLease((AzureBlobLease)lease);

            newLease.Offset         = checkpoint.Offset;
            newLease.SequenceNumber = checkpoint.SequenceNumber;
            await this.UpdateLeaseAsync(newLease).ConfigureAwait(false);
        }
Ejemplo n.º 5
0
        public async Task <Checkpoint> CreateCheckpointIfNotExistsAsync(string partitionId)
        {
            // Normally the lease will already be created, checkpoint store is initialized after lease store.
            AzureBlobLease lease      = (AzureBlobLease)(await CreateLeaseIfNotExistsAsync(partitionId));
            Checkpoint     checkpoint = new Checkpoint(partitionId, lease.Offset, lease.SequenceNumber);

            return(checkpoint);
        }
Ejemplo n.º 6
0
        async Task <bool> AcquireLeaseCoreAsync(AzureBlobLease lease)
        {
            CloudBlockBlob leaseBlob   = lease.Blob;
            bool           retval      = true;
            string         newLeaseId  = Guid.NewGuid().ToString();
            string         partitionId = lease.PartitionId;

            try
            {
                string newToken;
                await leaseBlob.FetchAttributesAsync().ConfigureAwait(false);

                if (leaseBlob.Properties.LeaseState == LeaseState.Leased)
                {
                    if (string.IsNullOrEmpty(lease.Token))
                    {
                        // We reach here in a race condition: when this instance of EventProcessorHost scanned the
                        // lease blobs, this partition was unowned (token is empty) but between then and now, another
                        // instance of EPH has established a lease (getLeaseState() is LEASED). We normally enforce
                        // that we only steal the lease if it is still owned by the instance which owned it when we
                        // scanned, but we can't do that when we don't know who owns it. The safest thing to do is just
                        // fail the acquisition. If that means that one EPH instance gets more partitions than it should,
                        // rebalancing will take care of that quickly enough.
                        return(false);
                    }

                    ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, lease.PartitionId, "Need to ChangeLease");
                    newToken = await leaseBlob.ChangeLeaseAsync(newLeaseId, AccessCondition.GenerateLeaseCondition(lease.Token)).ConfigureAwait(false);
                }
                else
                {
                    ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, lease.PartitionId, "Need to AcquireLease");

                    try
                    {
                        newToken = await leaseBlob.AcquireLeaseAsync(leaseDuration, newLeaseId).ConfigureAwait(false);
                    }
                    catch (StorageException se)
                        when(se.RequestInformation != null &&
                             se.RequestInformation.ErrorCode.Equals(BlobErrorCodeStrings.LeaseAlreadyPresent, StringComparison.OrdinalIgnoreCase))
                        {
                            // Either some other host grabbed the lease or checkpoint call renewed it.
                            return(false);
                        }
                }

                lease.Token = newToken;
                lease.Owner = this.host.HostName;
                lease.IncrementEpoch(); // Increment epoch each time lease is acquired or stolen by a new host
                await leaseBlob.UploadTextAsync(JsonConvert.SerializeObject(lease), null, AccessCondition.GenerateLeaseCondition(lease.Token), null, null).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                throw HandleStorageException(partitionId, se);
            }

            return(retval);
        }
        public async Task UpdateCheckpointAsync(Checkpoint checkpoint)
        {
            // Need to fetch the most current lease data so that we can update it correctly.
            AzureBlobLease lease = (AzureBlobLease) await GetLeaseAsync(checkpoint.PartitionId).ConfigureAwait(false);

            lease.Offset         = checkpoint.Offset;
            lease.SequenceNumber = checkpoint.SequenceNumber;
            await UpdateLeaseAsync(lease).ConfigureAwait(false);
        }
Ejemplo n.º 8
0
        async Task <AzureBlobLease> DownloadLeaseAsync(string partitionId, CloudBlockBlob blob) // throws StorageException, IOException
        {
            string jsonLease = await blob.DownloadTextAsync();

            ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.Id, partitionId, "Raw JSON downloaded: " + jsonLease);
            AzureBlobLease rehydrated = (AzureBlobLease)JsonConvert.DeserializeObject(jsonLease, typeof(AzureBlobLease));
            AzureBlobLease blobLease  = new AzureBlobLease(rehydrated, blob);

            return(blobLease);
        }
        async Task <Lease> DownloadLeaseAsync(string partitionId, CloudBlockBlob blob) // throws StorageException, IOException
        {
            string jsonLease = await blob.DownloadTextAsync(null, null, this.defaultRequestOptions, this.operationContext).ConfigureAwait(false);

            ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, partitionId, "Raw JSON downloaded: " + jsonLease);
            AzureBlobLease rehydrated = (AzureBlobLease)JsonConvert.DeserializeObject(jsonLease, typeof(AzureBlobLease));
            AzureBlobLease blobLease  = new AzureBlobLease(rehydrated, blob);

            return(blobLease);
        }
        public async Task <Lease> GetLeaseAsync(string partitionId) // throws URISyntaxException, IOException, StorageException
        {
            AzureBlobLease retval = null;

            CloudBlockBlob leaseBlob = GetBlockBlobReference(partitionId);

            if (await leaseBlob.ExistsAsync().ConfigureAwait(false))
            {
                retval = await DownloadLeaseAsync(partitionId, leaseBlob).ConfigureAwait(false);
            }

            return(retval);
        }
Ejemplo n.º 11
0
        public async Task <Lease> GetLeaseAsync(string partitionId) // throws URISyntaxException, IOException, StorageException
        {
            AzureBlobLease retval = null;

            CloudBlockBlob leaseBlob = this.consumerGroupDirectory.GetBlockBlobReference(partitionId);

            if (await leaseBlob.ExistsAsync())
            {
                retval = await DownloadLeaseAsync(partitionId, leaseBlob);
            }

            return(retval);
        }
Ejemplo n.º 12
0
        public async Task <Lease> CreateLeaseIfNotExistsAsync(string partitionId) // throws URISyntaxException, IOException, StorageException
        {
            AzureBlobLease returnLease;

            try
            {
                CloudBlockBlob leaseBlob = GetBlockBlobReference(partitionId);
                returnLease = new AzureBlobLease(partitionId, leaseBlob);
                string jsonLease = JsonConvert.SerializeObject(returnLease);

                ProcessorEventSource.Log.AzureStorageManagerInfo(
                    this.host.HostName,
                    partitionId,
                    "CreateLeaseIfNotExist - leaseContainerName: " + this.leaseContainerName +
                    " consumerGroupName: " + this.host.ConsumerGroupName + " storageBlobPrefix: " + this.storageBlobPrefix);

                // Don't provide default request options for upload call.
                // This request will respect client's default options.
                await leaseBlob.UploadTextAsync(
                    jsonLease,
                    null,
                    AccessCondition.GenerateIfNoneMatchCondition("*"),
                    null,
                    this.operationContext).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                if (se.RequestInformation.ErrorCode == BlobErrorCodeStrings.BlobAlreadyExists ||
                    se.RequestInformation.ErrorCode == BlobErrorCodeStrings.LeaseIdMissing)  // occurs when somebody else already has leased the blob
                {
                    // The blob already exists.
                    ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, partitionId, "Lease already exists");
                    returnLease = (AzureBlobLease) await GetLeaseAsync(partitionId).ConfigureAwait(false);
                }
                else
                {
                    ProcessorEventSource.Log.AzureStorageManagerError(
                        this.host.HostName,
                        partitionId,
                        "CreateLeaseIfNotExist StorageException - leaseContainerName: " + this.leaseContainerName +
                        " consumerGroupName: " + this.host.ConsumerGroupName + " storageBlobPrefix: " + this.storageBlobPrefix,
                        se.ToString());
                    throw;
                }
            }

            return(returnLease);
        }
Ejemplo n.º 13
0
        public async Task <Checkpoint> GetCheckpointAsync(string partitionId)
        {
            AzureBlobLease lease      = (AzureBlobLease)(await GetLeaseAsync(partitionId));
            Checkpoint     checkpoint = null;

            if (lease != null && lease.Offset != null)
            {
                checkpoint = new Checkpoint(partitionId)
                {
                    Offset         = lease.Offset,
                    SequenceNumber = lease.SequenceNumber
                };
            }

            return(checkpoint);
        }
Ejemplo n.º 14
0
        async Task <bool> RenewLeaseCoreAsync(AzureBlobLease lease)
        {
            CloudBlockBlob leaseBlob   = lease.Blob;
            string         partitionId = lease.PartitionId;

            try
            {
                await leaseBlob.RenewLeaseAsync(AccessCondition.GenerateLeaseCondition(lease.Token), this.renewRequestOptions, null).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                throw HandleStorageException(partitionId, se);
            }

            return(true);
        }
        public async Task <Checkpoint> GetCheckpointAsync(string partitionId)
        {
            AzureBlobLease lease = (AzureBlobLease) await GetLeaseAsync(partitionId).ConfigureAwait(false);

            Checkpoint checkpoint = null;

            if (lease != null && !string.IsNullOrEmpty(lease.Offset))
            {
                checkpoint = new Checkpoint(partitionId)
                {
                    Offset         = lease.Offset,
                    SequenceNumber = lease.SequenceNumber
                };
            }

            return(checkpoint);
        }
        async Task <bool> UpdateLeaseCoreAsync(AzureBlobLease lease)
        {
            if (lease == null)
            {
                return(false);
            }

            string partitionId = lease.PartitionId;

            ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.Id, partitionId, "Updating lease");

            string token = lease.Token;

            if (string.IsNullOrEmpty(token))
            {
                return(false);
            }

            // First, renew the lease to make sure the update will go through.
            if (!await this.RenewLeaseAsync(lease).ConfigureAwait(false))
            {
                return(false);
            }

            CloudBlockBlob leaseBlob = lease.Blob;

            try
            {
                string jsonToUpload = JsonConvert.SerializeObject(lease);
                ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.Id, lease.PartitionId, $"Raw JSON uploading: {jsonToUpload}");
                await leaseBlob.UploadTextAsync(jsonToUpload, null, AccessCondition.GenerateLeaseCondition(token), null, null).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                if (WasLeaseLost(partitionId, se))
                {
                    throw new LeaseLostException(lease, se);
                }

                throw;
            }

            return(true);
        }
Ejemplo n.º 17
0
        public async Task <Lease> CreateLeaseIfNotExistsAsync(string partitionId) // throws URISyntaxException, IOException, StorageException
        {
            AzureBlobLease returnLease;

            try
            {
                CloudBlockBlob leaseBlob = this.consumerGroupDirectory.GetBlockBlobReference(partitionId);
                returnLease = new AzureBlobLease(partitionId, leaseBlob);
                string jsonLease = JsonConvert.SerializeObject(returnLease);

                ProcessorEventSource.Log.AzureStorageManagerInfo(
                    this.host.Id,
                    partitionId,
                    "CreateLeaseIfNotExist - leaseContainerName: " + this.leaseContainerName + " consumerGroupName: " + this.host.ConsumerGroupName);
                await leaseBlob.UploadTextAsync(jsonLease, null, AccessCondition.GenerateIfNoneMatchCondition("*"), null, null);
            }
            catch (StorageException se)
            {
                StorageExtendedErrorInformation extendedErrorInfo = se.RequestInformation.ExtendedErrorInformation;
                if (extendedErrorInfo != null &&
                    (extendedErrorInfo.ErrorCode == BlobErrorCodeStrings.BlobAlreadyExists ||
                     extendedErrorInfo.ErrorCode == BlobErrorCodeStrings.LeaseIdMissing)) // occurs when somebody else already has leased the blob
                {
                    // The blob already exists.
                    ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.Id, partitionId, "Lease already exists");
                    returnLease = (AzureBlobLease)(await GetLeaseAsync(partitionId));
                }
                else
                {
                    Console.WriteLine("errorCode " + extendedErrorInfo.ErrorCode);
                    Console.WriteLine("errorString " + extendedErrorInfo.ErrorMessage);

                    ProcessorEventSource.Log.AzureStorageManagerError(
                        this.host.Id,
                        partitionId,
                        "CreateLeaseIfNotExist StorageException - leaseContainerName: " + this.leaseContainerName + " consumerGroupName: " + this.host.ConsumerGroupName,
                        se.ToString());
                    throw;
                }
            }

            return(returnLease);
        }
        async Task <bool> AcquireLeaseCoreAsync(AzureBlobLease lease)
        {
            CloudBlockBlob leaseBlob   = lease.Blob;
            bool           retval      = true;
            string         newLeaseId  = Guid.NewGuid().ToString();
            string         partitionId = lease.PartitionId;

            try
            {
                string newToken;
                await leaseBlob.FetchAttributesAsync().ConfigureAwait(false);

                if (leaseBlob.Properties.LeaseState == LeaseState.Leased)
                {
                    ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.Id, lease.PartitionId, "Need to ChangeLease");
                    newToken = await leaseBlob.ChangeLeaseAsync(newLeaseId, AccessCondition.GenerateLeaseCondition(lease.Token)).ConfigureAwait(false);
                }
                else
                {
                    ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.Id, lease.PartitionId, "Need to AcquireLease");
                    newToken = await leaseBlob.AcquireLeaseAsync(leaseDuration, newLeaseId).ConfigureAwait(false);
                }

                lease.Token = newToken;
                lease.Owner = this.host.HostName;
                lease.IncrementEpoch(); // Increment epoch each time lease is acquired or stolen by a new host
                await leaseBlob.UploadTextAsync(JsonConvert.SerializeObject(lease), null, AccessCondition.GenerateLeaseCondition(lease.Token), null, null).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                if (WasLeaseLost(partitionId, se))
                {
                    retval = false;
                }
                else
                {
                    throw;
                }
            }

            return(retval);
        }
Ejemplo n.º 19
0
        async Task <bool> UpdateLeaseCoreAsync(AzureBlobLease lease)
        {
            if (lease == null)
            {
                return(false);
            }

            string partitionId = lease.PartitionId;

            ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, partitionId, "Updating lease");

            string token = lease.Token;

            if (string.IsNullOrEmpty(token))
            {
                return(false);
            }

            CloudBlockBlob leaseBlob = lease.Blob;

            try
            {
                string jsonToUpload = JsonConvert.SerializeObject(lease);
                ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, lease.PartitionId, $"Raw JSON uploading: {jsonToUpload}");

                // This is on the code path of checkpoint call thus don't provide default request options for upload call.
                // This request will respect client's default options.
                await leaseBlob.UploadTextAsync(
                    jsonToUpload,
                    null,
                    AccessCondition.GenerateLeaseCondition(token),
                    null,
                    this.operationContext).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                throw HandleStorageException(partitionId, se);
            }

            return(true);
        }
        async Task <bool> ReleaseLeaseCoreAsync(AzureBlobLease lease)
        {
            ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, lease.PartitionId, "Releasing lease");

            CloudBlockBlob leaseBlob   = lease.Blob;
            string         partitionId = lease.PartitionId;

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

                // Remove owner in the metadata.
                leaseBlob.Metadata.Remove(MetaDataOwnerName);

                await leaseBlob.SetMetadataAsync(
                    AccessCondition.GenerateLeaseCondition(leaseId),
                    this.defaultRequestOptions,
                    this.operationContext).ConfigureAwait(false);

                await leaseBlob.UploadTextAsync(
                    JsonConvert.SerializeObject(releasedCopy),
                    null,
                    AccessCondition.GenerateLeaseCondition(leaseId),
                    this.defaultRequestOptions,
                    this.operationContext).ConfigureAwait(false);

                await leaseBlob.ReleaseLeaseAsync(AccessCondition.GenerateLeaseCondition(leaseId), this.defaultRequestOptions, this.operationContext).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                throw HandleStorageException(partitionId, se);
            }

            return(true);
        }
        async Task <bool> UpdateLeaseCoreAsync(AzureBlobLease lease)
        {
            if (lease == null)
            {
                return(false);
            }

            string partitionId = lease.PartitionId;

            ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, partitionId, "Updating lease");

            string token = lease.Token;

            if (string.IsNullOrEmpty(token))
            {
                return(false);
            }

            CloudBlockBlob leaseBlob = lease.Blob;

            try
            {
                string jsonToUpload = JsonConvert.SerializeObject(lease);
                ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, lease.PartitionId, $"Raw JSON uploading: {jsonToUpload}");

                await leaseBlob.UploadTextAsync(
                    jsonToUpload,
                    null,
                    AccessCondition.GenerateLeaseCondition(token),
                    this.defaultRequestOptions,
                    this.operationContext).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                throw HandleStorageException(partitionId, se);
            }

            return(true);
        }
        async Task <bool> RenewLeaseCoreAsync(AzureBlobLease lease)
        {
            CloudBlockBlob leaseBlob   = lease.Blob;
            bool           retval      = true;
            string         partitionId = lease.PartitionId;

            try
            {
                await leaseBlob.RenewLeaseAsync(AccessCondition.GenerateLeaseCondition(lease.Token), this.renewRequestOptions, null).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                if (WasLeaseLost(partitionId, se))
                {
                    retval = false;
                }
                else
                {
                    throw;
                }
            }

            return(retval);
        }
        async Task <bool> AcquireLeaseCoreAsync(AzureBlobLease lease)
        {
            CloudBlockBlob leaseBlob   = lease.Blob;
            bool           retval      = true;
            string         newLeaseId  = Guid.NewGuid().ToString();
            string         partitionId = lease.PartitionId;

            try
            {
                bool   renewLease = false;
                string newToken;

                await leaseBlob.FetchAttributesAsync(null, this.defaultRequestOptions, this.operationContext).ConfigureAwait(false);

                if (leaseBlob.Properties.LeaseState == LeaseState.Leased)
                {
                    if (string.IsNullOrEmpty(lease.Token))
                    {
                        // We reach here in a race condition: when this instance of EventProcessorHost scanned the
                        // lease blobs, this partition was unowned (token is empty) but between then and now, another
                        // instance of EPH has established a lease (getLeaseState() is LEASED). We normally enforce
                        // that we only steal the lease if it is still owned by the instance which owned it when we
                        // scanned, but we can't do that when we don't know who owns it. The safest thing to do is just
                        // fail the acquisition. If that means that one EPH instance gets more partitions than it should,
                        // rebalancing will take care of that quickly enough.
                        return(false);
                    }

                    ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, lease.PartitionId, "Need to ChangeLease");
                    renewLease = true;
                    newToken   = await leaseBlob.ChangeLeaseAsync(
                        newLeaseId,
                        AccessCondition.GenerateLeaseCondition(lease.Token),
                        this.defaultRequestOptions,
                        this.operationContext).ConfigureAwait(false);
                }
                else
                {
                    ProcessorEventSource.Log.AzureStorageManagerInfo(this.host.HostName, lease.PartitionId, "Need to AcquireLease");
                    newToken = await leaseBlob.AcquireLeaseAsync(
                        leaseDuration,
                        newLeaseId,
                        null,
                        this.defaultRequestOptions,
                        this.operationContext).ConfigureAwait(false);
                }

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

                // Renew lease here if needed?
                // ChangeLease doesn't renew so we should avoid lease expiring before next renew interval.
                if (renewLease)
                {
                    await this.RenewLeaseCoreAsync(lease).ConfigureAwait(false);
                }

                // Update owner in the metadata first since clients get ownership information by looking at metadata.
                lease.Blob.Metadata[MetaDataOwnerName] = lease.Owner;
                await lease.Blob.SetMetadataAsync(
                    AccessCondition.GenerateLeaseCondition(lease.Token),
                    this.defaultRequestOptions,
                    this.operationContext).ConfigureAwait(false);

                // Then update deserialized lease content.
                await leaseBlob.UploadTextAsync(
                    JsonConvert.SerializeObject(lease),
                    null,
                    AccessCondition.GenerateLeaseCondition(lease.Token),
                    this.defaultRequestOptions,
                    this.operationContext).ConfigureAwait(false);
            }
            catch (StorageException se)
            {
                throw HandleStorageException(partitionId, se);
            }

            return(retval);
        }
Ejemplo n.º 24
0
 internal AzureBlobLease(AzureBlobLease source, CloudBlockBlob blob) : base(source)
 {
     this.Offset         = source.Offset;
     this.SequenceNumber = source.SequenceNumber;
     this.Blob           = blob;
 }