Skip to content

Commit 02bbc98

Browse files
committed
fix: remove params from importAllEvents that conflict with nextSyncToken
Although these params would've helped narrow down the events needed to import, they'd prevent us from receiving a nextSyncToken, which would break sync. There are several query parameters that cannot be specified together with nextSyncToken to ensure consistency of the client state. See `syncToken` description here: https://developers.google.com/calendar/api/v3/reference/events/list
1 parent 3bd33b3 commit 02bbc98

File tree

3 files changed

+41
-25
lines changed

3 files changed

+41
-25
lines changed

packages/backend/src/sync/services/sync.service.helpers.ts

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import dayjs from "dayjs";
21
import { WithId } from "mongodb";
32
import { Origin } from "@core/constants/core.constants";
43
import { Logger } from "@core/logger/winston.logger";
@@ -7,7 +6,7 @@ import { MapEvent } from "@core/mappers/map.event";
76
import { Schema_CalendarList } from "@core/types/calendar.types";
87
import {
98
gCalendar,
10-
gParamsEventsList,
9+
gParamsImportAllEvents,
1110
gSchema$CalendarList,
1211
} from "@core/types/gcal";
1312
import { gSchema$CalendarListEntry } from "@core/types/gcal";
@@ -29,7 +28,6 @@ import {
2928
SyncError,
3029
} from "@backend/common/constants/error.constants";
3130
import { error } from "@backend/common/errors/handlers/error.handler";
32-
import { yearsAgo } from "@backend/common/helpers/common.util";
3331
import gcalService from "@backend/common/services/gcal/gcal.service";
3432
import {
3533
isFullSyncRequired,
@@ -202,26 +200,20 @@ export const hasAnyActiveEventSync = (sync: Schema_Sync) => {
202200
return false;
203201
};
204202

205-
export const importEvents = async (
203+
export const importAllEvents = async (
206204
userId: string,
207205
gcal: gCalendar,
208206
calendarId: string,
209207
) => {
210208
let nextPageToken: string | undefined = undefined;
211-
let nextSyncToken: string | null | undefined = undefined;
212-
let total = 0;
209+
let nextSyncToken: string | undefined = undefined;
213210

214-
const numYears = 1;
215-
const timeMin = yearsAgo(numYears).toISOString();
216-
const timeMax = dayjs().add(6, "months").toISOString();
211+
let total = 0;
217212

218213
do {
219-
const params: gParamsEventsList = {
214+
const params: gParamsImportAllEvents = {
220215
calendarId,
221-
timeMin,
222-
timeMax,
223216
singleEvents: true,
224-
orderBy: "startTime",
225217
pageToken: nextPageToken,
226218
};
227219

@@ -242,15 +234,19 @@ export const importEvents = async (
242234
await eventService.createMany(cEvents);
243235
}
244236

245-
nextPageToken = gEvents.data.nextPageToken as string;
246-
nextSyncToken = gEvents.data.nextSyncToken;
237+
nextPageToken = gEvents.data.nextPageToken ?? undefined;
238+
nextSyncToken = gEvents.data.nextSyncToken ?? undefined;
247239
} while (nextPageToken !== undefined);
248240

249-
const summary = {
250-
total: total,
251-
nextSyncToken: nextSyncToken as string,
241+
// nextSyncToken is defined when there are no more events
242+
if (!nextSyncToken) {
243+
throw error(GcalError.NoSyncToken, "Failed to get sync token");
244+
}
245+
246+
return {
247+
total,
248+
nextSyncToken,
252249
};
253-
return summary;
254250
};
255251

256252
export const importEventsByCalendar = async (
@@ -276,7 +272,6 @@ export const importEventsByCalendar = async (
276272

277273
do {
278274
const syncToken = getSyncToken(nextPageToken, nextSyncToken);
279-
280275
const response = await getUpdatedEvents(gcal, gCalendarId, syncToken);
281276
const updatedEvents = response.items || [];
282277

@@ -376,9 +371,11 @@ export const prepSyncMaintenance = async () => {
376371
ignored.push(userId);
377372
}
378373
} else {
379-
hasAnyActiveEventSync(sync)
380-
? toPrune.push(sync.user)
381-
: ignored.push(userId);
374+
if (hasAnyActiveEventSync(sync)) {
375+
toPrune.push(sync.user);
376+
} else {
377+
ignored.push(userId);
378+
}
382379
}
383380
}
384381

packages/backend/src/sync/services/sync.service.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { getChannelExpiration, isUsingHttps } from "../util/sync.utils";
3030
import {
3131
assembleEventImports,
3232
getCalendarInfo,
33-
importEvents,
33+
importAllEvents,
3434
importEventsByCalendar,
3535
prepIncrementalImport,
3636
prepSyncMaintenance,
@@ -104,7 +104,7 @@ class SyncService {
104104
userId: string,
105105
) => {
106106
const eventImports = gCalendarIds.map(async (gCalId) => {
107-
const { nextSyncToken } = await importEvents(userId, gcal, gCalId);
107+
const { nextSyncToken } = await importAllEvents(userId, gcal, gCalId);
108108
if (isUsingHttps()) {
109109
await updateSyncTokenFor("events", userId, nextSyncToken, gCalId);
110110
} else {
@@ -273,6 +273,7 @@ class SyncService {
273273
watchParams: { gCalId: string; nextSyncToken?: string }[],
274274
gcal: gCalendar,
275275
) => {
276+
console.log("starting event watch for:", watchParams);
276277
const eventWatches = watchParams.map(async (gInfo) => {
277278
await this.startWatchingGcalEvents(
278279
userId,

packages/core/src/types/gcal.d.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,21 @@ export declare type gSchema$Events$Union = gSchema$Events | gSchema$Events[];
1414

1515
export declare type gParamsEventsList =
1616
calendar.calendar_v3.Params$Resource$Events$List;
17+
18+
/**
19+
* Params for importing all events from a calendar, excluding those
20+
* that would conflict with nextSyncToken
21+
*
22+
* @see https://developers.google.com/calendar/api/v3/reference/events/list
23+
*/
24+
export declare type gParamsImportAllEvents = Omit<
25+
gParamsEventsList,
26+
| "iCalUID"
27+
| "orderBy"
28+
| "privateExtendedProperty"
29+
| "q"
30+
| "sharedExtendedProperty"
31+
| "timeMin"
32+
| "timeMax"
33+
| "updatedMin"
34+
>;

0 commit comments

Comments
 (0)