private async Task <(EndPointAddress endPoint, string securityToken)> AddClientCoreAsync(CancellationToken cancellation)
        {
            var now                     = _dateTimeProvider.GetCurrentTime();
            var securityToken           = Guid.NewGuid().ToString();
            var leaseEnd                = now + Timeout;
            var securityTokenBytesCount = Encoding.UTF8.GetByteCount(securityToken);

            using (ArrayPool <byte> .Shared.Rent(8 + 4 + securityTokenBytesCount, out var bytes))
            {
                var payloadLength = EncodePayload(bytes, securityToken.AsSpan(), leaseEnd);
                var payload       = bytes.AsMemory().Slice(start: 0, payloadLength);

                EndPointAddress endPoint;
                do
                {
                    endPoint = AllocateEndPointAddress();
                    var path = GetPath(endPoint);

                    try
                    {
                        await _coordinationManager.CreateAsync(path, payload, cancellation : cancellation);

                        _logger?.LogDebug($"Assigning end-point '{endPoint.ToString()}' to recently connected client.");

                        break;
                    }
                    catch (DuplicateEntryException) // TODO: Add a TryCreateAsync method to the coordination service.
                    {
                        continue;
                    }
                }while (cancellation.ThrowOrContinue());

                return(endPoint, securityToken);
            }
        }
Beispiel #2
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);
            }
        }