コード例 #1
0
        private void EnsureMessagingEntityExists(MessageTypeMessagingEntityMappingDetails mappingDetails, IEnumerable <MessageTypeMessagingEntityMappingDetails> allMessageTypePathMappings)
        {
            MessagingEntityCreationOptions creationOptions = mappingDetails.CreationOptions;

            if (creationOptions != MessagingEntityCreationOptions.None
                &&
                !_verifiedExistingMessagingEntities.Contains(mappingDetails))
            {
                Func <bool> exists;
                Action      create;
                Action      delete;

                string path = mappingDetails.Path;

                switch (mappingDetails.MessagingEntityType)
                {
                case MessagingEntityType.Queue:
                    exists = () => _namespaceManager.QueueExists(path);
                    create = () => _namespaceManager.CreateQueue(path);
                    delete = () => _namespaceManager.DeleteQueue(path);

                    break;

                case MessagingEntityType.Topic:
                    exists = () => _namespaceManager.TopicExists(path);
                    create = () => _namespaceManager.CreateTopic(path);
                    delete = () => _namespaceManager.DeleteTopic(path);

                    break;

                case MessagingEntityType.Subscription:
                    string[] parts            = path.Split('/');
                    string   topicPath        = parts[0];
                    string   subscriptionName = parts[2];

                    exists = () => _namespaceManager.SubscriptionExists(topicPath, subscriptionName);
                    create = () =>
                    {
                        MessageTypeMessagingEntityMappingDetails topicMessageTypePathMapping = allMessageTypePathMappings.FirstOrDefault(mtpmd => mtpmd.MessagingEntityType == MessagingEntityType.Topic && mtpmd.Path == topicPath);

                        if (topicMessageTypePathMapping == null)
                        {
                            topicMessageTypePathMapping = new MessageTypeMessagingEntityMappingDetails(mappingDetails.MessageType, topicPath, MessagingEntityType.Topic, MessagingEntityCreationOptions.VerifyAlreadyExists);
                        }

                        EnsureMessagingEntityExists(topicMessageTypePathMapping, allMessageTypePathMappings);

                        _namespaceManager.CreateSubscription(topicPath, subscriptionName);
                    };
                    delete = () => _namespaceManager.DeleteSubscription(topicPath, subscriptionName);

                    break;

                default:
                    throw new NotSupportedException(string.Format("Unsupported messaging entity type, {0}, requested for creation (path {1}).", mappingDetails.MessagingEntityType, mappingDetails.Path));
                }

                bool alreadyExists = exists();

                if (alreadyExists)
                {
                    if ((creationOptions & MessagingEntityCreationOptions.CreateAsTemporary) != 0)
                    {
                        if ((creationOptions & MessagingEntityCreationOptions.RecreateExistingTemporary) == 0)
                        {
                            throw new MessagingEntityAlreadyExistsException(mappingDetails.Path, mappingDetails.MessagingEntityType);
                        }

                        try
                        {
                            delete();

                            alreadyExists = false;
                        }
                        catch (UnauthorizedAccessException exception)
                        {
                            throw new UnauthorizedAccessException(string.Format("Unable to delete temporary messaging that already exists at path \"{0}\" due to insufficient access. Make sure the policy being used has 'Manage' permission for the namespace.", mappingDetails.Path), exception);
                        }
                    }
                }

                if (!alreadyExists)
                {
                    if ((creationOptions & (MessagingEntityCreationOptions.CreateIfDoesntExist | MessagingEntityCreationOptions.CreateAsTemporary)) == 0)
                    {
                        throw new MessagingEntityDoesNotAlreadyExistException(mappingDetails.Path, mappingDetails.MessagingEntityType);
                    }

                    try
                    {
                        create();
                    }
                    catch (UnauthorizedAccessException exception)
                    {
                        throw new UnauthorizedAccessException(string.Format("Unable to create messaging entity at path \"{0}\" due to insufficient access. Make sure the policy being used has 'Manage' permission for the namespace.", mappingDetails.Path), exception);
                    }
                }

                _verifiedExistingMessagingEntities.Add(mappingDetails);
            }
        }
        public async Task <QueueDescription> Create(string queuePath, INamespaceManager namespaceManager)
        {
            var description = descriptionFactory(queuePath, settings);

            try
            {
                if (!await ExistsAsync(namespaceManager, description.Path).ConfigureAwait(false))
                {
                    await namespaceManager.CreateQueue(description).ConfigureAwait(false);

                    logger.InfoFormat("Queue '{0}' created in namespace '{1}'.", description.Path, namespaceManager.Address.Host);

                    var key = GenerateQueueKey(namespaceManager, queuePath);

                    await rememberExistence.AddOrUpdate(key, s => Task.FromResult(true), (s, b) => Task.FromResult(true)).ConfigureAwait(false);
                }
                else
                {
                    logger.InfoFormat("Queue '{0}' in namespace '{1}' already exists, skipping creation.", description.Path, namespaceManager.Address.Host);
                    logger.InfoFormat("Checking if queue '{0}' in namespace '{1}' needs to be updated.", description.Path, namespaceManager.Address.Host);
                    if (IsSystemQueue(description.Path))
                    {
                        logger.InfoFormat("Queue '{0}' in '{1}' is a shared queue and should not be updated.", description.Path, namespaceManager.Address.Host);
                        return(description);
                    }
                    var existingDescription = await namespaceManager.GetQueue(description.Path).ConfigureAwait(false);

                    if (MembersAreNotEqual(existingDescription, description))
                    {
                        OverrideImmutableMembers(existingDescription, description);
                        logger.InfoFormat("Updating queue '{0}' in namespace '{1}' with new description.", description.Path, namespaceManager.Address.Host);
                        await namespaceManager.UpdateQueue(description).ConfigureAwait(false);
                    }
                }
            }
            catch (MessagingEntityAlreadyExistsException)
            {
                // the queue already exists or another node beat us to it, which is ok
                logger.InfoFormat("Queue '{0}' in namespace '{1}' already exists, another node probably beat us to it.", description.Path, namespaceManager.Address.Host);
            }
            catch (TimeoutException)
            {
                logger.InfoFormat("Timeout occurred on queue creation for '{0}' in namespace '{1}' going to validate if it doesn't exist.", description.Path, namespaceManager.Address.Host);

                // there is a chance that the timeout occurred, but the topic was still created, check again
                if (!await ExistsAsync(namespaceManager, description.Path, removeCacheEntry: true).ConfigureAwait(false))
                {
                    throw;
                }

                logger.InfoFormat("Looks like queue '{0}' in namespace '{1}' exists anyway.", description.Path, namespaceManager.Address.Host);
            }
            catch (MessagingException ex)
            {
                if (!ex.IsTransient)
                {
                    logger.Fatal(string.Format("{1} {2} occurred on queue creation '{0}' in namespace '{3}'.", description.Path, (ex.IsTransient ? "Transient" : "Non transient"), ex.GetType().Name, namespaceManager.Address.Host), ex);
                    throw;
                }

                logger.Info(string.Format("{1} {2} occurred on queue creation '{0}' in namespace '{3}'.", description.Path, (ex.IsTransient ? "Transient" : "Non transient"), ex.GetType().Name, namespaceManager.Address.Host), ex);
            }

            return(description);
        }