Skip to content

Commit 8a11904

Browse files
AVaksmanGautamSharda
authored andcommitted
chore: remove paginator dependency and use gapic to return streams for paginated calls instead (#762)
1 parent ce41186 commit 8a11904

6 files changed

Lines changed: 324 additions & 73 deletions

File tree

handwritten/bigtable/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
"api-documenter": "api-documenter yaml --input-folder=temp"
4848
},
4949
"dependencies": {
50-
"@google-cloud/paginator": "^3.0.0",
5150
"@google-cloud/projectify": "^2.0.0",
5251
"@google-cloud/promisify": "^2.0.0",
5352
"arrify": "^2.0.0",

handwritten/bigtable/src/index.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -750,16 +750,20 @@ export class Bigtable {
750750
});
751751
};
752752

753+
const gapicStreamingMethods = {listTablesStream: true};
754+
753755
if (isStreamMode) {
754756
stream = streamEvents(new PassThrough({objectMode: true}));
755757
stream.abort = () => {
756758
if (gaxStream && gaxStream.cancel) {
757759
gaxStream.cancel();
758760
}
759761
};
760-
761-
stream.once('reading', makeRequestStream);
762-
762+
if (config.method! in gapicStreamingMethods) {
763+
stream.once('reading', makeGapicStreamRequest);
764+
} else {
765+
stream.once('reading', makeRequestStream);
766+
}
763767
return stream;
764768
} else {
765769
makeRequestCallback();
@@ -805,6 +809,21 @@ export class Bigtable {
805809
.pipe(stream);
806810
});
807811
}
812+
813+
function makeGapicStreamRequest() {
814+
prepareGaxRequest((err, requestFn) => {
815+
if (err) {
816+
stream.destroy(err);
817+
return;
818+
}
819+
gaxStream = requestFn!();
820+
gaxStream
821+
.on('error', (err: Error) => {
822+
stream.destroy(err);
823+
})
824+
.pipe(stream);
825+
});
826+
}
808827
}
809828

810829
/**

handwritten/bigtable/src/instance.ts

Lines changed: 67 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import {paginator, ResourceStream} from '@google-cloud/paginator';
1615
import {promisifyAll} from '@google-cloud/promisify';
16+
import {Transform} from 'stream';
1717
import arrify = require('arrify');
1818
import * as is from 'is';
19+
// eslint-disable-next-line @typescript-eslint/no-var-requires
20+
const pumpify = require('pumpify');
21+
1922
import snakeCase = require('lodash.snakecase');
2023
import {
2124
AppProfile,
@@ -155,7 +158,6 @@ export class Instance {
155158
id: string;
156159
name: string;
157160
metadata?: google.bigtable.admin.v2.IInstance;
158-
getTablesStream!: (options?: GetTablesOptions) => ResourceStream<Table>;
159161
constructor(bigtable: Bigtable, id: string) {
160162
this.bigtable = bigtable;
161163

@@ -905,6 +907,68 @@ Please use the format 'my-instance' or '${bigtable.projectName}/instances/my-ins
905907
);
906908
}
907909

910+
/**
911+
* Get {@link Table} objects for all the tables in your Cloud Bigtable
912+
* instance as a readable object stream.
913+
*
914+
* @param {object} [options] Query object. See
915+
* {@link Instance#getTables} for a complete list of options.
916+
* @returns {stream}
917+
*
918+
* @example
919+
* const {Bigtable} = require('@google-cloud/bigtable');
920+
* const bigtable = new Bigtable();
921+
* const instance = bigtable.instance('my-instance');
922+
*
923+
* instance.getTablesStream()
924+
* .on('error', console.error)
925+
* .on('data', function(table) {
926+
* // table is a Table object.
927+
* })
928+
* .on('end', () => {
929+
* // All tables retrieved.
930+
* });
931+
*
932+
* //-
933+
* // If you anticipate many results, you can end a stream early to prevent
934+
* // unnecessary processing and API requests.
935+
* //-
936+
* instance.getTablesStream()
937+
* .on('data', function(table) {
938+
* this.end();
939+
* });
940+
*/
941+
getTablesStream(options: GetTablesOptions = {}): NodeJS.ReadableStream {
942+
const reqOpts = Object.assign({}, options, {
943+
parent: this.name,
944+
view: Table.VIEWS[options.view || 'unspecified'],
945+
});
946+
947+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
948+
delete (reqOpts as any).gaxOptions;
949+
950+
// eslint-disable-next-line @typescript-eslint/no-this-alias
951+
const self = this;
952+
const transformToTable = (
953+
chunk: google.bigtable.admin.v2.ITable,
954+
enc: string,
955+
callback: Function
956+
) => {
957+
const table = self.table(chunk.name!.split('/').pop()!);
958+
table.metadata = chunk;
959+
callback(null, table);
960+
};
961+
return pumpify.obj([
962+
this.bigtable.request({
963+
client: 'BigtableTableAdminClient',
964+
method: 'listTablesStream',
965+
reqOpts,
966+
gaxOpts: options.gaxOptions,
967+
}),
968+
new Transform({objectMode: true, transform: transformToTable}),
969+
]);
970+
}
971+
908972
setIamPolicy(
909973
policy: Policy,
910974
gaxOptions?: CallOptions
@@ -1104,52 +1168,13 @@ Please use the format 'my-instance' or '${bigtable.projectName}/instances/my-ins
11041168
}
11051169
}
11061170

1107-
/**
1108-
* Get {@link Table} objects for all the tables in your Cloud Bigtable
1109-
* instance as a readable object stream.
1110-
*
1111-
* @param {object} [query] Configuration object. See
1112-
* {@link Instance#getTables} for a complete list of options.
1113-
* @returns {stream}
1114-
*
1115-
* @example
1116-
* const {Bigtable} = require('@google-cloud/bigtable');
1117-
* const bigtable = new Bigtable();
1118-
* const instance = bigtable.instance('my-instance');
1119-
*
1120-
* instance.getTablesStream()
1121-
* .on('error', console.error)
1122-
* .on('data', function(table) {
1123-
* // table is a Table object.
1124-
* })
1125-
* .on('end', () => {
1126-
* // All tables retrieved.
1127-
* });
1128-
*
1129-
* //-
1130-
* // If you anticipate many results, you can end a stream early to prevent
1131-
* // unnecessary processing and API requests.
1132-
* //-
1133-
* instance.getTablesStream()
1134-
* .on('data', function(table) {
1135-
* this.end();
1136-
* });
1137-
*/
1138-
Instance.prototype.getTablesStream = paginator.streamify<Table>('getTables');
1139-
1140-
/*! Developer Documentation
1141-
*
1142-
* These methods can be auto-paginated.
1143-
*/
1144-
paginator.extend(Instance, ['getTables']);
1145-
11461171
/*! Developer Documentation
11471172
*
11481173
* All async methods (except for streams) will return a Promise in the event
11491174
* that a callback is omitted.
11501175
*/
11511176
promisifyAll(Instance, {
1152-
exclude: ['appProfile', 'cluster', 'table'],
1177+
exclude: ['appProfile', 'cluster', 'table', 'getTablesStream'],
11531178
});
11541179

11551180
/**

handwritten/bigtable/system-test/bigtable.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ describe('Bigtable', () => {
160160
it('should retrieve a list of app profiles', async () => {
161161
const [appProfiles] = await INSTANCE.getAppProfiles();
162162
assert(appProfiles[0] instanceof AppProfile);
163+
assert(appProfiles.length > 0);
163164
});
164165

165166
it('should check if an app profile exists', async () => {

handwritten/bigtable/test/index.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,80 @@ describe('Bigtable', () => {
873873
requestStream.on('request', done);
874874
});
875875
});
876+
877+
describe('makeGapicStreamRequest', () => {
878+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
879+
let GAX_STREAM: any;
880+
const config = {
881+
client: 'client',
882+
method: 'listTablesStream',
883+
reqOpts: {
884+
a: 'b',
885+
c: 'd',
886+
},
887+
gaxOpts: {},
888+
};
889+
890+
beforeEach(() => {
891+
GAX_STREAM = new PassThrough();
892+
bigtable.api[config.client][config.method] = {
893+
bind() {
894+
return () => {
895+
return GAX_STREAM;
896+
};
897+
},
898+
};
899+
});
900+
901+
it('should expose an abort function', done => {
902+
GAX_STREAM.cancel = done;
903+
904+
const requestStream = bigtable.request(config);
905+
requestStream.emit('reading');
906+
requestStream.abort();
907+
});
908+
909+
it('should prepare the request once reading', done => {
910+
bigtable.api[config.client][config.method] = {
911+
bind(gaxClient: {}, reqOpts: {}, gaxOpts: {}) {
912+
assert.strictEqual(gaxClient, bigtable.api[config.client]);
913+
assert.deepStrictEqual(reqOpts, config.reqOpts);
914+
assert.strictEqual(gaxOpts, config.gaxOpts);
915+
setImmediate(done);
916+
return () => {
917+
return GAX_STREAM;
918+
};
919+
},
920+
};
921+
922+
const requestStream = bigtable.request(config);
923+
requestStream.emit('reading');
924+
});
925+
926+
it('should destroy the stream with prepare error', done => {
927+
const error = new Error('Error.');
928+
bigtable.getProjectId_ = (callback: Function) => {
929+
callback(error);
930+
};
931+
const requestStream = bigtable.request(config);
932+
requestStream.emit('reading');
933+
requestStream.on('error', (err: Error) => {
934+
assert.strictEqual(err, error);
935+
done();
936+
});
937+
});
938+
939+
it('should destroy the stream with GAX error', done => {
940+
const error = new Error('Error.');
941+
const requestStream = bigtable.request(config);
942+
requestStream.emit('reading');
943+
GAX_STREAM.emit('error', error);
944+
requestStream.on('error', (err: Error) => {
945+
assert.strictEqual(err, error);
946+
done();
947+
});
948+
});
949+
});
876950
});
877951

878952
describe('getProjectId_', () => {

0 commit comments

Comments
 (0)