Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Storage] Async iter paging draft 3 #4

Closed
wants to merge 11 commits into from
87 changes: 77 additions & 10 deletions sdk/storage/storage-queue/samples/typescript/iterators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,88 @@ async function main() {
console.log(`List queues`);

// List queues
let iter1 = queueServiceClient.listQueues();
let i = 1;
for await (const item of iter1) {
console.log(`Queue${i}: ${item.name}`);
i++;
let marker: string | undefined = undefined;

let iter1 = queueServiceClient.listQueues();
for await (const items of iter1) {
for (const item of items!) {
console.log(`Queue${i}: ${item.name}`);
i++;
}
}

// Same as the previous example
i = 1;
for await (const items of queueServiceClient.listQueues()) {
for (const item of items!) {
console.log(`Queue${i}: ${item.name}`);
i++;
}
}

// List queues - generator syntax
let iter2 = await queueServiceClient.listQueues();
// Generator syntax .next()
i = 1;
let item = await iter2.next();
let iter2 = await queueServiceClient.listQueues()[Symbol.asyncIterator]();
let items2 = (await iter2.next()).value;
do {
console.log(`Queue${i++}: ${item.value.name}`);
item = await iter2.next();
} while (item.value);
for await (const item of items2!) {
console.log(`Queue${i}: ${item.name}`);
i++;
}
items2 = (await iter2.next()).value;
} while (items2);

// ////////////////////////////////
// /// Examples for .byPage() ///
// ////////////////////////////////

i = 1;
for await (const item1 of queueServiceClient.listQueues().byPage({})) {
item1.queueItems!.forEach((queueItem) => {
console.log(`Queue${i}: ${queueItem.name}`);
i++;
});
}

// Same as the previous example
i = 1;
for await (const item2 of queueServiceClient.listQueues().byPage({ pagesize: 20 })) {
item2.queueItems!.forEach((queueItem) => {
console.log(`Queue${i}: ${queueItem.name}`);
i++;
});
}

// Generator syntax .next()
i = 1;
let iter3 = queueServiceClient.listQueues().byPage({ pagesize: 2 });
let item3 = (await iter3.next()).value;
do {
for (const queueItem of item3.queueItems!) {
console.log(`Queue${i}: ${queueItem.name}`);
i++;
}
item3 = (await iter3.next()).value;
} while (item3);

// Passing marker as argument (similar to the previous example)
i = 1;
let iter4 = queueServiceClient.listQueues().byPage({ pagesize: 2 });
let item = (await iter4.next()).value;
// Prints 2 queuenames
for (const queueItem of item.queueItems!) {
console.log(`Queue${i}: ${queueItem.name}`);
i++;
}
marker = item.nextMarker;
iter4 = queueServiceClient.listQueues().byPage({ marker: marker, pagesize: 10 });
item = (await iter4.next()).value;
// Prints 10 queuenames
for (const queueItem of item.queueItems!) {
console.log(`Queue${i}: ${queueItem.name}`);
i++;
}
}

// An async method returns a Promise object, which is compatible with then().catch() coding style.
Expand Down
117 changes: 67 additions & 50 deletions sdk/storage/storage-queue/src/QueueServiceClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,56 +200,6 @@ export class QueueServiceClient extends StorageClient {
});
}

/**
* Iterates over queues under the specified account.
*
* @param {ServiceListQueuesSegmentOptions} [options={}] Options to list queues(optional)
* @returns {AsyncIterableIterator<Models.QueueItem>}
* @memberof QueueServiceClient
*
* @example
* let i = 1;
* for await (const item of queueServiceClient.listQueues()) {
* console.log(`Queue${i}: ${item.name}`);
* i++;
* }
*
* @example
* let iter1 = queueServiceClient.listQueues();
* let i = 1;
* for await (const item of iter1) {
* console.log(`Queue${i}: ${item.name}`);
* i++;
* }
*
* @example
* let iter2 = await queueServiceClient.listQueues();
* i = 1;
* let item = await iter2.next();
* do {
* console.log(`Queue${i++}: ${item.value.name}`);
* item = await iter2.next();
* } while (item.value);
*
*/
public async *listQueues(
options: ServiceListQueuesSegmentOptions = {}
): AsyncIterableIterator<Models.QueueItem> {
let marker = undefined;
const queueServiceClient = this;
const aborter = !options.abortSignal ? Aborter.none : options.abortSignal;
let listQueuesResponse;
do {
listQueuesResponse = await queueServiceClient.listQueuesSegment(marker, {
...options,
abortSignal: aborter
});

marker = listQueuesResponse.nextMarker;
yield* listQueuesResponse.queueItems;
} while (marker);
}

/**
* Returns a list of the queues under the specified account.
* @see https://docs.microsoft.com/en-us/rest/api/storageservices/list-queues1
Expand All @@ -276,4 +226,71 @@ export class QueueServiceClient extends StorageClient {
...options
});
}

async *listSegments(
marker: string | undefined = undefined,
options: ServiceListQueuesSegmentOptions = {}
): AsyncIterableIterator<Models.ServiceListQueuesSegmentResponse> {
let listQueuesResponse;
do {
listQueuesResponse = await this.listQueuesSegment(marker, options);
marker = listQueuesResponse.nextMarker;
yield await listQueuesResponse;
} while (marker);
}

async *listItems(
options: ServiceListQueuesSegmentOptions = {}
): AsyncIterableIterator<Models.QueueItem> {
let marker: string | undefined;
for await (const segment of this.listSegments(marker, options)) {
marker = segment.nextMarker;
yield* segment.queueItems;
}
}

public listQueues(options: ServiceListQueuesSegmentOptions = {}) {
const client = this;
let marker: string | undefined;
return {
[Symbol.asyncIterator]: function() {
return {
next: async function() {
let segment;
try {
segment = (await client.listSegments(marker, options).next()).value;
marker = segment.nextMarker;
if (segment.queueItems) {
return { done: false, value: segment.queueItems };
} else {
return { done: true };
}
} catch (error) {
return { done: true };
}
}
};
},
/**
*@param {string} [marker] A string value that identifies the portion of
* the list of queues to be returned with the next listing operation. The
* operation returns the NextMarker value within the response body if the
* listing operation did not return all queues remaining to be listed
* with the current page. The NextMarker value can be used as the value for
* the marker parameter in a subsequent call to request the next page of list
* items. The marker value is opaque to the client.
*@param {number} [pagesize] Number of items to be returned. Default value is `10`.
*/
byPage: ({
marker = undefined,
pagesize = 10
}: {
marker?: string | undefined;
pagesize?: number;
}) => {
options.maxresults = pagesize;
return this.listSegments(marker, options);
}
};
}
}