Skip to content

Commit

Permalink
feat: support map handle for DIREGAPIC Pagination (#1052)
Browse files Browse the repository at this point in the history
* add implementation and test

* remove console.log

* add type for tuple

* Add detail resource check
  • Loading branch information
summer-ji-eng committed Jul 13, 2021
1 parent 2c8e56d commit faab4c6
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 3 deletions.
11 changes: 9 additions & 2 deletions src/paginationCalls/pageDescriptor.ts
Expand Up @@ -143,7 +143,7 @@ export class PageDescriptor implements Descriptor {
const asyncIterable = {
[Symbol.asyncIterator]() {
let nextPageRequest: RequestType | null | undefined = request;
const cache: {}[] = [];
const cache: Array<ResponseType | [string, ResponseType]> = [];
return {
async next() {
if (cache.length > 0) {
Expand All @@ -159,7 +159,14 @@ export class PageDescriptor implements Descriptor {
nextPageRequest!,
options
)) as ResultTuple;
cache.push(...(result as ResponseType[]));
// For pagination response with protobuf map type, use tuple as representation.
if (result && !Array.isArray(result)) {
for (const [key, value] of Object.entries(result)) {
cache.push([key, value as ResponseType]);
}
} else {
cache.push(...(result as ResponseType[]));
}
if (cache.length === 0) {
++attempts;
if (attempts > maxAttemptsEmptyResponse) {
Expand Down
85 changes: 84 additions & 1 deletion test/unit/pagedIteration.ts
Expand Up @@ -23,7 +23,7 @@ import * as sinon from 'sinon';
import {PassThrough} from 'stream';
import * as streamEvents from 'stream-events';
import {PageDescriptor} from '../../src/paginationCalls/pageDescriptor';
import {APICallback, GaxCall} from '../../src/apitypes';
import {APICallback, GaxCall, RequestType} from '../../src/apitypes';
import {describe, it, beforeEach} from 'mocha';

import * as util from './utils';
Expand Down Expand Up @@ -473,3 +473,86 @@ describe('paged iteration', () => {
});
});
});

describe('REGAPIC Pagination', () => {
const pageSize = 3;
const pagesToStream = 5;
const descriptor = new PageDescriptor('pageToken', 'nextPageToken', 'items');
const retryOptions = util.createRetryOptions(0, 0, 0, 0, 0, 0, 100);
const createOptions = {
settings: {retry: retryOptions},
descriptor,
};
const response: RequestType = {
'regions/us-central1': {
warning: {
code: 'NO_RESULTS_ON_PAGE',
message:
"There are no results for scope 'regions/us-central1' on this page.",
},
},
'regions/us-east1': {
addresses: [
{
id: '5011754511478056813',
creationTimestamp: '2021-05-28T23:04:50.044-07:00',
name: 'test-address-0',
},
{
id: '1036412484008568684',
creationTimestamp: '2021-05-28T23:04:51.044-07:00',
name: 'test-address-1',
},
],
},
};

function func(
request: {pageToken?: number},
metadata: {},
options: {},
callback: APICallback
) {
const pageToken = request.pageToken || 0;
if (pageToken >= pageSize * pagesToStream) {
callback(null, {items: {}});
} else {
callback(null, {items: response, nextPageToken: pageToken + pageSize});
}
}

describe('use async tuple iterator', () => {
const spy = sinon.spy(func);
let apiCall: GaxCall;
beforeEach(() => {
apiCall = util.createApiCall(spy, createOptions);
});

async function iterableChecker(iterable: AsyncIterable<{} | undefined>) {
let counter = 0;
const resources = [];
for await (const resource of iterable) {
counter++;
resources.push(resource);
if (counter === 10) {
break;
}
}
return resources;
}

it('return an tuple iterable, count to 10', async () => {
const settings = new gax.CallSettings(
(createOptions && createOptions.settings) || {}
);
const resources = await iterableChecker(
descriptor.asyncIterate(apiCall, {}, settings)
);
assert.strictEqual(resources.length, 10);
for await (const [key, value] of resources as [string, ResponseType]) {
assert.ok(response.hasOwnProperty(key));
assert.strictEqual(value, response[key]);
}
});
});
});

0 comments on commit faab4c6

Please sign in to comment.