예제 #1
0
        private async Task <MsgOp> DoRequestAsync(string subject, ReadOnlyMemory <byte> body, CancellationToken cancellationToken = default)
        {
            var replyToSubject = UniqueId.Generate();
            var taskComp       = new TaskCompletionSource <MsgOp>();

            using var _ = MsgOpStream
                          .WhereSubjectMatches(replyToSubject)
                          .SubscribeSafe(msg => taskComp.SetResult(msg), ex => taskComp.SetException(ex));

            using var cts = cancellationToken == default
                ? new CancellationTokenSource(_connectionInfo.RequestTimeoutMs)
                : CancellationTokenSource.CreateLinkedTokenSource(_cancellation.Token, cancellationToken);

            await using var __ = cts.Token.Register(() => taskComp.SetCanceled()).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            await _connection.WithWriteLockAsync(async (writer, arg) =>
            {
                var(subjectIn, bodyIn, replyToIn) = arg;
                var sid = UniqueId.Generate().AsMemory();

                await SubCmd.WriteAsync(writer, replyToIn, sid, ReadOnlyMemory <char> .Empty).ConfigureAwait(false);
                await UnsubCmd.WriteAsync(writer, sid, 1).ConfigureAwait(false);
                await writer.FlushAsync().ConfigureAwait(false);
                await PubCmd.WriteAsync(writer, subjectIn, replyToIn, bodyIn).ConfigureAwait(false);
                await writer.FlushAsync().ConfigureAwait(false);
            }, Tuple.Create(subject.AsMemory(), body, replyToSubject.AsMemory())).ConfigureAwait(false);

            return(await taskComp.Task.ConfigureAwait(false));
        }
예제 #2
0
        private Task DoSubAsync(SubscriptionInfo subscriptionInfo) =>
        _connection.WithWriteLockAsync(async(writer, arg) =>
        {
            var sid = arg.Id.AsMemory();

            await SubCmd.WriteAsync(writer, arg.Subject.AsMemory(), sid, arg.QueueGroup.AsMemory())
            .ConfigureAwait(false);

            if (arg.MaxMessages.HasValue)
            {
                await UnsubCmd.WriteAsync(writer, sid, arg.MaxMessages).ConfigureAwait(false);
            }

            await writer.FlushAsync().ConfigureAwait(false);
        }, subscriptionInfo);
예제 #3
0
        private async Task <MsgOp> DoRequestUsingInboxAsync(string subject, ReadOnlyMemory <byte> body, CancellationToken cancellationToken = default)
        {
            var requestId      = UniqueId.Generate();
            var replyToSubject = $"{_inboxAddress}.{requestId}";
            var taskComp       = new TaskCompletionSource <MsgOp>();

            if (!_outstandingRequests.TryAdd(requestId, taskComp))
            {
                throw NatsException.InitRequestError("Unable to initiate request.");
            }

            using var cts = cancellationToken == default
                ? new CancellationTokenSource(_connectionInfo.RequestTimeoutMs)
                : CancellationTokenSource.CreateLinkedTokenSource(_cancellation.Token, cancellationToken);

            await using var _ = cts.Token.Register(() =>
            {
                if (_outstandingRequests.TryRemove(requestId, out var ts))
                {
                    ts.TrySetCanceled();
                }
            }).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            await _connection.WithWriteLockAsync(async (writer, arg) =>
            {
                var(subjectIn, bodyIn, replyToIn) = arg;

                if (_inboxSubscription == null)
                {
                    SetupInboxSubscription();

                    await SubCmd.WriteAsync(
                        writer,
                        _inboxSubscription.SubscriptionInfo.Subject.AsMemory(),
                        _inboxSubscription.SubscriptionInfo.Id.AsMemory(),
                        _inboxSubscription.SubscriptionInfo.QueueGroup.AsMemory()).ConfigureAwait(false);
                }

                await PubCmd.WriteAsync(writer, subjectIn, replyToIn, bodyIn).ConfigureAwait(false);
                await writer.FlushAsync().ConfigureAwait(false);
            }, Tuple.Create(subject.AsMemory(), body, replyToSubject.AsMemory())).ConfigureAwait(false);

            return(await taskComp.Task.ConfigureAwait(false));
        }
예제 #4
0
        private Task DoSubAsync(SubscriptionInfo[] subscriptionInfos) =>
        _connection.WithWriteLockAsync(async(writer, arg) =>
        {
            foreach (var subscriptionInfo in arg)
            {
                var sid = subscriptionInfo.Id.AsMemory();

                await SubCmd.WriteAsync(writer, subscriptionInfo.Subject.AsMemory(), sid, subscriptionInfo.QueueGroup.AsMemory())
                .ConfigureAwait(false);

                if (subscriptionInfo.MaxMessages.HasValue)
                {
                    await UnsubCmd.WriteAsync(writer, sid, subscriptionInfo.MaxMessages).ConfigureAwait(false);
                }

                await writer.FlushAsync().ConfigureAwait(false);
            }
        }, subscriptionInfos);