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); }