示例#1
0
        /// <summary>
        /// Analyzes the response path of a two way send port to build the route back to the topic channel.
        /// </summary>
        /// <param name="intermediaryKeyPrefix">The prefix for the intermediary key.</param>
        /// <param name="sourceApplication">The application object in the source model.</param>
        /// <param name="targetApplication">The application object in the target model.</param>
        /// <param name="sendPortSource">The send port source.</param>
        /// <param name="sendPort">The send port resource item.</param>
        /// <param name="endpointAdapter">The endpoint adapter which triggers the response.</param>
        private void AnalyzeSendPortResponse(string intermediaryKeyPrefix, ResourceItem sourceApplication, Application targetApplication, SendPort sendPortSource, ResourceItem sendPort, MessagingObject endpointAdapter)
        {
            _logger.LogDebug(TraceMessages.SendPortIsTwoWay, RuleName, sendPort.Name);

            // Format the keys.
            var applicationName = targetApplication.Name.FormatKey();
            var sendPortName    = sendPort.Name.FormatKey();

            // Set the scenario name on the endpoint adapter.
            endpointAdapter.Properties.Add(ModelConstants.ScenarioName, $"{applicationName}.{sendPortName}.Response");

            var route = new List <MessagingObject>
            {
                endpointAdapter
            };

            // Create the intermediaries for the pipeline
            route.AddRange(CreateReceivePipelineIntermediaries(intermediaryKeyPrefix, sourceApplication, sendPortSource.ReceivePipeline, sendPortSource.ReceivePipelineCustomConfiguration));

            // If there is a map, create the intermediary
            if (sendPortSource.InboundTransforms != null && sendPortSource.InboundTransforms.Any())
            {
                // Find map resource items
                var transforms = sendPort.FindRelatedResourcesByType(Model, ResourceRelationshipType.ReferencesTo, ModelConstants.ResourceMap);

                // Add to route
                var intermediary = CreateMapIntermediary(intermediaryKeyPrefix, targetApplication, transforms);
                if (intermediary != null)
                {
                    route.Add(intermediary);
                }
            }
            else
            {
                _logger.LogTrace(TraceMessages.NoReceiveMapSpecifiedOnSendPort, RuleName, sendPortSource.Name);
            }

            // Create the message agent intermediaries
            route.AddRange(CreateMessageAgentIntermediaries(intermediaryKeyPrefix, _messageBoxChannelKey, false, null));

            // Binds the route by adding routing slip router intermediaries between the intermediaries in the response from the send port
            var boundRoute = BindResponseRoute(intermediaryKeyPrefix, targetApplication, sendPortSource, route);

            // Binds the channels between the endpoint and intermediaries up to the message box (topic channel)
            BindResponseChannels(intermediaryKeyPrefix, targetApplication, sendPortSource, boundRoute);
        }
示例#2
0
        protected override async Task AnalyzePortsAsync(ResourceItem sourceApplication, Application targetApplication, CancellationToken token)
        {
            _logger.LogDebug(TraceMessages.AnalyzingSendPortScenarios, RuleName, sourceApplication.Name);

            var scenarios       = 0;
            var applicationName = targetApplication.Name.FormatKey();

            // TODO: Handle distribution lists

            // Find send ports in application
            var sendPorts = sourceApplication.FindRelatedResourcesByType(Model, ResourceRelationshipType.Child, ModelConstants.ResourceSendPort);

            foreach (var sendPort in sendPorts)
            {
                var sendPortSource = (SendPort)sendPort.SourceObject;
                var sendPortName   = sendPort.Name.FormatKey();

                // Is there a pipeline?
                if (sendPortSource.TransmitPipeline != null)
                {
                    var route     = new List <MessagingObject>();
                    var keyPrefix = $"{Model.MigrationTarget.MessageBus.Key}:{applicationName}:{sendPortName}";

                    // Create message subscriber
                    route.Add(CreateMessageSubscriberIntermediary(keyPrefix, targetApplication, sendPortSource));

                    // If there is a map, create the intermediary
                    if (sendPortSource.Transforms != null && sendPortSource.Transforms.Any())
                    {
                        // Find map resource items
                        var transforms = sendPort.FindRelatedResourcesByType(Model, ResourceRelationshipType.ReferencesTo, ModelConstants.ResourceMap);

                        // Add to route
                        var intermediary = CreateMapIntermediary(keyPrefix, targetApplication, transforms);
                        if (intermediary != null)
                        {
                            route.Add(intermediary);
                        }
                    }
                    else
                    {
                        _logger.LogTrace(TraceMessages.NoSendMapSpecifiedOnSendPort, RuleName, sendPortSource.Name);
                    }

                    // Create the intermediaries for the pipeline
                    route.AddRange(CreateSendPipelineIntermediaries(keyPrefix, sourceApplication, sendPortSource.TransmitPipeline, sendPortSource.SendPipelineCustomConfiguration));

                    // Create endpoint adapter
                    var endpointAdapter = CreateSendEndpoint(keyPrefix, sendPortSource);
                    route.Add(endpointAdapter);

                    // Binds the route by adding routing slip router intermediaries between the intermediaries and the endpoint in the send port
                    var boundRoute = BindRoute(keyPrefix, targetApplication, sendPortSource, route);

                    // Binds the channels between the message box (topic channel), intermediaries up to the endpoint (send adapter)
                    var topicChannelKey = _messageBoxChannelKey;
                    BindChannels(keyPrefix, topicChannelKey, targetApplication, sendPortSource, boundRoute);

                    // Add a new route for interchange batch completion handling, if required
                    var handleBatches = route.Any(s => s.Properties.ContainsKey(ModelConstants.HandleBatches) && (bool)s.Properties[ModelConstants.HandleBatches]);
                    if (handleBatches)
                    {
                        // Need to add interchange aggregation for individual messages that are to be sent as a batch, as would be
                        // done in an orchestration by building a batch of messages and calling send pipeline inline.  Instead, this
                        // adds an aggregator to the model which receives messages from an interchange queue and which then feeds the
                        // batch to the start of the send pipeline intermediaries.
                        BuildInterchangeAggregationRoute(keyPrefix, sourceApplication, targetApplication, sendPortSource);
                    }

                    // If port is two way, check for reverse path
                    if (sendPortSource.IsTwoWay)
                    {
                        AnalyzeSendPortResponse(keyPrefix, sourceApplication, targetApplication, sendPortSource, sendPort, endpointAdapter);
                    }

                    scenarios++;
                }
                else
                {
                    _logger.LogError(ErrorMessages.TransmitPipelineNotSetInSendPort, sendPort.Name);
                    Context.Errors.Add(new ErrorMessage(string.Format(CultureInfo.CurrentCulture, ErrorMessages.TransmitPipelineNotSetInSendPort, sendPort.Name)));
                }
            }

            if (scenarios > 0)
            {
                _logger.LogDebug(TraceMessages.FoundSendPortScenariosInApplication, RuleName, scenarios, sourceApplication.Name);
            }
            else
            {
                _logger.LogDebug(TraceMessages.NoSendPortsFoundInApplication, RuleName, sourceApplication.Name);
            }

            await Task.CompletedTask.ConfigureAwait(false);
        }
示例#3
0
        protected override async Task AnalyzePortsAsync(ResourceItem sourceApplication, Application targetApplication, CancellationToken token)
        {
            _logger.LogDebug(TraceMessages.AnalyzingReceivePortScenarios, RuleName, sourceApplication.Name);

            var scenarios       = 0;
            var applicationName = targetApplication.Name.FormatKey();

            // Find receive ports in application
            var receivePorts = sourceApplication.FindRelatedResourcesByType(Model, ResourceRelationshipType.Child, ModelConstants.ResourceReceivePort);

            foreach (var receivePort in receivePorts)
            {
                var receivePortSource = (ReceivePort)receivePort.SourceObject;
                var receivePortName   = receivePort.Name.FormatKey();

                // Find receive locations in receive port
                var receiveLocations = receivePort.Resources.Where(r => r.Type == ModelConstants.ResourceReceiveLocation);
                if (receiveLocations != null && receiveLocations.Any())
                {
                    foreach (var receiveLocation in receiveLocations)
                    {
                        var receiveLocationSource = (ReceiveLocation)receiveLocation.SourceObject;
                        var receiveLocationName   = receiveLocation.Name.FormatKey();

                        // Is there a pipeline?
                        if (receiveLocationSource.ReceivePipeline != null)
                        {
                            var route     = new List <MessagingObject>();
                            var keyPrefix = $"{Model.MigrationTarget.MessageBus.Key}:{applicationName}:{receivePortName}:{receiveLocationName}";

                            // Create endpoint adapter
                            route.Add(CreateReceiveEndpoint(keyPrefix, sourceApplication, targetApplication, receivePortSource, receiveLocationSource));

                            // Create the intermediaries for the pipeline
                            route.AddRange(CreateReceivePipelineIntermediaries(keyPrefix, sourceApplication, receiveLocationSource.ReceivePipeline, receiveLocationSource.ReceivePipelineCustomConfiguration));

                            // If there is a map, create the intermediary
                            if (receivePortSource.Transforms != null && receivePortSource.Transforms.Any())
                            {
                                // Find map resource items
                                var transforms = receivePort.FindRelatedResourcesByType(Model, ResourceRelationshipType.ReferencesTo, ModelConstants.ResourceMap);

                                // Add to route
                                var intermediary = CreateMapIntermediary(keyPrefix, targetApplication, transforms);
                                if (intermediary != null)
                                {
                                    route.Add(intermediary);
                                }
                            }
                            else
                            {
                                _logger.LogTrace(TraceMessages.NoReceiveMapSpecifiedOnReceivePort, RuleName, receivePortSource.Name, receiveLocationSource.Name);
                            }

                            // Check the route for interchange batch handling
                            var handleBatches = route.Any(s => s.Properties.ContainsKey(ModelConstants.HandleBatches) && (bool)s.Properties[ModelConstants.HandleBatches]);
                            if (handleBatches)
                            {
                                // Need to add intermediaries for batch handling (regardless of recoverable interchange processing, all routes will
                                // go through the content based router, but if batch failures must be handled as a unit, then messages in an
                                // interchange will go via a queue used to aggregate messages back into a batch to see if the batch failed, before
                                // being split again and sent to the message box topic.
                                route.AddRange(CreateInterchangeHandlingIntermediaries(keyPrefix));
                            }

                            // Create the message agent intermediaries
                            route.AddRange(CreateMessageAgentIntermediaries(keyPrefix, _messageBoxChannelKey, false, null));

                            // Binds the route by adding routing slip router intermediaries between the intermediaries in the receive port
                            var boundRoute = BindRoute(keyPrefix, targetApplication, receivePortSource, route);

                            // Binds the channels between the endpoint and intermediaries up to the message box (topic channel)
                            BindChannels(keyPrefix, targetApplication, receivePortSource, boundRoute);

                            // Add a new route for interchange batch completion handling, if required
                            if (handleBatches)
                            {
                                // Need to add interchange aggregation for batch failure handling as an atomic unit (recoverable interchange
                                // processing = false).  If batch succeeds and the messages in the batch can be published, then it goes back through
                                // a splitter for the messages to be published individually to the message box, otherwise the aggregated message is
                                // sent to the suspend queue channel.  The aggregator is an Activator intermediary as it triggers off the interchange
                                // channel, so this is treated as its own route with routing slip.  In this instance, the content based router won't
                                // route to the content promoter and the route ends with the main scenario route before it gets to the content promoter.
                                BuildInterchangeAggregationRoute(keyPrefix, targetApplication, receivePortSource, receiveLocationSource);
                            }

                            // If port is two way, check for reverse path and add a new route if required.
                            if (receivePortSource.IsTwoWay)
                            {
                                AnalyzeReceivePortResponse(keyPrefix, sourceApplication, targetApplication, receivePortSource, receiveLocation);
                            }

                            scenarios++;
                        }
                        else
                        {
                            _logger.LogError(ErrorMessages.ReceivePipelineNotSetInReceiveLocation, receiveLocation.Name);
                            Context.Errors.Add(new ErrorMessage(string.Format(CultureInfo.CurrentCulture, ErrorMessages.ReceivePipelineNotSetInReceiveLocation, receiveLocation.Name)));
                        }
                    }
                }
            }

            if (scenarios > 0)
            {
                _logger.LogDebug(TraceMessages.FoundReceivePortScenariosInApplication, RuleName, scenarios, sourceApplication.Name);
            }
            else
            {
                _logger.LogDebug(TraceMessages.NoReceivePortsFoundInApplication, RuleName, sourceApplication.Name);
            }

            await Task.CompletedTask.ConfigureAwait(false);
        }