Example #1
0
        static CancellationToken GetCombinedCancellationToken(ref CancellationTokenSource?combinedCts, NpgsqlTimeout timeout, CancellationToken cancellationToken)
        {
            var finalCt = cancellationToken;

            if (timeout.IsSet)
            {
                combinedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                combinedCts.CancelAfter((int)timeout.CheckAndGetTimeLeft().TotalMilliseconds);
                finalCt = combinedCts.Token;
            }

            return(finalCt);
        }
Example #2
0
        /// <summary>
        /// Utility that simplifies awaiting a task with a timeout. If the given task does not
        /// complete within <paramref name="timeout"/>, a <see cref="TimeoutException"/> is thrown.
        /// </summary>
        /// <param name="task">The task to be awaited</param>
        /// <param name="timeout">How much time to allow <paramref name="task"/> to complete before throwing a <see cref="TimeoutException"/></param>
        /// <returns>An awaitable task that represents the original task plus the timeout</returns>
        internal static async Task <T> WithTimeout <T>(this Task <T> task, NpgsqlTimeout timeout)
        {
            if (!timeout.IsSet)
            {
                return(await task);
            }
            var timeLeft = timeout.CheckAndGetTimeLeft();

            if (task != await Task.WhenAny(task, Task.Delay(timeLeft)))
            {
                throw new TimeoutException();
            }
            return(await task);
        }
        /// <summary>
        /// Called exactly once per multiplexing pool, when the first connection is opened, with two goals:
        /// 1. Load types and bind the pool-wide type mapper (necessary for binding parameters)
        /// 2. Cause any connection exceptions (e.g. bad username) to be thrown from NpgsqlConnection.Open
        /// </summary>
        internal async Task BootstrapMultiplexing(NpgsqlConnection conn, NpgsqlTimeout timeout, bool async, CancellationToken cancellationToken = default)
        {
            Debug.Assert(_multiplexing);

            var hasSemaphore = async
                ? await _bootstrapSemaphore !.WaitAsync(timeout.CheckAndGetTimeLeft(), cancellationToken)
                : _bootstrapSemaphore !.Wait(timeout.CheckAndGetTimeLeft(), cancellationToken);

            // We've timed out - calling Check, to throw the correct exception
            if (!hasSemaphore)
            {
                timeout.Check();
            }

            try
            {
                if (IsBootstrapped)
                {
                    return;
                }

                var connector = await conn.StartBindingScope(ConnectorBindingScope.Connection, timeout, async, cancellationToken);

                using var _ = Defer(static conn => conn.EndBindingScope(ConnectorBindingScope.Connection), conn);