public Task <EventStoreSubscription> FilteredSubscribeToAllAsync(bool resolveLinkTos, Filter filter,
                                                                         Func <EventStoreSubscription, ResolvedEvent, Task> eventAppeared,
                                                                         Func <EventStoreSubscription, Position, Task> checkpointReached, int checkpointInterval,
                                                                         Action <EventStoreSubscription, SubscriptionDropReason, Exception> subscriptionDropped = null,
                                                                         UserCredentials userCredentials = null)
        {
            Ensure.NotNull(eventAppeared, nameof(eventAppeared));
            Ensure.NotNull(filter, nameof(filter));
            Ensure.NotNull(checkpointReached, nameof(checkpointReached));

            if (checkpointInterval <= 0 && checkpointInterval != DontReportCheckpointReached)
            {
                throw new ArgumentOutOfRangeException(nameof(checkpointInterval));
            }

            var source = TaskCompletionSourceFactory.Create <EventStoreSubscription>();

            _handler.EnqueueMessage(new StartFilteredSubscriptionMessage(source, string.Empty, resolveLinkTos,
                                                                         checkpointInterval, filter, userCredentials, eventAppeared, checkpointReached,
                                                                         subscriptionDropped, Settings.MaxRetries, Settings.OperationTimeout));
            return(source.Task);
        }
        public async Task <AllEventsSlice> FilteredReadAllEventsBackwardAsync(Position position, int maxCount,
                                                                              bool resolveLinkTos, Filter filter, int maxSearchWindow, UserCredentials userCredentials = null)
        {
            Ensure.Positive(maxCount, "maxCount");
            Ensure.Positive(maxSearchWindow, nameof(maxSearchWindow));
            Ensure.GreaterThanOrEqualTo(maxSearchWindow, maxCount, nameof(maxSearchWindow));
            Ensure.NotNull(filter, nameof(filter));

            if (maxCount > ClientApiConstants.MaxReadSize)
            {
                throw new ArgumentException(string.Format(
                                                "Count should be less than {0}. For larger reads you should page.",
                                                ClientApiConstants.MaxReadSize));
            }

            var source    = TaskCompletionSourceFactory.Create <AllEventsSlice>();
            var operation = new FilteredReadAllEventsBackwardOperation(Settings.Log, source, position, maxCount,
                                                                       resolveLinkTos, Settings.RequireLeader, maxSearchWindow, filter.Value, userCredentials);

            await EnqueueOperation(operation).ConfigureAwait(false);

            return(await source.Task.ConfigureAwait(false));
        }
        /// <summary>
        /// Sometimes, we need to manually send more requests:
        ///     - When more requests are added to the DicomClient
        ///     - When a pending request has completed, perhaps freeing up an async operations slot on the association
        /// </summary>
        private async Task KeepSendingUntilAllRequestsHaveCompletedAsync()
        {
            while (true)
            {
                var cancellationTaskCompletionSource = TaskCompletionSourceFactory.Create <bool>();
                using (_sendRequestsCancellationTokenSource.Token.Register(() => cancellationTaskCompletionSource.SetResult(true)))
                {
                    /*
                     * This event will be triggered when the DicomClientConnection believes it has finished its work by triggering the OnSendQueueEmpty event
                     */
                    var sendMoreRequests = _sendMoreRequests.WaitAsync();

                    /*
                     * This event will be triggered when the CancellationToken passed into SendAsync is cancelled
                     */
                    var onCancel = cancellationTaskCompletionSource.Task;

                    /*
                     * This event will be triggered when the pending queue becomes empty
                     */
                    var allRequestsHaveCompleted = _allRequestsHaveCompletedTaskCompletionSource.Task;

                    var winner = await Task.WhenAny(allRequestsHaveCompleted, sendMoreRequests, onCancel).ConfigureAwait(false);

                    if (winner == allRequestsHaveCompleted || winner == onCancel)
                    {
                        return;
                    }
                }

                try
                {
                    if (Interlocked.CompareExchange(ref _sending, 1, 0) == 0)
                    {
                        try
                        {
                            if (!_dicomClient.QueuedRequests.IsEmpty)
                            {
                                if (_numberOfSentRequests >= _maximumNumberOfRequestsPerAssociation)
                                {
                                    _dicomClient.Logger.Debug(
                                        $"[{this}] DICOM client has reached the maximum number of requests for this association and is still waiting for the sent requests to complete");
                                }
                                else
                                {
                                    _dicomClient.Logger.Debug($"[{this}] DICOM client has more queued requests, sending those now...");

                                    await SendRequests().ConfigureAwait(false);
                                }
                            }

                            if (Connection.IsSendNextMessageRequired)
                            {
                                _dicomClient.Logger.Debug($"[{this}] DICOM client connection still has unsent requests, sending those now...");

                                await Connection.SendNextMessageAsync().ConfigureAwait(false);
                            }
                        }
                        finally
                        {
                            Interlocked.Exchange(ref _sending, 0);
                        }
                    }
                }
                finally
                {
                    _sendMoreRequests.Reset();
                }
            }
        }
예제 #4
0
 public DicomClientConnectState(DicomClient dicomClient)
 {
     _dicomClient = dicomClient ?? throw new ArgumentNullException(nameof(dicomClient));
     _cancellationRequestedTaskCompletionSource = TaskCompletionSourceFactory.Create <bool>();
     _disposables = new List <IDisposable>();
 }