示例#1
0
        public OnDemandClientChannelFactory(IEstablishedClientChannelBuilder channelBuilder)
        {
            if (channelBuilder == null)
            {
                throw new ArgumentNullException(nameof(channelBuilder));
            }

            ChannelBuilder = channelBuilder;
        }
        private IOnDemandClientChannel CreateOnDemandClientChannel(IEstablishedClientChannelBuilder establishedClientChannelBuilder)
        {
            IOnDemandClientChannel onDemandClientChannel;

            // Avoid the overhead of the MultiplexerClientChannel for a single connection
            if (ChannelCount == 1)
            {
                onDemandClientChannel = new OnDemandClientChannel(establishedClientChannelBuilder);
            }
            else
            {
                onDemandClientChannel = new MultiplexerClientChannel(establishedClientChannelBuilder, ChannelCount);
            }
            return(onDemandClientChannel);
        }
示例#3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OnDemandClientChannel"/> class.
        /// </summary>
        /// <param name="builder">The builder.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        public OnDemandClientChannel(IEstablishedClientChannelBuilder builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }
            if (builder.ChannelBuilder == null)
            {
                throw new ArgumentException("The specified builder is invalid", nameof(builder));
            }
            _builder   = builder;
            _semaphore = new SemaphoreSlim(1, 1);

            ChannelCreatedHandlers         = new List <Func <ChannelInformation, Task> >();
            ChannelDiscardedHandlers       = new List <Func <ChannelInformation, Task> >();
            ChannelCreationFailedHandlers  = new List <Func <FailedChannelInformation, Task <bool> > >();
            ChannelOperationFailedHandlers = new List <Func <FailedChannelInformation, Task <bool> > >();
        }
示例#4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiplexerClientChannel"/> class.
        /// </summary>
        /// <param name="builder">The channel builder.</param>
        /// <param name="count">The number of channels to create.</param>
        /// <param name="inputBufferSize">The input buffer bounded capacity.</param>
        /// <param name="outputBufferSize">The output buffer bounded capacity.</param>
        /// <param name="channelCommandProcessor">The workflow for processing commands.</param>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public MultiplexerClientChannel(
            IEstablishedClientChannelBuilder builder,
            int count            = 5,
            int inputBufferSize  = 1,
            int outputBufferSize = 1,
            IChannelCommandProcessor channelCommandProcessor = null)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }
            if (count <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            // Create observable collections to allow synchronization
            var channelCreatedHandlers         = new ObservableCollection <Func <ChannelInformation, Task> >();
            var channelDiscardedHandlers       = new ObservableCollection <Func <ChannelInformation, Task> >();
            var channelCreationFailedHandlers  = new ObservableCollection <Func <FailedChannelInformation, Task <bool> > >();
            var channelOperationFailedHandlers = new ObservableCollection <Func <FailedChannelInformation, Task <bool> > >();

            ChannelCreatedHandlers         = channelCreatedHandlers;
            ChannelDiscardedHandlers       = channelDiscardedHandlers;
            ChannelCreationFailedHandlers  = channelCreationFailedHandlers;
            ChannelOperationFailedHandlers = channelOperationFailedHandlers;

            // Global input buffers
            var inputOptions = new ExecutionDataflowBlockOptions()
            {
                BoundedCapacity        = inputBufferSize,
                MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
                EnsureOrdered          = false
            };

            _inputMessageBufferBlock      = new BufferBlock <Message>(inputOptions);
            _inputNotificationBufferBlock = new BufferBlock <Notification>(inputOptions);
            _channelCommandProcessor      = channelCommandProcessor ?? new ChannelCommandProcessor();
            // Uses the same channel command processor for all instances
            // to avoid problems with commands responses being received on different channels.
            builder.ChannelBuilder.WithChannelCommandProcessor(_channelCommandProcessor);
            _processCommandTransformBlock = new TransformBlock <Command, Command>(c =>
            {
                if (_channelCommandProcessor.TrySubmitCommandResult(c))
                {
                    return(null);
                }
                return(c);
            },
                                                                                  inputOptions);
            _inputCommandBufferBlock = new BufferBlock <Command>(inputOptions);
            _processCommandTransformBlock.LinkTo(_inputCommandBufferBlock, c => c != null);
            _processCommandTransformBlock.LinkTo(DataflowBlock.NullTarget <Command>(), c => c == null);

            // The global output buffer
            _outputBufferBlock = new BufferBlock <BufferedEnvelope>(new DataflowBlockOptions()
            {
                BoundedCapacity = outputBufferSize,
                EnsureOrdered   = false
            });

            // An output action block per channel
            _outputActionBlocks = new ActionBlock <BufferedEnvelope> [count];
            _channels           = new IOnDemandClientChannel[count];
            _listeners          = new IChannelListener[count];

            for (var i = 0; i < _channels.Length; i++)
            {
                // Add an instance suffix to the builder
                var currentBuilder = builder
                                     .Copy()
                                     .WithInstance($"{builder.Instance}-{i+1}");
                var channel = new OnDemandClientChannel(currentBuilder);

                // Synchronize the handlers
                AttachCollection(channelCreatedHandlers, channel.ChannelCreatedHandlers);
                AttachCollection(channelDiscardedHandlers, channel.ChannelDiscardedHandlers);
                AttachCollection(channelCreationFailedHandlers, channel.ChannelCreationFailedHandlers);
                AttachCollection(channelOperationFailedHandlers, channel.ChannelOperationFailedHandlers);

                // Setup the listener for the channel
                _listeners[i] = new DataflowChannelListener(
                    _inputMessageBufferBlock,
                    _inputNotificationBufferBlock,
                    _processCommandTransformBlock);

                // Create a single bounded action block for each channel
                _outputActionBlocks[i] = new ActionBlock <BufferedEnvelope>(
                    async e => await SendToChannelAsync(channel, e.Envelope).ConfigureAwait(false),
                    new ExecutionDataflowBlockOptions()
                {
                    BoundedCapacity = 1, MaxDegreeOfParallelism = 1
                });

                var channelId = i;
                _outputBufferBlock.LinkTo(
                    _outputActionBlocks[i],
                    new DataflowLinkOptions()
                {
                    PropagateCompletion = true
                },
                    e => e.ChannelId == channelId);

                _channels[i] = channel;
            }

            _semaphore = new SemaphoreSlim(1, 1);
        }
示例#5
0
 private void SubstituteEstablishedClientChannelBuilder()
 {
     EstablishedClientChannelBuilder = Substitute.For <IEstablishedClientChannelBuilder>();
 }