From deb4ee68aa8a39f8ef7cf73ba180fe222de3fc82 Mon Sep 17 00:00:00 2001 From: Don Cote Date: Wed, 29 Jun 2022 11:22:11 -0400 Subject: [PATCH] add paging --- js/README.md | 24 ++++++++++++++--- js/src/api.ts | 3 ++- .../integrations/query-integration/index.ts | 13 ++++++--- js/src/tests/endToEndTest.ts | 27 +++++++++++++++++++ js/src/tests/query-integration.test.ts | 6 +++++ js/src/tests/query-result-set-builder.test.ts | 2 ++ js/src/types/api/api-client.type.ts | 2 +- js/src/types/api/query-result-resp.type.ts | 2 ++ js/src/types/query-defaults.type.ts | 2 ++ js/src/types/query.type.ts | 4 +++ 10 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 js/src/tests/endToEndTest.ts diff --git a/js/README.md b/js/README.md index d1259e3..3c82a8f 100644 --- a/js/README.md +++ b/js/README.md @@ -84,6 +84,12 @@ type Query = { // The number of minutes until your query run times out timeoutMinutes?: number; + + // The number of records to return, defaults to 100000 + pageSize?: number; + + // The page number to return, defaults to 1 + pageNumber?: number; }; ``` @@ -97,6 +103,8 @@ const query: Query = { ttlMinutes: 60, cached: true, timeoutMinutes: 15, + pageNumber: 1, + pageSize: 10, }; ``` @@ -135,6 +143,12 @@ interface QueryResultSet { // The results of the query transformed as an array of objects records: QueryResultRecord[] | null; + // The number of records to return + pageSize: number; + + // The page number to return + pageNumber: number; + // If the query failed, this will contain the error error: | QueryRunRateLimitError @@ -154,10 +168,12 @@ Our query selected `nft_address`, `mint_price_eth`, and `mint_price_usd`. We can ```typescript result.records.map((record) => { - const nftAddress = record.nft_address - const mintPriceEth = record.mint_price_eth - const mintPriceUSD = = record.mint_price_usd - console.log(`address ${nftAddress} minted at a price of ${mintPrice} ETH or $${mintPriceUSD} USD`); + const nftAddress = record.nft_address; + const mintPriceEth = record.mint_price_eth; + const mintPriceUSD = record.mint_price_usd; + console.log( + `address ${nftAddress} minted at a price of ${mintPriceEth} ETH or $${mintPriceUSD} USD` + ); }); ``` diff --git a/js/src/api.ts b/js/src/api.ts index 6e64156..a60237f 100644 --- a/js/src/api.ts +++ b/js/src/api.ts @@ -64,10 +64,11 @@ export class API implements ApiClient { }; } - async getQueryResult(queryID: string): Promise { + async getQueryResult(queryID: string, pageNumber: number, pageSize: number): Promise { let result; try { result = await axios.get(this.getUrl(`queries/${queryID}`), { + params: { pageNumber: pageNumber, pageSize: pageSize }, method: "GET", headers: this.#headers, }); diff --git a/js/src/integrations/query-integration/index.ts b/js/src/integrations/query-integration/index.ts index b78da4f..e4bec18 100644 --- a/js/src/integrations/query-integration/index.ts +++ b/js/src/integrations/query-integration/index.ts @@ -28,6 +28,8 @@ const DEFAULTS: QueryDefaults = { cached: true, timeoutMinutes: 20, retryIntervalSeconds: 0.5, + pageSize: 100000, + pageNumber: 1, }; export class QueryIntegration { @@ -64,7 +66,9 @@ export class QueryIntegration { } const [getQueryResultJson, getQueryErr] = await this.#getQueryResult( - createQueryJson.token + createQueryJson.token, + query.pageNumber || 1, + query.pageSize || 100000, ); if (getQueryErr) { @@ -74,6 +78,7 @@ export class QueryIntegration { }); } + if (!getQueryResultJson) { return new QueryResultSetBuilder({ queryResultJson: null, @@ -132,6 +137,8 @@ export class QueryIntegration { async #getQueryResult( queryID: string, + pageNumber: number, + pageSize: number, attempts: number = 0 ): Promise< [ @@ -139,7 +146,7 @@ export class QueryIntegration { QueryRunTimeoutError | ServerError | UserError | null ] > { - const resp = await this.#api.getQueryResult(queryID); + const resp = await this.#api.getQueryResult(queryID, pageNumber, pageSize); if (resp.statusCode > 299) { if (resp.statusCode >= 400 && resp.statusCode <= 499) { let errorMsg = resp.statusMsg || "user input error"; @@ -183,6 +190,6 @@ export class QueryIntegration { return [null, new QueryRunTimeoutError(elapsedSeconds * 60)]; } - return this.#getQueryResult(queryID, attempts + 1); + return this.#getQueryResult(queryID, pageNumber, pageSize, attempts + 1); } } diff --git a/js/src/tests/endToEndTest.ts b/js/src/tests/endToEndTest.ts new file mode 100644 index 0000000..78fe193 --- /dev/null +++ b/js/src/tests/endToEndTest.ts @@ -0,0 +1,27 @@ +import { Flipside } from "../flipside"; +import { Query, QueryResultSet } from "../types"; + +const runIt = async (): Promise => { + // Initialize `Flipside` with your API key + const flipside = new Flipside( + "api-key-here", + "https://api.flipsidecrypto.com", + ); + + // Create a query object for the `query.run` function to execute + const query: Query = { + sql: "select nft_address, mint_price_eth, mint_price_usd from flipside_prod_db.ethereum_core.ez_nft_mints limit 100", + ttlMinutes: 10, + pageSize: 100, + pageNumber: 1 + }; + + // Send the `Query` to Flipside's query engine and await the results + const result: QueryResultSet = await flipside.query.run(query); + + if (!result || !result.records) throw "null result"; + + console.log(result); +}; + +runIt(); \ No newline at end of file diff --git a/js/src/tests/query-integration.test.ts b/js/src/tests/query-integration.test.ts index 57a3732..b63fc07 100644 --- a/js/src/tests/query-integration.test.ts +++ b/js/src/tests/query-integration.test.ts @@ -58,6 +58,8 @@ function generateQueryResultData(status: QueryStatus) { columnTypes: ["string", "string"], message: "", errors: "invalid sql", + pageNumber: 1, + pageSize: 100, }; } @@ -173,6 +175,8 @@ describe("run: timeout_error", () => { cached: false, timeoutMinutes: 0.01, retryIntervalSeconds: 0.001, + pageNumber: 1, + pageSize: 100, }); const result = await queryIntegration.run(defaultQueryData); assert.equal(result.error?.errorType, ERROR_TYPES.query_run_timeout_error); @@ -190,6 +194,8 @@ describe("run: timeout_error", () => { cached: false, timeoutMinutes: 0.01, retryIntervalSeconds: 0.001, + pageNumber: 1, + pageSize: 100, }); const result = await queryIntegration.run(defaultQueryData); assert.equal( diff --git a/js/src/tests/query-result-set-builder.test.ts b/js/src/tests/query-result-set-builder.test.ts index 8e250b5..f863132 100644 --- a/js/src/tests/query-result-set-builder.test.ts +++ b/js/src/tests/query-result-set-builder.test.ts @@ -33,6 +33,8 @@ function getQueryResultSetBuilder( columnTypes: ["number", "string", "string", "boolean", "number"], message: "", errors: null, + pageSize: 100, + pageNumber: 0, }, error: null, }; diff --git a/js/src/types/api/api-client.type.ts b/js/src/types/api/api-client.type.ts index c133a0a..80e6287 100644 --- a/js/src/types/api/api-client.type.ts +++ b/js/src/types/api/api-client.type.ts @@ -5,5 +5,5 @@ import { QueryResultResp } from "./query-result-resp.type"; export interface ApiClient { getUrl(path: string): string; createQuery(query: Query): Promise; - getQueryResult(queryID: string): Promise; + getQueryResult(queryID: string, pageNumber: number, pageSize: number): Promise; } diff --git a/js/src/types/api/query-result-resp.type.ts b/js/src/types/api/query-result-resp.type.ts index 43e4e1c..70c088b 100644 --- a/js/src/types/api/query-result-resp.type.ts +++ b/js/src/types/api/query-result-resp.type.ts @@ -12,6 +12,8 @@ export type QueryResultJson = { columnTypes: string[]; message?: string; errors?: string | null; + pageNumber: number; + pageSize: number; }; export interface QueryResultResp extends ApiResponse { diff --git a/js/src/types/query-defaults.type.ts b/js/src/types/query-defaults.type.ts index c26c71a..631aa46 100644 --- a/js/src/types/query-defaults.type.ts +++ b/js/src/types/query-defaults.type.ts @@ -3,4 +3,6 @@ export type QueryDefaults = { cached: boolean; timeoutMinutes: number; retryIntervalSeconds: number; + pageSize: number; + pageNumber: number; }; diff --git a/js/src/types/query.type.ts b/js/src/types/query.type.ts index 6923d84..c663a8f 100644 --- a/js/src/types/query.type.ts +++ b/js/src/types/query.type.ts @@ -7,4 +7,8 @@ export type Query = { cached?: boolean; // The number of minutes until your query time out timeoutMinutes?: number; + // The number of records to return + pageSize?: number; + // The page number to return + pageNumber?: number; };