Skip to content

Commit 9b99998

Browse files
Google Calendar improvements to New or Updated Event source (#14925)
* Google Calendar - New Created or Updated Event (Instant) - update to handle invalid sync token * Bug fix: When the listEvents API returned a 410 status, this threw an exception instead of returning to code that handles this condition. The API call is changed to allow a 410 status to be returned. * Google Calendar - New Created or Updated Event (Instant) - reduce API calls when many calendars subscribed * When a notification is received, updates are fetched only for the calendar that triggered the notification This reduces calls to the Google Calendar API, preventing unnecessary rate limiting * Address style issues and additional bug identified by coderabbitai * versions, lint fix * pnpm-lock.yaml * update --------- Co-authored-by: michelle0927 <[email protected]>
1 parent 6b2368a commit 9b99998

File tree

3 files changed

+53
-43
lines changed

3 files changed

+53
-43
lines changed

components/google_calendar/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/google_calendar",
3-
"version": "0.5.6",
3+
"version": "0.5.7",
44
"description": "Pipedream Google_calendar Components",
55
"main": "google_calendar.app.mjs",
66
"keywords": [

components/google_calendar/sources/new-or-updated-event-instant/new-or-updated-event-instant.mjs

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default {
88
type: "source",
99
name: "New Created or Updated Event (Instant)",
1010
description: "Emit new event when a Google Calendar events is created or updated (does not emit cancelled events)",
11-
version: "0.1.13",
11+
version: "0.1.14",
1212
dedupe: "unique",
1313
props: {
1414
googleCalendar,
@@ -199,16 +199,18 @@ export default {
199199
}
200200
return new Date(min);
201201
},
202-
getChannelIds() {
203-
const channelIds = [];
202+
getCalendarIdForChannelId(incomingChannelId) {
204203
for (const calendarId of this.calendarIds) {
205-
const channelId = this.db.get(`${calendarId}.channelId`);
206-
channelIds.push(channelId);
204+
if (this.db.get(`${calendarId}.channelId`) === incomingChannelId) {
205+
return calendarId;
206+
}
207207
}
208-
return channelIds;
208+
return null;
209209
},
210210
},
211211
async run(event) {
212+
let calendarId = null; // calendar ID matching incoming channel ID
213+
212214
// refresh watch
213215
if (event.interval_seconds) {
214216
// get time
@@ -224,9 +226,9 @@ export default {
224226
}
225227
} else {
226228
// Verify channel ID
227-
const channelIds = this.getChannelIds();
228229
const incomingChannelId = event?.headers?.["x-goog-channel-id"];
229-
if (!channelIds.includes(incomingChannelId)) {
230+
calendarId = this.getCalendarIdForChannelId(incomingChannelId);
231+
if (!calendarId) {
230232
console.log(
231233
`Unexpected channel ID ${incomingChannelId}. This likely means there are multiple, older subscriptions active.`,
232234
);
@@ -252,41 +254,49 @@ export default {
252254
}
253255

254256
// Fetch and emit events
255-
for (const calendarId of this.calendarIds) {
257+
const checkCalendarIds = calendarId
258+
? [
259+
calendarId,
260+
]
261+
: this.calendarIds;
262+
for (const calendarId of checkCalendarIds) {
256263
const syncToken = this.getNextSyncToken(calendarId);
257264
let nextSyncToken = null;
258265
let nextPageToken = null;
259266
while (!nextSyncToken) {
260-
const {
261-
data: syncData = {},
262-
status: syncStatus,
263-
} = await this.googleCalendar.listEvents({
264-
returnOnlyData: false,
265-
calendarId,
266-
syncToken,
267-
pageToken: nextPageToken,
268-
maxResults: 2500,
269-
});
270-
if (syncStatus === 410) {
271-
console.log("Sync token invalid, resyncing");
272-
nextSyncToken = await this.googleCalendar.fullSync(this.calendarId);
273-
break;
274-
}
275-
nextPageToken = syncData.nextPageToken;
276-
nextSyncToken = syncData.nextSyncToken;
277-
278-
const { items: events = [] } = syncData;
279-
events
280-
.filter(this.isEventRelevant, this)
281-
.forEach((event) => {
282-
const { status } = event;
283-
if (status === "cancelled") {
284-
console.log("Event cancelled. Exiting.");
285-
return;
286-
}
287-
const meta = this.generateMeta(event);
288-
this.$emit(event, meta);
267+
try {
268+
const { data: syncData = {} } = await this.googleCalendar.listEvents({
269+
returnOnlyData: false,
270+
calendarId,
271+
syncToken,
272+
pageToken: nextPageToken,
273+
maxResults: 2500,
289274
});
275+
276+
nextPageToken = syncData.nextPageToken;
277+
nextSyncToken = syncData.nextSyncToken;
278+
279+
const { items: events = [] } = syncData;
280+
events
281+
.filter(this.isEventRelevant, this)
282+
.forEach((event) => {
283+
const { status } = event;
284+
if (status === "cancelled") {
285+
console.log("Event cancelled. Exiting.");
286+
return;
287+
}
288+
const meta = this.generateMeta(event);
289+
this.$emit(event, meta);
290+
});
291+
} catch (error) {
292+
if (error === "Sync token is no longer valid, a full sync is required.") {
293+
console.log("Sync token invalid, resyncing");
294+
nextSyncToken = await this.googleCalendar.fullSync(calendarId);
295+
break;
296+
} else {
297+
throw error;
298+
}
299+
}
290300
}
291301

292302
this.setNextSyncToken(calendarId, nextSyncToken);

pnpm-lock.yaml

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)