Exemple #1
0
        public void WithEarlierDeadline_SimpleSettingsNoDeadline()
        {
            CallSettings settings = CallSettings.FromHeader("name", "value");
            DateTime?    deadline = null;

            Assert.Same(settings, settings.WithEarlierDeadline(deadline, new FakeClock()));
        }
Exemple #2
0
        /// <summary>
        /// Asynchronously polls the operation until it is complete, returning the completed operation.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If this object already represents a completed operation, it is returned with no further RPCs.
        /// If <paramref name="metadataCallback"/> is non-null, the callback will be called with any metadata
        /// present before the result is returned.
        /// </para>
        /// <para>
        /// No guarantee is made as to which thread is used for metadata callbacks. However, each callback is
        /// performed synchronously: this method waits for the callback to complete before the operation is next polled.
        /// This guarantees that for a single call, metadata callbacks will never occur in parallel.
        /// </para>
        /// </remarks>
        /// <param name="pollSettings">The settings to use for repeated polling, or null
        /// to use the default poll settings (poll once every 10 seconds, forever).</param>
        /// <param name="callSettings">The call settings to apply on each call, or null for default settings.</param>
        /// <param name="metadataCallback">The callback to invoke with the metadata from each poll operation, even if the metadata is null.</param>
        /// <returns>The completed operation, which can then be checked for errors or a result.</returns>
        public Task <Operation <TResponse, TMetadata> > PollUntilCompletedAsync(
            PollSettings pollSettings           = null,
            CallSettings callSettings           = null,
            Action <TMetadata> metadataCallback = null)
        {
            if (IsCompleted)
            {
                metadataCallback?.Invoke(Metadata);
                return(Task.FromResult(this));
            }

            // We need to work out the effective timing so that we can truncate any deadline, but anything else
            // that's in the effective call settings can be left to the normal merging process. In particular,
            // we don't want to include the header mutation that adds the version header, as otherwise we'll end up
            // including it twice.
            var effectiveTiming = Client.GetEffectiveCallSettingsForGetOperation(callSettings)?.Timing;

            callSettings = callSettings.WithCallTiming(effectiveTiming);
            Func <DateTime?, Task <Operation <TResponse, TMetadata> > > pollAction =
                async deadline =>
            {
                var result = await PollOnceAsync(callSettings.WithEarlierDeadline(deadline, Client.Clock)).ConfigureAwait(false);

                metadataCallback?.Invoke(result.Metadata);
                return(result);
            };

            return(Polling.PollRepeatedlyAsync(
                       pollAction, o => o.IsCompleted,
                       Client.Clock, Client.Scheduler, pollSettings ?? Client.DefaultPollSettings ?? s_defaultPollSettings,
                       callSettings?.CancellationToken ?? CancellationToken.None));
        }
Exemple #3
0
        public void WithEarlierDeadline_NoSettingsNoDeadline()
        {
            CallSettings settings = null;
            DateTime?    deadline = null;

            Assert.Null(settings.WithEarlierDeadline(deadline, new FakeClock()));
        }
Exemple #4
0
        /// <summary>
        /// Asynchronously polls the operation until it is complete, returning the completed operation.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If this object already represents a completed operation, it is returned with no further RPCs.
        /// If <paramref name="metadataCallback"/> is non-null, the callback will be called with any metadata
        /// present before the result is returned.
        /// </para>
        /// <para>
        /// No guarantee is made as to which thread is used for metadata callbacks. However, each callback is
        /// performed synchronously: this method waits for the callback to complete before the operation is next polled.
        /// This guarantees that for a single call, metadata callbacks will never occur in parallel.
        /// </para>
        /// </remarks>
        /// <param name="pollSettings">The settings to use for repeated polling, or null
        /// to use the default poll settings (poll once every 10 seconds, forever).</param>
        /// <param name="callSettings">The call settings to apply on each call, or null for default settings.</param>
        /// <param name="metadataCallback">The callback to invoke with the metadata from each poll operation, even if the metadata is null.</param>
        /// <returns>The completed operation, which can then be checked for errors or a result.</returns>
        public Task <Operation <TResponse, TMetadata> > PollUntilCompletedAsync(
            PollSettings pollSettings           = null,
            CallSettings callSettings           = null,
            Action <TMetadata> metadataCallback = null)
        {
            if (IsCompleted)
            {
                metadataCallback?.Invoke(Metadata);
                return(Task.FromResult(this));
            }
            callSettings = Client.GetEffectiveCallSettingsForGetOperation(callSettings);
            Func <DateTime?, Task <Operation <TResponse, TMetadata> > > pollAction =
                async deadline =>
            {
                var result = await PollOnceAsync(callSettings.WithEarlierDeadline(deadline, Client.Clock)).ConfigureAwait(false);

                metadataCallback?.Invoke(result.Metadata);
                return(result);
            };

            return(Polling.PollRepeatedlyAsync(
                       pollAction, o => o.IsCompleted,
                       Client.Clock, Client.Scheduler, pollSettings ?? Client.DefaultPollSettings ?? s_defaultPollSettings,
                       callSettings?.CancellationToken ?? CancellationToken.None));
        }
Exemple #5
0
        /// <summary>
        /// Polls the operation until it is complete, returning the completed operation.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If this object already represents a completed operation, it is returned with no further RPCs.
        /// If <paramref name="metadataCallback"/> is non-null, the callback will be called with any metadata
        /// present before the result is returned.
        /// </para>
        /// <para>
        /// Each callback is performed synchronously: this method waits for the callback to complete before the operation is next polled.
        /// This guarantees that for a single call, metadata callbacks will never occur in parallel.
        /// </para>
        /// </remarks>
        /// <param name="pollSettings">The settings to use for repeated polling, or null
        /// to use the default poll settings (poll once every 10 seconds, forever).</param>
        /// <param name="callSettings">The call settings to apply on each call, or null for default settings.</param>
        /// <param name="metadataCallback">The callback to invoke with the metadata from each poll operation, even if the metadata is null.</param>
        /// <returns>The completed operation, which can then be checked for errors or a result.</returns>
        public Operation <TResponse, TMetadata> PollUntilCompleted(
            PollSettings pollSettings           = null,
            CallSettings callSettings           = null,
            Action <TMetadata> metadataCallback = null)
        {
            if (IsCompleted)
            {
                metadataCallback?.Invoke(Metadata);
                return(this);
            }
            callSettings = Client.GetEffectiveCallSettingsForGetOperation(callSettings);

            Func <DateTime?, Operation <TResponse, TMetadata> > pollAction =
                deadline =>
            {
                var result = PollOnce(callSettings.WithEarlierDeadline(deadline, Client.Clock));
                metadataCallback?.Invoke(result.Metadata);
                return(result);
            };

            return(Polling.PollRepeatedly(
                       pollAction, o => o.IsCompleted,
                       Client.Clock, Client.Scheduler, pollSettings ?? Client.DefaultPollSettings ?? s_defaultPollSettings,
                       callSettings?.CancellationToken ?? CancellationToken.None));
        }
Exemple #6
0
        public void WithEarlierDeadline_DeadlineIsLaterThanExistingDeadline()
        {
            // Use a cancellation token to emphasize that it's not just the timing.
            var          token    = new CancellationTokenSource().Token;
            CallSettings settings = CallSettings.FromCancellationToken(token)
                                    .WithDeadline(new DateTime(10L, DateTimeKind.Utc));
            DateTime?deadline = new DateTime(20L, DateTimeKind.Utc);

            Assert.Same(settings, settings.WithEarlierDeadline(deadline, new FakeClock()));
        }
Exemple #7
0
        public void WithEarlierDeadline_NoSettingsWithDeadline()
        {
            var          token    = new CancellationTokenSource().Token;
            CallSettings settings = null;
            DateTime?    deadline = new DateTime(1L, DateTimeKind.Utc);

            CallSettings newSettings = settings.WithEarlierDeadline(deadline, new FakeClock());

            Assert.Equal(deadline, newSettings.Expiration.Deadline);
        }
Exemple #8
0
        public void WithEarlierDeadline_DeadlineIsLaterThanExistingTimeout()
        {
            // Use a cancellation token to emphasize that it's not just the timing.
            var          token    = new CancellationTokenSource().Token;
            CallSettings settings = CallSettings.FromCancellationToken(token)
                                    .WithTimeout(TimeSpan.FromTicks(100));
            var      clock    = new FakeClock();
            DateTime?deadline = clock.GetCurrentDateTimeUtc() + TimeSpan.FromTicks(200);

            Assert.Same(settings, settings.WithEarlierDeadline(deadline, clock));
        }
Exemple #9
0
        public void WithEarlierDeadline_DeadlineIsLaterThanExistingRetryTotalExpiration()
        {
            var backoffSettings = new BackoffSettings(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), 2.0);
            // Use a cancellation token to emphasize that it's not just the timing.
            var          token    = new CancellationTokenSource().Token;
            var          timing   = CallTiming.FromRetry(new RetrySettings(backoffSettings, backoffSettings, Expiration.FromDeadline(new DateTime(100L, DateTimeKind.Utc))));
            CallSettings settings = CallSettings.FromCancellationToken(token)
                                    .WithCallTiming(timing);
            DateTime?deadline = new DateTime(200L, DateTimeKind.Utc);

            Assert.Same(settings, settings.WithEarlierDeadline(deadline, new FakeClock()));
        }
Exemple #10
0
        public void WithEarlierDeadline_DeadlineIsEarlierThanExistingDeadline()
        {
            // Use a cancellation token to emphasize that it's not just the timing.
            var          token    = new CancellationTokenSource().Token;
            CallSettings settings = CallSettings.FromCancellationToken(token)
                                    .WithCallTiming(CallTiming.FromExpiration(Expiration.FromDeadline(new DateTime(10L, DateTimeKind.Utc))));
            DateTime?deadline = new DateTime(1L, DateTimeKind.Utc);

            CallSettings newSettings = settings.WithEarlierDeadline(deadline, new FakeClock());

            Assert.Equal(deadline, newSettings.Timing.Expiration.Deadline);
            Assert.Equal(token, newSettings.CancellationToken);
        }
Exemple #11
0
        public void WithEarlierDeadline_DeadlineIsEarlierThanExistingTimeout()
        {
            // Use a cancellation token to emphasize that it's not just the timing.
            var          token    = new CancellationTokenSource().Token;
            CallSettings settings = CallSettings.FromCancellationToken(token)
                                    .WithTimeout(TimeSpan.FromTicks(200));
            var          clock       = new FakeClock();
            DateTime?    deadline    = clock.GetCurrentDateTimeUtc() + TimeSpan.FromTicks(100);
            CallSettings newSettings = settings.WithEarlierDeadline(deadline, new FakeClock());

            // New timing has a deadline rather than a timeout
            Assert.Equal(deadline, newSettings.Expiration.Deadline);
            Assert.Equal(token, newSettings.CancellationToken);
        }
        /// <summary>
        /// Polls the operation until it is complete, returning the completed operation.
        /// </summary>
        /// <remarks>
        /// If this object already represents a completed operation, it is returned immediately,
        /// with no further RPCs.
        /// </remarks>
        /// <param name="pollSettings">The settings to use for repeated polling, or null
        /// to use the default poll settings (poll once every 10 seconds, forever).</param>
        /// <param name="callSettings">The call settings to apply on each call, or null for default settings.</param>
        /// <returns>The completed operation, which can then be checked for errors or a result.</returns>
        public Operation <T> PollUntilCompleted(PollSettings pollSettings = null, CallSettings callSettings = null)
        {
            if (IsCompleted)
            {
                return(this);
            }
            callSettings = Client.GetEffectiveCallSettingsForGetOperation(callSettings);

            Func <DateTime?, Operation <T> > pollAction = deadline => PollOnce(callSettings.WithEarlierDeadline(deadline, Client.Clock));

            return(Polling.PollRepeatedly(
                       pollAction, o => o.IsCompleted,
                       Client.Clock, Client.Scheduler, pollSettings ?? s_defaultPollSettings,
                       callSettings?.CancellationToken ?? CancellationToken.None));
        }
Exemple #13
0
        public async Task CheckConsistencyAsync()
        {
            // TODO: When replication goes to beta or GA, having something cleaner available than what is below.

            // Snippet: CheckConsistencyAsync(TableName,string,CallSettings)
            // Additional: GenerateConsistencyTokenAsync(TableName,CallSettings)
            BigtableTableAdminClient adminClient = await BigtableTableAdminClient.CreateAsync();

            BigtableTableAdminSettings settings   = BigtableTableAdminSettings.GetDefault();
            CallSettings generateSettings         = settings.GenerateConsistencyTokenSettings;
            CallSettings checkConsistencySettings = settings.CheckConsistencySettings;

            // Create a consistency token for the table.
            TableName tableName = new TableName("[PROJECT]", "[INSTANCE]", "[TABLE]");
            GenerateConsistencyTokenResponse generateResponse =
                await adminClient.GenerateConsistencyTokenAsync(tableName, generateSettings);

            string consistencyToken = generateResponse.ConsistencyToken;

            // Check for consistency for 60 seconds at 10 second intervals.
            TimeSpan pollingTimeout  = TimeSpan.FromSeconds(60);
            TimeSpan pollingInterval = TimeSpan.FromSeconds(10);
            CheckConsistencyResponse checkConsistencyResponse =
                await Polling.PollRepeatedlyAsync(
                    deadline => adminClient.CheckConsistencyAsync(
                        tableName,
                        consistencyToken,
                        checkConsistencySettings.WithEarlierDeadline(deadline, settings.Clock)),
                    response => response.Consistent,
                    settings.Clock,
                    settings.Scheduler,
                    new PollSettings(Expiration.FromTimeout(pollingTimeout), pollingInterval),
                    checkConsistencySettings.CancellationToken ?? CancellationToken.None);

            if (checkConsistencyResponse.Consistent)
            {
                // Replication has caught up.
            }
            // End snippet
        }
Exemple #14
0
        /// <summary>
        /// Polls the operation until it is complete, returning the completed operation.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If this object already represents a completed operation, it is returned with no further RPCs.
        /// If <paramref name="metadataCallback"/> is non-null, the callback will be called with any metadata
        /// present before the result is returned.
        /// </para>
        /// <para>
        /// Each callback is performed synchronously: this method waits for the callback to complete before the operation is next polled.
        /// This guarantees that for a single call, metadata callbacks will never occur in parallel.
        /// </para>
        /// </remarks>
        /// <param name="pollSettings">The settings to use for repeated polling, or null
        /// to use the default poll settings (poll once every 10 seconds, forever).</param>
        /// <param name="callSettings">The call settings to apply on each call, or null for default settings.</param>
        /// <param name="metadataCallback">The callback to invoke with the metadata from each poll operation, even if the metadata is null.</param>
        /// <returns>The completed operation, which can then be checked for errors or a result.</returns>
        public Operation <TResponse, TMetadata> PollUntilCompleted(
            PollSettings pollSettings           = null,
            CallSettings callSettings           = null,
            Action <TMetadata> metadataCallback = null)
        {
            if (IsCompleted)
            {
                metadataCallback?.Invoke(Metadata);
                return(this);
            }

            // We need to work out the effective expiration so that we can truncate any deadline, but anything else
            // that's in the effective call settings can be left to the normal merging process. In particular,
            // we don't want to include the header mutation that adds the version header, as otherwise we'll end up
            // including it twice.
            var effectiveExpiration = Client.GetEffectiveCallSettingsForGetOperation(callSettings)?.Expiration;

            if (effectiveExpiration != null)
            {
                callSettings = callSettings.WithExpiration(effectiveExpiration);
            }
            // TODO: Retry settings?

            Func <DateTime?, Operation <TResponse, TMetadata> > pollAction =
                deadline =>
            {
                var result = PollOnce(callSettings.WithEarlierDeadline(deadline, Client.Clock));
                metadataCallback?.Invoke(result.Metadata);
                return(result);
            };

            return(Polling.PollRepeatedly(
                       pollAction, o => o.IsCompleted,
                       Client.Clock, Client.Scheduler, pollSettings ?? Client.DefaultPollSettings ?? s_defaultPollSettings,
                       callSettings?.CancellationToken ?? CancellationToken.None));
        }