Skip to content

Commit

Permalink
fix: fixing maximum call stack size exceeded error (#639)
Browse files Browse the repository at this point in the history
  • Loading branch information
tuanphamcybozu authored Jan 10, 2024
1 parent 071a9fe commit e9e20d4
Showing 1 changed file with 31 additions and 44 deletions.
75 changes: 31 additions & 44 deletions src/record/export/usecases/get/getAllRecords.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { KintoneRestAPIClient } from "@kintone/rest-api-client";
import type { KintoneRecordForResponse } from "../../../../kintone/types";

const GET_RECORDS_LIMIT = 500;

// TODO: replace this function after @kintone/rest-api-client supports generator/stream
// eslint-disable-next-line func-style
export async function* getAllRecords(params: {
Expand All @@ -27,45 +29,37 @@ async function* getAllRecordsWithId(params: {
fields?: string[];
condition?: string;
}): AsyncGenerator<KintoneRecordForResponse[], void, undefined> {
const { fields: originalFields, ...rest } = params;
const { apiClient, condition, fields: originalFields, ...rest } = params;
let fields = originalFields;
// Append $id if $id doesn't exist in fields
if (fields && fields.length > 0 && fields.indexOf("$id") === -1) {
fields = [...fields, "$id"];
}
yield* getAllRecordsRecursiveWithId({ ...rest, fields }, "0");
}

// eslint-disable-next-line func-style
async function* getAllRecordsRecursiveWithId(
params: {
apiClient: KintoneRestAPIClient;
app: string;
fields?: string[];
condition?: string;
},
id: string,
): AsyncGenerator<KintoneRecordForResponse[], void, undefined> {
const GET_RECORDS_LIMIT = 500;

const { apiClient, condition, ...rest } = params;
const conditionQuery = condition ? `(${condition}) and ` : "";
const query = `${conditionQuery}$id > ${id} order by $id asc limit ${GET_RECORDS_LIMIT}`;
const result = await apiClient.record.getRecords({ ...rest, query });
yield result.records;
let lastId = "0";
while (true) {
const query = `${conditionQuery}$id > ${lastId} order by $id asc limit ${GET_RECORDS_LIMIT}`;
const result = await apiClient.record.getRecords({
...rest,
fields,
query,
});
yield result.records;

if (result.records.length < GET_RECORDS_LIMIT) {
return;
}
const lastRecord = result.records[result.records.length - 1];
if (lastRecord.$id.type === "__ID__") {
const lastId = lastRecord.$id.value;
yield* getAllRecordsRecursiveWithId(params, lastId);
return;
if (result.records.length < GET_RECORDS_LIMIT) {
break;
}

const lastRecord = result.records[result.records.length - 1];
if (lastRecord.$id.type === "__ID__") {
lastId = lastRecord.$id.value;
} else {
throw new Error(
"Missing `$id` in `getRecords` response. This error is likely caused by a bug in Kintone REST API Client. Please file an issue.",
);
}
}
throw new Error(
"Missing `$id` in `getRecords` response. This error is likely caused by a bug in Kintone REST API Client. Please file an issue.",
);
}

// eslint-disable-next-line func-style
Expand All @@ -78,22 +72,15 @@ async function* getAllRecordsWithCursor(params: {
const { apiClient, ...rest } = params;
const { id } = await apiClient.record.createCursor(rest);
try {
yield* getAllRecordsRecursiveByCursor({ apiClient, id });
while (true) {
const result = await apiClient.record.getRecordsByCursor({ id });
yield result.records;
if (!result.next) {
break;
}
}
} catch (error) {
await apiClient.record.deleteCursor({ id });
throw error;
}
}

// eslint-disable-next-line func-style
async function* getAllRecordsRecursiveByCursor(params: {
apiClient: KintoneRestAPIClient;
id: string;
}): AsyncGenerator<KintoneRecordForResponse[], void, undefined> {
const { apiClient, id } = params;
const result = await apiClient.record.getRecordsByCursor({ id });
yield result.records;
if (result.next) {
yield* getAllRecordsRecursiveByCursor({ apiClient, id });
}
}

0 comments on commit e9e20d4

Please sign in to comment.