private void InvalidateSearchIndex(List <OrganizationServiceCachePluginMessage> batchedPluginMessage, Dictionary <Guid, SearchIndexBuildRequest.SearchIndexInvalidationData> searchInvalidationDatum) { foreach (var message in batchedPluginMessage) { if (message.Target == null || SearchMetadataCache.Instance.SearchEnabledEntities.Contains(message.Target.LogicalName)) { SearchIndexBuildRequest.SearchIndexInvalidationData searchInvalidationData = null; if (message.Target != null) { searchInvalidationDatum.TryGetValue(message.Target.Id, out searchInvalidationData); } retryPolicy.Value.ExecuteAction(() => SearchIndexBuildRequest.ProcessMessage(message, searchInvalidationData, CrmChangeTrackingManager.Instance.OrganizationServiceContext)); } } }
private void ProcessNotification(CancellationToken cancellationToken, PluginMessageRequest request) { try { if (cancellationToken.IsCancellationRequested) { return; } if (!WebNotificationCryptography.ValidateRequest(request.Authorization)) { WebNotificationEventSource.Log.AuthorizationValidationFailed(); return; } var message = this.GetMessage(request); if (message == null) { WebNotificationEventSource.Log.MessageInvalid(); return; } CacheInvalidation.ProcessMessage(message); if (SearchIndexApplicableMessages.Contains(message.MessageName, MessageComparer)) { var serviceContext = CrmConfigurationManager.CreateContext(); SearchIndexBuildRequest.ProcessMessage(message, serviceContext: serviceContext); } } catch (TaskCanceledException e) { ADXTrace.Instance.TraceWarning(TraceCategory.Application, e.Message); } }
/// <summary> /// Posts notifications of entity changes /// </summary> /// <param name="messages">List of Notification messages</param> /// <param name="isMetadataChangeMessage">True if it is a metadata change notification.</param> /// <param name="isSearchIndexInvalidation">True for search index invlaidation and false for cache invalidation.</param> /// <returns></returns> private List <string> PostRequest(IEnumerable <PluginMessage> messages, bool isMetadataChangeMessage, bool isSearchIndexInvalidation = false) { List <string> entitiesWithSuccessfulInvalidation = new List <string>(); try { var batchedMessages = messages .Where(mesg => mesg != null) .GroupBy(mesg => mesg.Target == null ? string.Empty : mesg.Target.LogicalName); foreach (var batchedmessage in batchedMessages) { List <OrganizationServiceCachePluginMessage> batchedPluginMessage = new List <OrganizationServiceCachePluginMessage>(); var searchInvalidationDatum = new Dictionary <Guid, SearchIndexBuildRequest.SearchIndexInvalidationData>(); foreach (var changedItem in batchedmessage) { if (changedItem != null) { if (changedItem.Target != null) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Posting Request for message with Entity: {0} and ChangeType: {1}", changedItem.Target.LogicalName, changedItem.MessageName)); } var restartMessage = new ApplicationRestartPortalBusMessage(); // Conversion to OrganizationServiceCachePluginMessage type var message = new OrganizationServiceCachePluginMessage(); message.MessageName = changedItem.MessageName; message.RelatedEntities = changedItem.RelatedEntities; message.Relationship = changedItem.Relationship; message.Target = changedItem.Target; if (restartMessage.Validate(changedItem)) { // The restart messages should be processed only once when the message is received from Cache subscription. if (!isSearchIndexInvalidation) { // restart the web application var task = restartMessage.InvokeAsync(new OwinContext()).WithCurrentCulture(); task.GetAwaiter().GetResult(); SearchIndexBuildRequest.ProcessMessage(message); } } else { if (!isSearchIndexInvalidation && FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching) && message.Target != null && message.Target.Id != Guid.Empty) { // Get relevant info for search index invalidation from content map before cache invalidation // MUST OCCUR BEFORE CACHE INVALIDATION if (!searchInvalidationDatum.ContainsKey(message.Target.Id)) { searchInvalidationDatum.Add(message.Target.Id, GetSearchIndexInvalidationData(message)); } } batchedPluginMessage.Add(message); } } else { //logging ADXTrace.Instance.TraceWarning(TraceCategory.Application, string.Format("ChangedItem Record is Null ")); } } if (batchedPluginMessage.Count > 0) { if (isMetadataChangeMessage) { // Invalidate both search index as well as cache try { InvalidateSearchIndex(batchedPluginMessage, searchInvalidationDatum); } catch (Exception e) { // Even if exception occurs, we still need to invalidate cache, hence cathing exception here and logging error. ADXTrace.Instance.TraceError(TraceCategory.Exception, e.ToString()); } InvalidateCache(batchedPluginMessage); } else if (isSearchIndexInvalidation) { InvalidateSearchIndex(batchedPluginMessage, searchInvalidationDatum); } else { // Invalidate cache InvalidateCache(batchedPluginMessage); } } entitiesWithSuccessfulInvalidation.Add(batchedmessage.Key); } return(entitiesWithSuccessfulInvalidation); } catch (Exception e) { ADXTrace.Instance.TraceError(TraceCategory.Application, e.ToString()); return(entitiesWithSuccessfulInvalidation); } }