Skip to content

Commit bbfbb98

Browse files
committed
fix(polling): address PR review feedback for Google polling handlers
- Fix fetchHeaderRow to throw on 403/429 rate limits instead of silently returning empty headers (prevents rows from being processed without headers and lastKnownRowCount from advancing past them permanently) - Fix Drive pagination to avoid advancing resume cursor past sliced changes (prevents permanent change loss when allChanges > maxFiles) - Remove unused logger import from Google Drive trigger config
1 parent c7c9718 commit bbfbb98

File tree

3 files changed

+24
-15
lines changed

3 files changed

+24
-15
lines changed

apps/sim/lib/webhooks/polling/google-drive.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -252,20 +252,32 @@ async function fetchChanges(
252252
newStartPageToken = data.newStartPageToken as string
253253
}
254254

255-
if (data.nextPageToken) {
256-
lastNextPageToken = data.nextPageToken as string
257-
}
258-
259-
if (!data.nextPageToken || allChanges.length >= maxFiles || pages >= MAX_PAGES) {
255+
// Only advance the resume cursor when we'll actually use all changes from this page.
256+
// If allChanges exceeds maxFiles, we'll slice off the extras — so we must NOT
257+
// advance past this page, otherwise the sliced changes are lost permanently.
258+
const hasMore = !!data.nextPageToken
259+
const overLimit = allChanges.length >= maxFiles
260+
261+
if (!hasMore || overLimit || pages >= MAX_PAGES) {
262+
// If we stopped mid-stream and haven't consumed all changes from this page,
263+
// keep currentPageToken so the next poll re-fetches this page.
264+
// If we consumed everything on this page but there are more pages,
265+
// advance to nextPageToken so we don't re-process this page.
266+
if (hasMore && !overLimit) {
267+
lastNextPageToken = data.nextPageToken as string
268+
} else if (hasMore && overLimit && allChanges.length > maxFiles) {
269+
// We got more changes than maxFiles from this page — don't advance,
270+
// re-fetch this page next time (idempotency deduplicates already-processed ones)
271+
} else if (hasMore) {
272+
lastNextPageToken = data.nextPageToken as string
273+
}
260274
break
261275
}
262276

277+
lastNextPageToken = data.nextPageToken as string
263278
currentPageToken = data.nextPageToken as string
264279
}
265280

266-
// If we exhausted all pages the API returns newStartPageToken on the final page.
267-
// If we broke early, fall back to the last nextPageToken so we resume from where
268-
// we stopped rather than re-fetching from the original cursor.
269281
const resumeToken = newStartPageToken ?? lastNextPageToken ?? config.pageToken!
270282

271283
return { changes: allChanges.slice(0, maxFiles), newStartPageToken: resumeToken }

apps/sim/lib/webhooks/polling/google-sheets.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -315,12 +315,12 @@ async function fetchHeaderRow(
315315
if (!response.ok) {
316316
const status = response.status
317317
if (status === 403 || status === 429) {
318-
logger.warn(
319-
`[${requestId}] Sheets API rate limit (${status}) fetching header row, proceeding without headers`
318+
const errorData = await response.json().catch(() => ({}))
319+
throw new Error(
320+
`Sheets API rate limit (${status}) fetching header row — skipping to retry next poll cycle: ${JSON.stringify(errorData)}`
320321
)
321-
} else {
322-
logger.warn(`[${requestId}] Failed to fetch header row, proceeding without headers`)
323322
}
323+
logger.warn(`[${requestId}] Failed to fetch header row, proceeding without headers`)
324324
return []
325325
}
326326

apps/sim/triggers/google-drive/poller.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import { createLogger } from '@sim/logger'
21
import { GoogleDriveIcon } from '@/components/icons'
32
import type { TriggerConfig } from '@/triggers/types'
43

5-
const logger = createLogger('GoogleDrivePollingTrigger')
6-
74
const MIME_TYPE_OPTIONS = [
85
{ id: '', label: 'All Files' },
96
{ id: 'application/vnd.google-apps.document', label: 'Google Docs' },

0 commit comments

Comments
 (0)