Skip to content

Commit 9d28eb0

Browse files
feywindgcf-owl-bot[bot]
authored andcommitted
tests: conformance test fixes 2 (#1770)
* tests: roll cumulative test fixes from https://github.com/googleapis/nodejs-bigtable/tree/conformance-fixes-2 (manually due to merging errors) * chore: remove empty file * tests: change 'closed' wording to match previously expected wording * tests: also handle the stream mode being closed already * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * tests: remove extraneous bigtable.close() call * tests: put back the other close line, and add a comment about why it looks duplicate --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 36e2a0f commit 9d28eb0

13 files changed

Lines changed: 150 additions & 101 deletions

File tree

handwritten/bigtable/src/index.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ export class Bigtable {
487487
static Cluster: Cluster;
488488
_metricsConfigManager: ClientSideMetricsConfigManager;
489489
admin: admin.BigtableAdmin;
490+
closed = false;
490491

491492
constructor(options: BigtableOptions = {}) {
492493
// Determine what scopes are needed.
@@ -904,6 +905,27 @@ export class Bigtable {
904905
let gaxStream: gax.CancellableStream;
905906
let stream: AbortableDuplex;
906907

908+
if (this.closed) {
909+
const error = Object.assign(
910+
new Error('The client has already been closed.'),
911+
{
912+
name: 'Closed',
913+
code: grpc.status.ABORTED,
914+
details: 'The client has already been closed.',
915+
metadata: new grpc.Metadata(),
916+
},
917+
);
918+
if (isStreamMode) {
919+
stream = streamEvents(new PassThrough({objectMode: true}));
920+
stream.abort = () => {};
921+
setImmediate(() => stream.destroy(error));
922+
return stream;
923+
} else {
924+
callback?.(error as ServiceError);
925+
return;
926+
}
927+
}
928+
907929
const prepareGaxRequest = (
908930
callback: (err: Error | null, fn?: Function) => void,
909931
) => {
@@ -1021,11 +1043,22 @@ export class Bigtable {
10211043
* Close all bigtable clients. New requests will be rejected but it will not
10221044
* kill connections with pending requests.
10231045
*/
1024-
close(): Promise<void[]> {
1046+
async close(): Promise<void[]> {
1047+
// Close all of the clients.
10251048
const combined = Object.keys(this.api).map(clientType =>
10261049
this.api[clientType].close(),
10271050
);
1028-
return Promise.all(combined);
1051+
const results = await Promise.all(combined);
1052+
1053+
// Clear them out of our cache.
1054+
Object.keys(this.api).forEach(clientType => {
1055+
delete this.api[clientType];
1056+
});
1057+
1058+
// Mark as closed.
1059+
this.closed = true;
1060+
1061+
return results;
10291062
}
10301063

10311064
/**

handwritten/bigtable/src/row.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {CallOptions} from 'google-gax';
3030
import {ServiceError} from 'google-gax';
3131
import {google} from '../protos/protos';
3232
import {RowDataUtils, RowProperties} from './row-data-utils';
33-
import {TabularApiSurface} from './tabular-api-surface';
33+
import {GetRowsOptions, TabularApiSurface} from './tabular-api-surface';
3434
import {getRowsInternal} from './utils/getRowsInternal';
3535
import {
3636
MethodName,
@@ -667,9 +667,10 @@ export class Row {
667667
filter = arrify(filter).concat(options.filter);
668668
}
669669

670-
const getRowsOptions = Object.assign({}, options, {
670+
const getRowsOptions: GetRowsOptions = Object.assign({}, options, {
671671
keys: [this.id],
672672
filter,
673+
limit: 1,
673674
});
674675

675676
const metricsCollector =

handwritten/bigtable/src/tabular-api-surface.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,11 @@ Please use the format 'prezzy' or '${instance.name}/tables/prezzy'.`);
476476
reqOpts,
477477
gaxOpts: Object.assign({}, gaxOptions),
478478
});
479+
if (!requestStream) {
480+
throw new Error(
481+
'Failed to create request stream -- is the client already closed?',
482+
);
483+
}
479484
metricsCollector.wrapRequest(requestStream);
480485
const stream = pumpify.obj([requestStream, rowKeysStream]);
481486
stream.on('end', () => {
Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +0,0 @@
1-
TestMutateRow_Generic_DeadlineExceeded\|
2-
TestMutateRow_Generic_CloseClient\|
3-
TestMutateRow_Generic_DeadlineExceeded\|
4-
TestReadModifyWriteRow_Generic_DeadlineExceeded\|
5-
TestReadRow_Generic_DeadlineExceeded\|
6-
TestMutateRows_Retry_WithRoutingCookie\|
7-
TestReadRow_Generic_DeadlineExceeded\|
8-
TestReadRow_Retry_WithRoutingCookie\|
9-
TestReadRow_Retry_WithRetryInfo\|
10-
TestReadRows_ReverseScans_FeatureFlag_Enabled\|
11-
TestReadRows_NoRetry_OutOfOrderError_Reverse\|
12-
TestReadRows_Retry_LastScannedRow_Reverse\|
13-
TestReadRows_Retry_WithRoutingCookie\|
14-
TestReadRows_Retry_WithRoutingCookie_MultipleErrorResponses\|
15-
TestReadRows_Retry_WithRetryInfo\|
16-
TestReadRows_Retry_WithRetryInfo_MultipleErrorResponse\|
17-
TestSampleRowKeys_Retry_WithRoutingCookie\|
18-
TestSampleRowKeys_Generic_CloseClient\|
19-
TestSampleRowKeys_Generic_Headers\|
20-
TestSampleRowKeys_NoRetry_NoEmptyKey\|

handwritten/bigtable/testproxy/services/close-client.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@
1414

1515
import {google} from '../protos/protos';
1616
import {ClientImplMaker, normalizeCallback} from './utils';
17+
import {closeBigtableClient} from './utils/bigtable-client';
1718
type ICloseClientRequest = google.bigtable.testproxy.ICloseClientRequest;
1819
type ICloseClientResponse = google.bigtable.testproxy.ICloseClientResponse;
1920

21+
import {log} from './utils/log';
22+
2023
export const closeClient: ClientImplMaker<
2124
ICloseClientRequest,
2225
ICloseClientResponse
@@ -26,8 +29,18 @@ export const closeClient: ClientImplMaker<
2629
const {clientId} = request;
2730
const bigtable = clientMap.get(clientId!);
2831

32+
log.info(
33+
'close client %s (%s)',
34+
clientId,
35+
bigtable ? 'exists' : "doesn't exist",
36+
);
37+
2938
if (bigtable) {
39+
// closeBigtableClient closes the BigtableClient, but not the Bigtable
40+
// object itself. We need to close the Bigtable object as well.
41+
await closeBigtableClient(bigtable);
3042
await bigtable.close();
43+
log.info('client %s closed', clientId);
3144
}
3245
return {};
3346
});

handwritten/bigtable/testproxy/services/create-client.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {google} from '../protos/protos';
1818
import * as grpc from '@grpc/grpc-js';
1919
import {Bigtable} from '../../src';
2020
import {createBigtableClient} from './utils/bigtable-client';
21+
import {log} from './utils/log';
2122

2223
function durationToMilliseconds(
2324
duration: google.protobuf.Duration | google.protobuf.IDuration,
@@ -68,6 +69,12 @@ export const createClient: ClientImplMaker<
6869
);
6970
}
7071

72+
log.info(
73+
'create client %s (%s)',
74+
clientId,
75+
clientMap.has(clientId) ? 'exists' : "doesn't exist",
76+
);
77+
7178
if (clientMap.has(clientId)) {
7279
throw Object.assign(new Error(`Client ${clientId} already exists`), {
7380
code: grpc.status.ALREADY_EXISTS,
@@ -100,6 +107,7 @@ export const createClient: ClientImplMaker<
100107
appProfileId: appProfileId!,
101108
clientConfig,
102109
};
110+
log.info('created bigtable client %s', clientId);
103111
const bigtable = new Bigtable(options);
104112
createBigtableClient(bigtable);
105113
clientMap.set(clientId!, bigtable);

handwritten/bigtable/testproxy/services/mutate-row.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,25 @@ export const mutateRow: ClientImplMaker<
3434
const appProfileId = bigtable.appProfileId;
3535
const client = getBigtableClient(bigtable);
3636

37-
await client.mutateRow({
38-
appProfileId,
39-
mutations,
40-
tableName,
41-
rowKey,
42-
});
37+
try {
38+
await client.mutateRow({
39+
appProfileId,
40+
mutations,
41+
tableName,
42+
rowKey,
43+
});
4344

44-
return {
45-
status: {code: grpc.status.OK, details: []},
46-
};
45+
return {
46+
status: {code: grpc.status.OK, details: []},
47+
};
48+
} catch (e) {
49+
const error = e as GoogleError;
50+
return {
51+
status: {
52+
code: error.code ? error.code : grpc.status.UNKNOWN,
53+
message: error.message,
54+
details: [],
55+
},
56+
};
57+
}
4758
});

handwritten/bigtable/testproxy/services/read-row.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
getRowResponse,
2525
getTableInfo,
2626
} from './utils';
27+
import {GoogleError} from 'google-gax';
2728

2829
export const readRow: ClientImplMaker<IReadRowRequest, IRowResult> = ({
2930
clientMap,
@@ -32,15 +33,27 @@ export const readRow: ClientImplMaker<IReadRowRequest, IRowResult> = ({
3233
const {clientId, rowKey, tableName} = rawRequest.request;
3334
const columns = {};
3435

35-
const bigtable = clientMap.get(clientId!);
36-
const table = getTableInfo(bigtable, tableName!);
37-
const row = table.row(rowKey!);
36+
try {
37+
const bigtable = clientMap.get(clientId!);
38+
const table = getTableInfo(bigtable, tableName!);
39+
const row = table.row(rowKey!);
3840

39-
const res = await row.get(columns);
40-
const firstRow = getRowResponse(res[0]);
41+
const res = await row.get(columns);
42+
const firstRow = getRowResponse(res[0]);
4143

42-
return {
43-
status: {code: grpc.status.OK, details: []},
44-
row: firstRow,
45-
};
44+
return {
45+
status: {code: grpc.status.OK, details: []},
46+
row: firstRow,
47+
};
48+
} catch (e) {
49+
const error = e as GoogleError;
50+
return {
51+
status: {
52+
code: error.code || grpc.status.FAILED_PRECONDITION,
53+
// e.details must be in an empty array for the test runner to return the status. This is tracked in b/383096533.
54+
details: [],
55+
message: error.message,
56+
},
57+
};
58+
}
4659
});

handwritten/bigtable/testproxy/services/read-rows.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ export const readRows: ClientImplMaker<IReadRowsRequest, IRowsResult> = ({
8787
const error = e as GoogleError;
8888
return {
8989
status: {
90-
code: error.code,
90+
// This might be zero/undefined if it's a disconnected client error.
91+
code: error.code || grpc.status.FAILED_PRECONDITION,
9192
// e.details must be in an empty array for the test runner to return the status. This is tracked in b/383096533.
9293
details: [],
9394
message: error.message,

handwritten/bigtable/testproxy/services/sample-row-keys.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414

1515
import * as grpc from '@grpc/grpc-js';
1616
import {GoogleError} from 'google-gax';
17-
import {getSRKRequest} from './utils/request/sampleRowKeys';
1817
import {ClientImplMaker, normalizeCallback} from './utils';
1918

2019
import {google} from '../protos/protos';
20+
import {log} from './utils/log';
2121
type ISampleRowKeysRequest = google.bigtable.testproxy.ISampleRowKeysRequest;
2222
type ISampleRowKeysResult = google.bigtable.testproxy.ISampleRowKeysResult;
2323

@@ -28,25 +28,32 @@ export const sampleRowKeys: ClientImplMaker<
2828
normalizeCallback(async rawRequest => {
2929
const {request} = rawRequest;
3030
const {clientId, request: sampleRowKeysRequest} = request;
31-
const {appProfileId, tableName} = sampleRowKeysRequest!;
31+
const {tableName} = sampleRowKeysRequest!;
3232

3333
const bigtable = clientMap.get(clientId!);
34-
bigtable.appProfileId = appProfileId!;
34+
35+
const [, , , instanceId, , tableId] = tableName!.split('/');
36+
const instance = bigtable.instance(instanceId);
37+
const table = instance.table(tableId);
3538

3639
try {
37-
const response = await getSRKRequest(bigtable, {appProfileId, tableName});
40+
const response = await table.sampleRowKeys();
3841

42+
log.info('sampleRowKeys response %o', response);
3943
return {
4044
status: {code: grpc.status.OK, details: []},
41-
response,
45+
samples: response[0].map(sample => ({
46+
rowKey: sample.key,
47+
offsetBytes: sample.offset,
48+
})),
4249
};
4350
} catch (e) {
4451
const error = e as GoogleError;
45-
console.error('Error:', error.code);
4652

4753
return {
4854
status: {
49-
code: error.code,
55+
// This might be zero/undefined if it's a disconnected client error.
56+
code: error.code || grpc.status.FAILED_PRECONDITION,
5057
details: [],
5158
},
5259
};

0 commit comments

Comments
 (0)