fix: improve calendar event retrieval by batching requests to avoid server limits #141
This commit is contained in:
+60
-24
@@ -3223,33 +3223,48 @@ export class JMAPClient implements IJMAPClient {
|
|||||||
|
|
||||||
async getCalendarEvents(calendarIds?: string[], targetAccountId?: string): Promise<CalendarEvent[]> {
|
async getCalendarEvents(calendarIds?: string[], targetAccountId?: string): Promise<CalendarEvent[]> {
|
||||||
const accountId = targetAccountId || this.getCalendarsAccountId();
|
const accountId = targetAccountId || this.getCalendarsAccountId();
|
||||||
|
const GET_BATCH_SIZE = 500;
|
||||||
|
|
||||||
const queryArgs: Record<string, unknown> = { accountId, limit: 1000 };
|
const queryArgs: Record<string, unknown> = { accountId, limit: 1000 };
|
||||||
if (calendarIds && calendarIds.length > 0) {
|
if (calendarIds && calendarIds.length > 0) {
|
||||||
queryArgs.filter = { inCalendars: calendarIds };
|
queryArgs.filter = { inCalendars: calendarIds };
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await this.request([
|
// First, query to get all IDs
|
||||||
|
const queryResponse = await this.request([
|
||||||
["CalendarEvent/query", queryArgs, "0"],
|
["CalendarEvent/query", queryArgs, "0"],
|
||||||
["CalendarEvent/get", {
|
|
||||||
accountId,
|
|
||||||
properties: [...CALENDAR_EVENT_PROPERTIES],
|
|
||||||
"#ids": { resultOf: "0", name: "CalendarEvent/query", path: "/ids" },
|
|
||||||
}, "1"]
|
|
||||||
], this.calendarUsing());
|
], this.calendarUsing());
|
||||||
|
|
||||||
// Check for JMAP method-level errors
|
// Check for JMAP method-level errors
|
||||||
if (response.methodResponses?.[0]?.[0] === "error") {
|
if (queryResponse.methodResponses?.[0]?.[0] === "error") {
|
||||||
const error = response.methodResponses[0][1];
|
const error = queryResponse.methodResponses[0][1];
|
||||||
throw new Error(error?.description || error?.type || "CalendarEvent/query failed");
|
throw new Error(error?.description || error?.type || "CalendarEvent/query failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.methodResponses?.[1]?.[0] === "CalendarEvent/get") {
|
const ids: string[] = queryResponse.methodResponses?.[0]?.[1]?.ids || [];
|
||||||
return ((response.methodResponses[1][1].list || []) as CalendarEvent[])
|
if (ids.length === 0) return [];
|
||||||
.filter((event) => !isTaskObject(event))
|
|
||||||
.map((event) => normalizeCalendarEventLike(event));
|
// Batch the /get calls to stay within server max-objects limit
|
||||||
|
const allEvents: CalendarEvent[] = [];
|
||||||
|
for (let i = 0; i < ids.length; i += GET_BATCH_SIZE) {
|
||||||
|
const batchIds = ids.slice(i, i + GET_BATCH_SIZE);
|
||||||
|
const getResponse = await this.request([
|
||||||
|
["CalendarEvent/get", {
|
||||||
|
accountId,
|
||||||
|
properties: [...CALENDAR_EVENT_PROPERTIES],
|
||||||
|
ids: batchIds,
|
||||||
|
}, "0"]
|
||||||
|
], this.calendarUsing());
|
||||||
|
|
||||||
|
if (getResponse.methodResponses?.[0]?.[0] === "CalendarEvent/get") {
|
||||||
|
const events = (getResponse.methodResponses[0][1].list || []) as CalendarEvent[];
|
||||||
|
allEvents.push(...events);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return [];
|
|
||||||
|
return allEvents
|
||||||
|
.filter((event) => !isTaskObject(event))
|
||||||
|
.map((event) => normalizeCalendarEventLike(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
async queryAllCalendarEvents(
|
async queryAllCalendarEvents(
|
||||||
@@ -3314,21 +3329,42 @@ export class JMAPClient implements IJMAPClient {
|
|||||||
queryArgs.sort = sort;
|
queryArgs.sort = sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await this.request([
|
const GET_BATCH_SIZE = 500;
|
||||||
|
|
||||||
|
// First, query to get IDs
|
||||||
|
const queryResponse = await this.request([
|
||||||
["CalendarEvent/query", queryArgs, "0"],
|
["CalendarEvent/query", queryArgs, "0"],
|
||||||
["CalendarEvent/get", {
|
|
||||||
accountId,
|
|
||||||
properties: [...CALENDAR_EVENT_PROPERTIES],
|
|
||||||
"#ids": { resultOf: "0", name: "CalendarEvent/query", path: "/ids" },
|
|
||||||
}, "1"]
|
|
||||||
], this.calendarUsing());
|
], this.calendarUsing());
|
||||||
|
|
||||||
if (response.methodResponses?.[1]?.[0] === "CalendarEvent/get") {
|
if (queryResponse.methodResponses?.[0]?.[0] === "error") {
|
||||||
return ((response.methodResponses[1][1].list || []) as CalendarEvent[])
|
const error = queryResponse.methodResponses[0][1];
|
||||||
.filter((event) => !isTaskObject(event))
|
throw new Error(error?.description || error?.type || "CalendarEvent/query failed");
|
||||||
.map((event) => normalizeCalendarEventLike(event));
|
|
||||||
}
|
}
|
||||||
return [];
|
|
||||||
|
const ids: string[] = queryResponse.methodResponses?.[0]?.[1]?.ids || [];
|
||||||
|
if (ids.length === 0) return [];
|
||||||
|
|
||||||
|
// Batch the /get calls to stay within server max-objects limit
|
||||||
|
const allEvents: CalendarEvent[] = [];
|
||||||
|
for (let i = 0; i < ids.length; i += GET_BATCH_SIZE) {
|
||||||
|
const batchIds = ids.slice(i, i + GET_BATCH_SIZE);
|
||||||
|
const getResponse = await this.request([
|
||||||
|
["CalendarEvent/get", {
|
||||||
|
accountId,
|
||||||
|
properties: [...CALENDAR_EVENT_PROPERTIES],
|
||||||
|
ids: batchIds,
|
||||||
|
}, "0"]
|
||||||
|
], this.calendarUsing());
|
||||||
|
|
||||||
|
if (getResponse.methodResponses?.[0]?.[0] === "CalendarEvent/get") {
|
||||||
|
const events = (getResponse.methodResponses[0][1].list || []) as CalendarEvent[];
|
||||||
|
allEvents.push(...events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allEvents
|
||||||
|
.filter((event) => !isTaskObject(event))
|
||||||
|
.map((event) => normalizeCalendarEventLike(event));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to query calendar events:', error);
|
console.error('Failed to query calendar events:', error);
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
Reference in New Issue
Block a user