예제 #1
0
        public ILogicalEndPoint <TAddress> CreateLogicalEndPoint(EndPointAddress endPoint)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            if (_isDisposed != 0) // Volatile read op.
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            // We have to ensure that only a single logical end-point exists for each address at any given time.
            lock (_endPointsLock)
            {
                if (_endPoints == null)
                {
                    throw new ObjectDisposedException(GetType().FullName);
                }

                if (_endPoints.TryGetValue(endPoint, out _))
                {
                    throw new Exception("End point already present!"); // TODO
                }

                var logicalEndPoint = CreateLogicalEndPointInternal(endPoint);
                _endPoints.Add(endPoint, logicalEndPoint);
                return(logicalEndPoint);
            }
        }
예제 #2
0
        private IPhysicalEndPoint <TAddress> GetMultiplexPhysicalEndPoint(EndPointAddress endPoint)
        {
            var result = _endPointMultiplexer.GetPhysicalEndPoint("end-points/" + endPoint.ToString()); // TODO: This should be configurable

            Assert(result != null);
            return(result);
        }
예제 #3
0
        private LogicalEndPoint CreateLogicalEndPointInternal(EndPointAddress endPoint)
        {
            var physicalEndPoint = GetMultiplexPhysicalEndPoint(endPoint);
            var logger           = _loggerFactory?.CreateLogger <LogicalEndPoint>();

            return(new LogicalEndPoint(this, physicalEndPoint, endPoint, logger));
        }
        private async ValueTask <IDispatchResult> InternalDispatchAsync(
            DispatchDataDictionary dispatchData,
            bool publish,
            EndPointAddress endPoint,
            CancellationToken cancellation)
        {
            if (endPoint == await GetLocalEndPointAsync(cancellation))
            {
                var(result, _) = await TryDispatchLocalAsync(dispatchData, publish, allowRouteDescend : true, localDispatch : true, cancellation);

                return(result);
            }
            else
            {
                var route             = new Route(_typeConversion.SerializeType(dispatchData.MessageType));
                var serializedMessage = new Message();

                SerializeDispatchData(serializedMessage, dispatchData);

                var serializedResult = await _messageRouter.RouteAsync(route, serializedMessage, publish, endPoint, cancellation);

                var result = DeserializeDispatchResult(serializedResult);

                return(result);
            }
        }
예제 #5
0
        public async Task UnmapEndPointAsync(EndPointAddress endPoint, CancellationToken cancellation)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            var path = GetPath(endPoint);

            await _coordinationManager.DeleteAsync(path, recursive : true, cancellation : cancellation);
        }
예제 #6
0
        public async Task RemoveRoutesAsync(EndPointAddress endPoint, bool removePersistentRoutes, CancellationToken cancellation)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            var session      = (await _coordinationManager.GetSessionAsync(cancellation)).ToString();
            var path         = GetReversePath(session, endPoint);
            var reverseEntry = await _coordinationManager.GetAsync(path, cancellation);

            if (reverseEntry == null)
            {
                return;
            }

            var tasks = new List <Task>(capacity: reverseEntry.Children.Count);

            foreach (var reverseRouteEntry in await reverseEntry.GetChildrenEntriesAsync(cancellation))
            {
                var route     = new Route(reverseRouteEntry.Name.Segment.ConvertToString());
                var routePath = GetPath(route, endPoint, session);

                if (!removePersistentRoutes)
                {
                    using (var stream = reverseRouteEntry.OpenStream())
                        using (var reader = new BinaryReader(stream))
                        {
                            var registrationOptions = (RouteRegistrationOptions)reader.ReadInt32();

                            if (!registrationOptions.IncludesFlag(RouteRegistrationOptions.Transient))
                            {
                                continue;
                            }

                            var reverseRouteEntryDeletion = _coordinationManager.DeleteAsync(reverseRouteEntry.Path, recursive: true, cancellation: cancellation);
                            tasks.Add(reverseRouteEntryDeletion.AsTask());
                        }
                }

                var routeEntryDeletion = _coordinationManager.DeleteAsync(routePath, cancellation: cancellation);
                tasks.Add(routeEntryDeletion.AsTask());
            }

            await Task.WhenAll(tasks);

            if (removePersistentRoutes)
            {
                await _coordinationManager.DeleteAsync(path, recursive : true, cancellation : cancellation);
            }
        }
예제 #7
0
        public async Task RemoveRouteAsync(EndPointAddress endPoint, Route route, CancellationToken cancellation)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            var session = (await _coordinationManager.GetSessionAsync(cancellation)).ToString();
            var path    = GetPath(route, endPoint, session);
            await _coordinationManager.DeleteAsync(path, cancellation : cancellation);

            var reversePath = GetReversePath(session, endPoint, route);
            await _coordinationManager.DeleteAsync(reversePath, cancellation : cancellation);
        }
예제 #8
0
        public async ValueTask <IEnumerable <TAddress> > GetMapsAsync(EndPointAddress endPoint, CancellationToken cancellation)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            var endPointEntry = await GetLogicalAddressEntryAsync(endPoint, cancellation);

            Assert(endPointEntry != null);

            var entries = await endPointEntry.GetChildrenEntries().ToArray(cancellation);

            return(entries.Select(p => _addressConversion.DeserializeAddress(p.Value.ToArray())));
        }
예제 #9
0
        public RouteTarget(EndPointAddress endPoint, RouteRegistrationOptions registrationOptions)
        {
            if (endPoint == default)
            {
                this = default;
                return;
            }

            if (!registrationOptions.IsValid())
            {
                throw new ArgumentException("Invalid enum valid.", nameof(registrationOptions));
            }

            EndPoint            = endPoint;
            RegistrationOptions = registrationOptions;
        }
예제 #10
0
        public async Task AddRouteAsync(EndPointAddress endPoint, RouteRegistration routeRegistration, CancellationToken cancellation)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            if (routeRegistration == default)
            {
                throw new ArgumentDefaultException(nameof(routeRegistration));
            }

            var session           = (await _coordinationManager.GetSessionAsync(cancellation)).ToString();
            var entryCreationMode = EntryCreationModes.Default;

            if (routeRegistration.RegistrationOptions.IncludesFlag(RouteRegistrationOptions.Transient))
            {
                entryCreationMode |= EntryCreationModes.Ephemeral;
            }

            var reversePath = GetReversePath(session, endPoint, routeRegistration.Route);

            using (var stream = new MemoryStream(capacity: 4))
            {
                using (var writer = new BinaryWriter(stream, Encoding.UTF8, leaveOpen: true))
                {
                    writer.Write((int)routeRegistration.RegistrationOptions);
                }
                var payload = stream.ToArray();
                await _coordinationManager.CreateAsync(reversePath, payload, entryCreationMode, cancellation);
            }

            var path = GetPath(routeRegistration.Route, endPoint, session);

            using (var stream = new MemoryStream(capacity: 4 + 4 + endPoint.Utf8EncodedValue.Length))
            {
                using (var writer = new BinaryWriter(stream, Encoding.UTF8, leaveOpen: true))
                {
                    writer.Write((int)routeRegistration.RegistrationOptions);
                    writer.Write(endPoint);
                }
                var payload = stream.ToArray();
                // TODO: What to do if the entry already existed but with different options?
                await _coordinationManager.GetOrCreateAsync(path, payload, entryCreationMode, cancellation);
            }
        }
        public ValueTask <IDispatchResult> DispatchAsync(
            DispatchDataDictionary dispatchData,
            bool publish,
            EndPointAddress endPoint,
            CancellationToken cancellation = default)
        {
            if (dispatchData == null)
            {
                throw new ArgumentNullException(nameof(dispatchData));
            }

            if (endPoint != default)
            {
                return(InternalDispatchAsync(dispatchData, publish, endPoint, cancellation));
            }

            return(InternalDispatchAsync(dispatchData, publish, cancellation));
        }
예제 #12
0
        public IMessageRouter CreateMessageRouter(EndPointAddress endPoint, ISerializedMessageHandler serializedMessageHandler)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            if (serializedMessageHandler == null)
            {
                throw new ArgumentNullException(nameof(serializedMessageHandler));
            }

            if (_logicalEndPoint.EndPoint == endPoint)
            {
                return(CreateMessageRouterInternal(_logicalEndPoint, serializedMessageHandler));
            }

            var logicalEndPoint = _endPointManager.CreateLogicalEndPoint(endPoint);

            return(CreateMessageRouterInternal(logicalEndPoint, serializedMessageHandler));
        }
예제 #13
0
        public async Task MapEndPointAsync(EndPointAddress endPoint, TAddress address, CancellationToken cancellation)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            if (address == null)
            {
                throw new ArgumentNullException(nameof(address));
            }

            if (address.Equals(default(TAddress)))
            {
                throw new ArgumentDefaultException(nameof(address));
            }

            var session = (await _coordinationManager.GetSessionAsync(cancellation)).ToString();
            var path    = GetPath(endPoint, session);

            await _coordinationManager.GetOrCreateAsync(path, _addressConversion.SerializeAddress(address), EntryCreationModes.Ephemeral, cancellation);
        }
예제 #14
0
        public ILogicalEndPoint <TAddress> GetLogicalEndPoint(EndPointAddress endPoint)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            lock (_endPointsLock)
            {
                if (_endPoints == null)
                {
                    throw new ObjectDisposedException(GetType().FullName);
                }

                if (_endPoints.TryGetValue(endPoint, out var logicalEndPoint))
                {
                    return(logicalEndPoint);
                }

                return(null);
            }
        }
예제 #15
0
        public static void Write(this BinaryWriter writer, EndPointAddress endPointAddress)
        {
            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            if (endPointAddress == default)
            {
                writer.Write(0);
            }
            var utf8EncodedValue = endPointAddress.Utf8EncodedValue;

            writer.Write(utf8EncodedValue.Length);
            writer.Flush();

            if (utf8EncodedValue.Length > 0)
            {
                var stream = writer.BaseStream;
                stream.Write(utf8EncodedValue.Span);
            }
        }
예제 #16
0
        public async Task UnmapEndPointAsync(EndPointAddress endPoint, TAddress address, CancellationToken cancellation)
        {
            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            if (address == null)
            {
                throw new ArgumentNullException(nameof(address));
            }

            if (address.Equals(default(TAddress)))
            {
                throw new ArgumentDefaultException(nameof(address));
            }

            var endPointEntry = await GetLogicalAddressEntryAsync(endPoint, cancellation);

            var session = (await _coordinationManager.GetSessionAsync(cancellation)).ToString();
            var path    = GetPath(endPoint, session);

            await _coordinationManager.DeleteAsync(path, cancellation : cancellation);
        }
예제 #17
0
 public void Deconstruct(out EndPointAddress endPoint, out RouteRegistrationOptions registrationOptions)
 {
     endPoint            = EndPoint;
     registrationOptions = RegistrationOptions;
 }
예제 #18
0
 public static async Task HandleAsync(
     this ILogicalEndPointReceiveResult messageReceiveResult,
     Func <IMessage, EndPointAddress, CancellationToken, Task <(IMessage response, bool handled)> > handler,
예제 #19
0
 ILogicalEndPoint IEndPointManager.GetLogicalEndPoint(EndPointAddress endPoint)
 {
     return(GetLogicalEndPoint(endPoint));
 }
예제 #20
0
        private async ValueTask <(IMessage response, bool handled)> InternalRouteAsync(Route route, IMessage serializedMessage, bool publish, EndPointAddress endPoint, CancellationToken cancellation)
        {
            Assert(endPoint != default);

            var localEndPoint = await GetLocalEndPointAsync(cancellation);

            // This does short-circuit the dispatch to the remote end-point.
            // Any possible replicates do not get any chance to receive the message.
            // => Requests are kept local to the machine.
            if (endPoint == localEndPoint)
            {
                _logger?.LogDebug($"Message router for end-point '{localEndPoint}': Dispatching request message locally.");

                return(await RouteToLocalAsync(route, serializedMessage, publish, localDispatch : true, cancellation));
            }

            _logger?.LogDebug($"Message router for end-point '{localEndPoint}': Dispatching request message to remote end point '{endPoint}'.");

            // Remove all frames from other protocol stacks.
            serializedMessage.Trim(); // TODO

            // We do not want to override frames.
            Assert(serializedMessage.FrameIndex == serializedMessage.FrameCount - 1);

            EncodeMessage(serializedMessage, publish, localDispatch: false, route);

            var(response, handled) = await _logicalEndPoint.SendAsync(serializedMessage, endPoint, cancellation);

            _logger?.LogDebug($"Message router for end-point '{localEndPoint}': Processing response message."); // TODO

            response.Trim();                                                                                    // TODO

            return(response, handled);
        }
예제 #21
0
        public async ValueTask <IMessage> RouteAsync(Route route, IMessage serializedMessage, bool publish, EndPointAddress endPoint, CancellationToken cancellation)
        {
            if (route == null)
            {
                throw new ArgumentNullException(nameof(route));
            }

            if (serializedMessage == null)
            {
                throw new ArgumentNullException(nameof(serializedMessage));
            }

            if (endPoint == default)
            {
                throw new ArgumentDefaultException(nameof(endPoint));
            }

            try
            {
                using (var guard = await _disposeHelper.GuardDisposalAsync(cancellation))
                {
                    var(response, _) = await InternalRouteAsync(route, serializedMessage, publish, endPoint, cancellation);

                    return(response);
                }
            }
            catch (OperationCanceledException) when(_disposeHelper.IsDisposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }
        }
예제 #22
0
        private async Task <(IMessage response, bool handled)> HandleAsync(IMessage message, EndPointAddress remoteEndPoint, CancellationToken cancellation)
        {
            var localEndPoint = await GetLocalEndPointAsync(cancellation);

            var(publish, localDispatch, route) = DecodeMessage(message);

            _logger?.LogDebug($"End-point '{localEndPoint}': Processing request message.");
            return(await RouteToLocalAsync(route, message, publish, localDispatch, cancellation));
        }
예제 #23
0
 ILogicalEndPoint IEndPointManager.CreateLogicalEndPoint(EndPointAddress endPoint)
 {
     return(CreateLogicalEndPoint(endPoint));
 }
예제 #24
0
        private ValueTask <IEntry> GetLogicalAddressEntryAsync(EndPointAddress endPoint, CancellationToken cancellation)
        {
            var path = GetPath(endPoint);

            return(_coordinationManager.GetOrCreateAsync(path, ReadOnlyMemory <byte> .Empty, EntryCreationModes.Default, cancellation));
        }
예제 #25
0
 private static CoordinationEntryPath GetPath(EndPointAddress endPoint, string session)
 {
     return(_mapsRootPath.GetChildPath(endPoint.ToString(), session));
 }
예제 #26
0
 private static CoordinationEntryPath GetReversePath(string session, EndPointAddress endPoint, Route route)
 {
     return(_reverseRoutesRootPath.GetChildPath(session, endPoint.ToString(), route.ToString()));
 }
예제 #27
0
        private static CoordinationEntryPath GetPath(Route route, EndPointAddress endPoint, string session)
        {
            var uniqueEntryName = IdGenerator.GenerateId(endPoint.ToString(), session);

            return(_routesRootPath.GetChildPath(route.ToString(), uniqueEntryName));
        }
 public RemoteMessagingOptions()
 {
     LocalEndPoint = new EndPointAddress(Assembly.GetEntryAssembly().GetName().Name);
 }