@azure/cosmos
Version:
Microsoft Azure Cosmos DB Service Node.js SDK for NOSQL API
134 lines • 5.44 kB
JavaScript
import { OrderByComparator } from "../orderByComparator.js";
import { FixedSizePriorityQueue } from "../../utils/fixedSizePriorityQueue.js";
import { getInitialHeader } from "../headerUtils.js";
/**
* @hidden
* Represents an endpoint in handling an non-streaming order by query.
*/
export class NonStreamingOrderByEndpointComponent {
executionContext;
sortOrders;
priorityQueueBufferSize;
offset;
emitRawOrderByPayload;
/**
* A priority queue to store the final sorted results.
*/
nonStreamingOrderByPQ;
/**
* Flag to determine if all results are fetched from backend and results can be returned from priority queue.
*/
isCompleted = false;
/**
* Represents an endpoint in handling an non-streaming order by query. For each processed orderby
* result it returns 'payload' item of the result
*
* @param executionContext - Underlying Execution Context
* @hidden
*/
constructor(executionContext, sortOrders, priorityQueueBufferSize, offset = 0, emitRawOrderByPayload = false) {
this.executionContext = executionContext;
this.sortOrders = sortOrders;
this.priorityQueueBufferSize = priorityQueueBufferSize;
this.offset = offset;
this.emitRawOrderByPayload = emitRawOrderByPayload;
const comparator = new OrderByComparator(this.sortOrders);
this.nonStreamingOrderByPQ = new FixedSizePriorityQueue((a, b) => {
return comparator.compareItems(b, a);
}, this.priorityQueueBufferSize);
}
/**
* Determine if there are still remaining resources to processs.
* @returns true if there is other elements to process in the NonStreamingOrderByEndpointComponent.
*/
hasMoreResults() {
return this.priorityQueueBufferSize > 0 && this.executionContext.hasMoreResults();
}
/**
* Fetches the next batch of the result from the target container.
* @param diagnosticNode - The diagnostic information for the request.
*/
async fetchMore(diagnosticNode) {
if (this.isCompleted) {
return {
result: undefined,
headers: getInitialHeader(),
};
}
let resHeaders = getInitialHeader();
// if size is 0, just return undefined to signal to more results. Valid if query is TOP 0 or LIMIT 0
if (this.priorityQueueBufferSize <= 0) {
return {
result: undefined,
headers: resHeaders,
};
}
// If there are more results in backend, keep filling pq.
if (this.executionContext.hasMoreResults()) {
const response = await this.executionContext.fetchMore(diagnosticNode);
resHeaders = response.headers;
if (response === undefined || response.result === undefined) {
this.isCompleted = true;
if (!this.nonStreamingOrderByPQ.isEmpty()) {
return this.buildFinalResultArray(resHeaders);
}
return { result: undefined, headers: resHeaders };
}
for (const item of response.result) {
if (item !== undefined) {
this.nonStreamingOrderByPQ.enqueue(item);
}
}
}
// If the backend has more results to fetch, return [] to signal that there are more results to fetch.
if (this.executionContext.hasMoreResults()) {
return {
result: [],
headers: resHeaders,
};
}
// If all results are fetched from backend, prepare final results
if (!this.executionContext.hasMoreResults() && !this.isCompleted) {
this.isCompleted = true;
return this.buildFinalResultArray(resHeaders);
}
// If pq is empty, return undefined to signal that there are no more results.
return {
result: undefined,
headers: resHeaders,
};
}
async buildFinalResultArray(resHeaders) {
// Set isCompleted to true.
this.isCompleted = true;
// Reverse the priority queue to get the results in the correct order
this.nonStreamingOrderByPQ = this.nonStreamingOrderByPQ.reverse();
// For offset limit case we set the size of priority queue to offset + limit
// and we drain offset number of items from the priority queue
while (this.offset < this.priorityQueueBufferSize &&
this.offset > 0 &&
!this.nonStreamingOrderByPQ.isEmpty()) {
this.nonStreamingOrderByPQ.dequeue();
this.offset--;
}
// If pq is not empty, return the result from pq.
if (!this.nonStreamingOrderByPQ.isEmpty()) {
const buffer = [];
if (this.emitRawOrderByPayload) {
while (!this.nonStreamingOrderByPQ.isEmpty()) {
buffer.push(this.nonStreamingOrderByPQ.dequeue());
}
}
else {
while (!this.nonStreamingOrderByPQ.isEmpty()) {
buffer.push(this.nonStreamingOrderByPQ.dequeue()?.payload);
}
}
return {
result: buffer,
headers: resHeaders,
};
}
}
}
//# sourceMappingURL=NonStreamingOrderByEndpointComponent.js.map