Пример #1
0
        public async Task RetryAfterTotalExpiration()
        {
            var settings = new BigtableServiceApiSettings();

            // Don't allow for any time to retry.
            settings.MutateRowsSettings = CallSettings.FromExpiration(Expiration.FromTimeout(TimeSpan.Zero));

            var request = new MutateRowsRequest
            {
                Entries =
                {
                    Mutations.CreateEntry("a", Mutations.DeleteFromRow()),
                    Mutations.CreateEntry("b", Mutations.DeleteFromRow()),
                    Mutations.CreateEntry("c", Mutations.DeleteFromRow())
                }
            };
            var client = Utilities.CreateMutateRowsMockClient(
                request,
                entriesForInitialStream: new[]
            {
                Utilities.CreateMutateRowsResponseEntry(0, Code.Ok),
                Utilities.CreateMutateRowsResponseEntry(1, Code.DeadlineExceeded),
                Utilities.CreateMutateRowsResponseEntry(2, Code.Ok)
            },
                entriesForRetryStreams: new[]
            {
                // 1st retry response entries
                new[] { Utilities.CreateMutateRowsResponseEntry(0, Code.Ok) }
            },
                settings: settings);

            var exception = await Assert.ThrowsAsync <RpcException>(() => client.MutateRowsAsync(request));

            Assert.Equal(StatusCode.DeadlineExceeded, exception.StatusCode);
        }
Пример #2
0
 public static BigtableClient CreateMutateRowsMockClient(
     MutateRowsRequest initialRequest,
     MutateRowsResponse.Types.Entry[] entriesForInitialStream,
     MutateRowsResponse.Types.Entry[][] entriesForRetryStreams = null,
     BigtableServiceApiSettings settings = null) =>
 CreateMockClientForStreamingRpc(
     initialRequest,
     c => c.MutateRows(
         It.Is <MutateRowsRequest>(r => ReferenceEquals(r, initialRequest)),
         It.IsAny <CallSettings>()),
     c => c.MutateRows(
         It.IsAny <MutateRowsRequest>(),
         It.IsAny <CallSettings>()),
     entriesForInitialStream,
     entriesForRetryStreams,
     itemsToStream: entries => new MockMutateRowsStream(new MutateRowsResponse {
     Entries = { entries }
 }),
     validator: (request, response) =>
 {
     // Make sure the request is properly formulated for the mock stream being returned.
     if (request.Entries.Count != response.Responses.SelectMany(r => r.Entries).Count())
     {
         throw new InvalidOperationException("The specified request is invalid for the mock stream about to be returned.");
     }
 },
     settings);
Пример #3
0
        private static BigtableClient CreateMockClientForStreamingRpc <TRequest, TStream, TMockStream, TStreamItems>(
            TRequest initialRequest,
            Expression <Func <BigtableServiceApiClient, TStream> > initialSetup,
            Expression <Func <BigtableServiceApiClient, TStream> > retrySetup,
            TStreamItems[] entriesForInitialStream,
            TStreamItems[][] entriesForRetryStreams,
            Func <TStreamItems[], TMockStream> itemsToStream,
            Action <TRequest, TMockStream> validator,
            BigtableServiceApiSettings settings)
            where TMockStream : class, TStream
        {
            var mock = new Mock <BigtableServiceApiClient>();

            mock.SetupGet(x => x.DefaultSettings).Returns(settings);

            // Even though we want to setup the initial call last, we should call the stream conversion for it
            // first so `itemsToStream` is called in the order the streams will be returned, just in case the
            // order matters to the caller.
            var initialResponse = itemsToStream(entriesForInitialStream);

            var retryStreams = entriesForRetryStreams != null
                ? new Queue <TMockStream>(entriesForRetryStreams.Select(items => items == null ? null : itemsToStream(items)))
                : new Queue <TMockStream>();

            mock.Setup(retrySetup).Returns <TRequest, CallSettings>((request, callSettings) =>
            {
                Assert.NotEmpty(retryStreams);
                var respose = retryStreams.Dequeue();
                if (respose == null)
                {
                    throw new Grpc.Core.RpcException(
                        new Grpc.Core.Status(Grpc.Core.StatusCode.Unavailable, "Unavailable"));
                }
                validator?.Invoke(request, respose);
                return(respose);
            });

            // Setup the initial response last so the catch-all setup doesn't overwrite it.
            // Check for reference equality to retry requests that happen to be a duplicate of the original don't match here.
            mock.Setup(initialSetup).Returns <TRequest, CallSettings>((request, callSettings) =>
            {
                validator?.Invoke(request, initialResponse);
                return(initialResponse);
            });

            return(new BigtableClientImpl(mock.Object));
        }
        public async Task RetryingAfterTotalExpiration()
        {
            var settings = new BigtableServiceApiSettings();

            // Don't allow for any time to retry.
            settings.ReadRowsRetrySettings =
                settings.ReadRowsRetrySettings.WithTotalExpiration(
                    Expiration.FromTimeout(TimeSpan.Zero));

            var request = new ReadRowsRequest
            {
                Rows = RowSet.FromRowKeys("a", "b", "c")
            };
            var client = Utilities.CreateReadRowsMockClient(
                request,
                initialStreamResponse: new[]
            {
                new ReadRowsResponse
                {
                    Chunks =
                    {
                        CreateChunk("a", "cf1", "column1", "value1", commitRow: true)
                    }
                }
            },
                responsesForRetryStreams: new[]
            {
                null,     // A null entry will throw an Unavailable RpcException
                new []
                {
                    new ReadRowsResponse
                    {
                        Chunks =
                        {
                            CreateChunk("b", "cf1", "column2", "value2", commitRow: true)
                        }
                    }
                }
            },
                settings: settings);

            var exception = await Assert.ThrowsAsync <RpcException>(() => client.ReadRows(request).ToList());

            Assert.Equal(StatusCode.Unavailable, exception.StatusCode);
        }
Пример #5
0
        public BigtableFixtureBase()
        {
            GrpcInfo.EnableSubchannelCounting();

            string emulatorHost = Environment.GetEnvironmentVariable(EmulatorEnvironmentVariable);

            string projectId;
            string instanceId;

            if (!string.IsNullOrEmpty(emulatorHost))
            {
                projectId           = "emulator-test-project";
                EmulatorCallInvoker = new GcpCallInvoker(
                    emulatorHost,
                    ChannelCredentials.Insecure,
                    GrpcCoreAdapter.Instance.ConvertOptions(BigtableServiceApiSettings.GetDefault().CreateChannelOptions()));

                instanceId = "doesnt-matter";
            }
            else
            {
                projectId = Environment.GetEnvironmentVariable(TestProjectEnvironmentVariable);
                if (string.IsNullOrEmpty(projectId))
                {
                    throw new InvalidOperationException(
                              $"Please set either the {EmulatorEnvironmentVariable} or {TestProjectEnvironmentVariable} environment variable before running tests");
                }

                instanceId = Environment.GetEnvironmentVariable(TestInstanceEnvironmentVariable);
                if (string.IsNullOrEmpty(instanceId))
                {
                    throw new InvalidOperationException(
                              $"Please set the {TestInstanceEnvironmentVariable} environment variable before running non-emulator tests.");
                }
            }

            ProjectName  = new ProjectName(projectId);
            InstanceName = new InstanceName(projectId, instanceId);

            Task.Run(InitBigtableInstanceAndTable).Wait();
        }
Пример #6
0
        public static BigtableClient CreateReadRowsMockClient(
            ReadRowsRequest initialRequest,
            ReadRowsResponse[] initialStreamResponse,
            ReadRowsResponse[][] responsesForRetryStreams = null,
            bool errorAtEndOfLastStream         = false,
            BigtableServiceApiSettings settings = null)
        {
            MockReadRowsStream lastStream = null;
            var result = CreateMockClientForStreamingRpc(
                initialRequest,
                c => c.ReadRows(
                    It.Is <ReadRowsRequest>(r => ReferenceEquals(r, initialRequest)),
                    It.IsAny <CallSettings>()),
                c => c.ReadRows(
                    It.IsAny <ReadRowsRequest>(),
                    It.IsAny <CallSettings>()),
                initialStreamResponse,
                responsesForRetryStreams,
                itemsToStream: entries =>
                lastStream = new MockReadRowsStream(entries)
            {
                ShouldErrorAtEnd = true
            },
                validator: (request, response) =>
            {
                // Make sure the request is properly formulated for the mock stream being returned.
                // Each response chunk should be a continuation of a previous chunk or from a row
                // that was requested.
                if (!response.Responses.SelectMany(r => r.Chunks).All(
                        c => c.RowKey.IsEmpty || IsRequested(request, c.RowKey)))
                {
                    throw new InvalidOperationException("The specified request is invalid for the mock stream about to be returned.");
                }
            },
                settings);

            // All but the last stream should end with an RpcException which permits retrying with the
            // default RetrySettings so the higher level ReadRowsStream keeps retrying
            // (see `ShouldErrorAtEnd = true` above). The last stream should end normally, unless
            // errorAtEndOfLastStream is true, in which case it should end with an error as well.
            lastStream.ShouldErrorAtEnd = errorAtEndOfLastStream;

            return(result);

            bool IsRequested(ReadRowsRequest request, BigtableByteString rowKey)
            {
                return
                    (request.Rows.RowRanges.Any(IsInRange) ||
                     request.Rows.RowKeys.Contains((ByteString)rowKey));

                bool IsInRange(RowRange range)
                {
                    switch (range.StartKeyCase)
                    {
                    case RowRange.StartKeyOneofCase.StartKeyClosed:
                        if (rowKey < range.StartKeyClosed)
                        {
                            return(false);
                        }
                        break;

                    case RowRange.StartKeyOneofCase.StartKeyOpen:
                        if (rowKey <= range.StartKeyOpen)
                        {
                            return(false);
                        }
                        break;
                    }
                    if (!range.EndKeyClosed.IsEmpty)
                    {
                        switch (range.EndKeyCase)
                        {
                        case RowRange.EndKeyOneofCase.EndKeyClosed:
                            if (range.EndKeyClosed < rowKey)
                            {
                                return(false);
                            }
                            break;

                        case RowRange.EndKeyOneofCase.EndKeyOpen:
                            if (range.EndKeyOpen <= rowKey)
                            {
                                return(false);
                            }
                            break;
                        }
                    }
                    return(true);
                }
            }
        }