Skip to content

feat(trigger): add Google Sheets, Drive, and Calendar polling triggers#4081

Open
waleedlatif1 wants to merge 12 commits intostagingfrom
waleedlatif1/polling-research
Open

feat(trigger): add Google Sheets, Drive, and Calendar polling triggers#4081
waleedlatif1 wants to merge 12 commits intostagingfrom
waleedlatif1/polling-research

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Add polling triggers for Google Sheets (new rows), Google Drive (file changes), and Google Calendar (event updates)
  • Google Drive uses changes.list API with opaque cursor (no clock skew, catches deletes)
  • Google Calendar uses updatedMin + singleEvents=true (expanded recurring events)
  • Google Sheets uses row count comparison + Drive modifiedTime pre-check (saves Sheets quota)
  • Each poller supports: OAuth credentials, configurable filters (event type, MIME type, folder, search term, render options), idempotency, first-poll seeding
  • Wire triggers into block configs so trigger UI appears and generate-docs.ts discovers them
  • Regenerate integrations.json with new trigger entries
  • Update add-trigger skill with polling instructions and versioned block wiring guidance

Type of Change

  • New feature

Testing

Tested manually — type-check passes, lint passes, integrations.json regenerated correctly

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Building Building Preview, Comment Apr 10, 2026 1:24am

Request Review

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 9, 2026

PR Summary

Medium Risk
Adds new polling-based trigger execution paths (new provider handlers, cron schedules, and UI wiring) and changes idempotency semantics for polling to retry failed keys, which could affect trigger firing and load if misconfigured.

Overview
Adds polling triggers for Google Sheets (new rows), Google Drive (file changes), and Google Calendar (event changes), including new polling provider handlers that fetch deltas, seed state on first run, apply user-configurable filters, and emit events via processPolledWebhookEvent with polling idempotency.

Wires these triggers into the Google blocks via getTrigger(...).subBlocks and triggers.available, registers the new providers in polling/trigger registries, and enables new 1-minute polling cron jobs in helm/sim/values.yaml.

Updates idempotency to support retryFailures (enabled for pollingIdempotency), regenerates integrations.json to expose the new triggers, and expands the add-trigger docs/commands to cover polling trigger creation and versioned block wiring.

Reviewed by Cursor Bugbot for commit 47c7b3e. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 9, 2026

Greptile Summary

This PR adds polling triggers for Google Sheets (new rows), Google Drive (file changes), and Google Calendar (event updates). It introduces a retryFailures option to the idempotency service, wires all three triggers into their respective block configs, and updates the polling registry and constants. The core failure-handling logic (cursor/timestamp revert on any failure, idempotency deduplication on retry) is well-implemented, consistent with the existing Gmail/Outlook patterns, and the previously-raised issues from earlier review rounds appear resolved.

Confidence Score: 5/5

Safe to merge — all previously raised data-integrity concerns are resolved and the only remaining finding is a minor P2 style inconsistency in error messaging.

All critical issues from prior review rounds (cursor/timestamp revert on failure, partial-failure handling, rate-limit classification for Calendar and Sheets, Drive merge-order, resume-token overshoot) have been addressed. The retryFailures idempotency extension is correctly implemented with no infinite-loop risk. The sole remaining finding is a P2 suggestion to align Drive 403/429 error messaging with Calendar and Sheets for easier log diagnostics.

apps/sim/lib/webhooks/polling/google-drive.ts — missing explicit 403/429 rate-limit error classification in fetchChanges/getStartPageToken (P2 only)

Important Files Changed

Filename Overview
apps/sim/lib/webhooks/polling/google-drive.ts New Drive polling handler; cursor-revert, partial-failure handling, and knownFileIds logic are correct. Minor: 403/429 rate-limit response is not explicitly distinguished from other API errors, unlike Calendar and Sheets handlers.
apps/sim/lib/webhooks/polling/google-calendar.ts New Calendar polling handler; timestamp revert on any failure (failedCount > 0), idempotency key includes updated field for re-edit detection, and rate-limit handling are all correctly implemented.
apps/sim/lib/webhooks/polling/google-sheets.ts New Sheets polling handler; Drive modifiedTime pre-check, row-count heuristic, partial-failure revert logic, and 403/429 handling in all three API calls are correctly implemented.
apps/sim/lib/core/idempotency/service.ts Adds retryFailures option: on failure the key is deleted rather than stored, enabling the next poll cycle to retry. pollingIdempotency singleton opts in with retryFailures: true. Logic is correct; no infinite-loop risk since failed keys are deleted before any recursive re-attempt.
apps/sim/triggers/registry.ts New trigger entries (google_calendar_poller, google_drive_poller, google_sheets_poller) correctly added and imported from kebab-case directories.
apps/sim/lib/webhooks/polling/registry.ts Three new handlers registered under their provider keys; keys match POLLING_PROVIDERS constants and block trigger configs.

Sequence Diagram

sequenceDiagram
    participant Scheduler as Trigger.dev
    participant Poller as Poll Handler
    participant GoogleAPI as Google API
    participant Idempotency as pollingIdempotency
    participant DB as Webhook State

    Scheduler->>Poller: pollWebhook(ctx)
    Poller->>DB: read providerConfig
    alt First poll
        Poller->>GoogleAPI: get start cursor or seed row count
        GoogleAPI-->>Poller: initial state
        Poller->>DB: persist seeded state
        Poller-->>Scheduler: success, no events emitted
    else Subsequent polls
        Poller->>GoogleAPI: fetch changes since last state
        GoogleAPI-->>Poller: events or rows
        loop For each item
            Poller->>Idempotency: executeWithIdempotency(key, op)
            alt Cache hit
                Idempotency-->>Poller: cached result, no re-fire
            else New execution
                Idempotency->>Poller: run op
                alt Success
                    Poller-->>Idempotency: result stored as completed
                else Failure
                    Poller-->>Idempotency: key deleted for retry
                end
            end
        end
        alt anyFailed is true
            Poller->>DB: revert state to pre-poll values
        else All succeeded
            Poller->>DB: advance state to new cursor or timestamp
        end
    end
Loading

Reviews (7): Last reviewed commit: "fix(polling): revert drive cursor on any..." | Re-trigger Greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 104690d. Configure here.

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 47c7b3e. Configure here.

waleedlatif1 and others added 12 commits April 9, 2026 18:24
Add polling triggers for Google Sheets (new rows), Google Drive (file
changes via changes.list API), and Google Calendar (event updates via
updatedMin). Each includes OAuth credential support, configurable
filters (event type, MIME type, folder, search term, render options),
idempotency, and first-poll seeding. Wire triggers into block configs
and regenerate integrations.json. Update add-trigger skill with polling
instructions and versioned block wiring guidance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix Drive cursor stall: use nextPageToken as resume point when
  breaking early from pagination instead of re-using the original token
- Eliminate redundant Drive API call in Sheets poller by returning
  modifiedTime from the pre-check function
- Add 403/429 rate-limit handling to Sheets API calls matching the
  Calendar handler pattern
- Remove unused changeType field from DriveChangeEntry interface
- Rename triggers/google_drive to triggers/google-drive for consistency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
isDriveFileUnchanged short-circuited when lastModifiedTime was
undefined, never calling the Drive API — so currentModifiedTime
was never populated, creating a permanent chicken-and-egg loop.
Now always calls the Drive API and returns the modifiedTime
regardless of whether there's a previous value to compare against.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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
…empotency key

- Sheets: only advance lastKnownRowCount by processedCount when there
  are failures, so failed rows are retried on the next poll cycle
  (idempotency deduplicates already-processed rows on re-fetch)
- Drive: add fallback for change.time in idempotency key to prevent
  key collisions if the field is ever absent from the API response
… Drive API failure

- Remove unused `now` variable from Google Drive polling handler
- Preserve stored lastModifiedTime when Drive API pre-check fails
  (previously wrote undefined, disabling the optimization until the
  next successful Drive API call)
- Add 'trigger-advanced' mode to SubBlockConfig so canonical pairs work in trigger mode
- Fix buildCanonicalIndex: trigger-mode subblocks don't overwrite non-trigger basicId, deduplicate advancedIds from block spreads
- Update editor, subblock layout, and trigger config aggregation to include trigger-advanced subblocks
- Replace dropdown+fetchOptions in Calendar/Sheets/Drive pollers with file-selector (basic) + short-input (advanced) canonical pairs
- Add canonicalParamId: 'oauthCredential' to triggerCredentials for selector context resolution
- Update polling handlers to read canonical fallbacks (calendarId||manualCalendarId, etc.)
@waleedlatif1 waleedlatif1 force-pushed the waleedlatif1/polling-research branch from 47c7b3e to 2180127 Compare April 10, 2026 01:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant