Skip to content

Conversation

@andrewjschuang
Copy link
Contributor

@andrewjschuang andrewjschuang commented Sep 5, 2025

WHY

Summary by CodeRabbit

  • Bug Fixes

    • Initial sync now fetches only the first page when no prior checkpoint exists, preventing unexpectedly large imports.
    • Start time no longer defaults to “1 day ago”; syncing strictly respects the stored checkpoint (if none, only the first page is fetched).
    • Page size on first run is standardized to the default limit for consistency.
  • Refactor

    • Removed special-case first-run logic to simplify pagination and make initial behavior more predictable.

@vercel
Copy link

vercel bot commented Sep 5, 2025

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

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
pipedream-docs Ignored Ignored Sep 5, 2025 5:39pm
pipedream-docs-redirect-do-not-edit Ignored Ignored Sep 5, 2025 5:39pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 5, 2025

Walkthrough

HubSpot sources: removed the default "1 day ago" fallback for stored after; pagination now returns early when after is falsy to fetch only the first page on initial runs. The new-or-updated-contact source removed its first-run limit override and always uses DEFAULT_LIMIT. No public signatures changed.

Changes

Cohort / File(s) Change summary
Pagination & after-timestamp behavior
components/hubspot/sources/common/common.mjs
_getAfter() no longer returns a "1 day ago" fallback (may be undefined). paginate() and paginateUsingHasMore() now early-return when after is falsy so only the first page is fetched on initial runs.
New-or-updated contact params
components/hubspot/sources/new-or-updated-contact/new-or-updated-contact.mjs
Removed first-run special-case: isFirstRun and limit override removed. getParams always uses DEFAULT_LIMIT. Module version bumped from 0.0.15 to 0.0.16.
Version bumps (metadata only)
components/hubspot/package.json, components/hubspot/sources/delete-blog-article/delete-blog-article.mjs, components/hubspot/sources/new-company-property-change/new-company-property-change.mjs, components/hubspot/sources/new-contact-property-change/new-contact-property-change.mjs, components/hubspot/sources/new-custom-object-property-change/new-custom-object-property-change.mjs, components/hubspot/sources/new-deal-in-stage/new-deal-in-stage.mjs, components/hubspot/sources/new-deal-property-change/new-deal-property-change.mjs, components/hubspot/sources/new-email-event/new-email-event.mjs, components/hubspot/sources/new-email-subscriptions-timeline/new-email-subscriptions-timeline.mjs, components/hubspot/sources/new-engagement/new-engagement.mjs, components/hubspot/sources/new-event/new-event.mjs, components/hubspot/sources/new-form-submission/new-form-submission.mjs, components/hubspot/sources/new-note/new-note.mjs, components/hubspot/sources/new-or-updated-blog-article/new-or-updated-blog-article.mjs, components/hubspot/sources/new-or-updated-company/new-or-updated-company.mjs, components/hubspot/sources/new-or-updated-crm-object/new-or-updated-crm-object.mjs, components/hubspot/sources/new-or-updated-custom-object/new-or-updated-custom-object.mjs, components/hubspot/sources/new-or-updated-deal/new-or-updated-deal.mjs, components/hubspot/sources/new-or-updated-line-item/new-or-updated-line-item.mjs, components/hubspot/sources/new-or-updated-product/new-or-updated-product.mjs, components/hubspot/sources/new-social-media-message/new-social-media-message.mjs, components/hubspot/sources/new-task/new-task.mjs, components/hubspot/sources/new-ticket-property-change/new-ticket-property-change.mjs, components/hubspot/sources/new-ticket/new-ticket.mjs
Metadata-only version increments across many HubSpot sources and the package.json (no logic or API changes).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Scheduler
  participant Source as HubSpot Source
  participant DB as DB
  participant HubSpot as HubSpot API

  Scheduler->>Source: run()
  Source->>DB: get("after")
  DB-->>Source: after (may be undefined)
  alt after is falsy (initial run)
    Source->>HubSpot: fetch page 1 (params with DEFAULT_LIMIT)
    HubSpot-->>Source: results page 1
    Note over Source: Early return after first page
    Source->>DB: set("after", last timestamp from page 1)
  else after exists (subsequent runs)
    loop paginate until exhausted
      Source->>HubSpot: fetch next page (using after/hasMore)
      HubSpot-->>Source: results page N
      Source->>DB: update "after"
    end
  end
Loading
sequenceDiagram
  autonumber
  participant Source as New/Updated Contact
  participant DB as DB
  participant HubSpot as HubSpot API

  Source->>DB: get("after")
  DB-->>Source: after (may be undefined)
  Note over Source: getParams always sets limit = DEFAULT_LIMIT
  Source->>HubSpot: search/scroll contacts with params
  HubSpot-->>Source: contacts batch
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

User submitted

Suggested reviewers

  • luancazarine
  • jcortes

Poem

I hop through pages, then pause at one,
No "day-ago" shadows—just honest sun.
Limits now steady, no first-run disguise,
Contacts queue neat under bright little eyes.
🐇 Thump-thump, shipped!

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch hubspot-fix-limit-on-first-run

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
components/hubspot/sources/common/common.mjs (3)

16-18: Removing the fallback in _getAfter() is appropriate.

This guarantees a true initial run when no cursor exists. Consider normalizing to null (not required).


95-99: Guard should distinguish null/undefined from 0.

Using !after treats 0 as “first run”. Prefer a nullish check to avoid misclassification.

-        // first run, get only first page
-        if (!after) {
+        // first run = after is null/undefined; get only first page
+        if (after == null) {
           return;
         }

137-141: Same nullish check in paginateUsingHasMore.

Mirror the fix to ensure consistent initial-run behavior.

-        // first run, get only first page
-        if (!after) {
+        // first run = after is null/undefined
+        if (after == null) {
           return;
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ea4b419 and 3ab227f.

📒 Files selected for processing (2)
  • components/hubspot/sources/common/common.mjs (3 hunks)
  • components/hubspot/sources/new-or-updated-contact/new-or-updated-contact.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
components/hubspot/sources/new-or-updated-contact/new-or-updated-contact.mjs (2)
components/hubspot/hubspot.app.mjs (2)
  • DEFAULT_LIMIT (35-41)
  • DEFAULT_LIMIT (587-592)
components/hubspot/common/constants.mjs (1)
  • DEFAULT_LIMIT (40-40)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: pnpm publish
  • GitHub Check: Lint Code Base
🔇 Additional comments (1)
components/hubspot/sources/new-or-updated-contact/new-or-updated-contact.mjs (1)

105-118: Always using DEFAULT_LIMIT is correct and consistent with first-run pagination.

This aligns with the new “first page only on initial run” behavior in common.mjs. No issues found.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
components/hubspot/sources/new-custom-object-property-change/new-custom-object-property-change.mjs (2)

54-83: Guard against undefined after in filters (aligns with new first-run semantics)

If getParams(after) is called with a falsy after, HubSpot may receive value: undefined. To be resilient (even if common’s paginator early-returns), include the hs_lastmodifieddate filter only when after is truthy.

-    getParams(after) {
-      return {
-        object: this.objectSchema,
-        data: {
-          limit: DEFAULT_LIMIT,
-          properties: [
-            this.property,
-          ],
-          sorts: [
-            {
-              propertyName: "hs_lastmodifieddate",
-              direction: "DESCENDING",
-            },
-          ],
-          filterGroups: [
-            {
-              filters: [
-                {
-                  propertyName: this.property,
-                  operator: "HAS_PROPERTY",
-                },
-                {
-                  propertyName: "hs_lastmodifieddate",
-                  operator: "GTE",
-                  value: after,
-                },
-              ],
-            },
-          ],
-        },
-      };
-    },
+    getParams(after) {
+      const filters = [
+        { propertyName: this.property, operator: "HAS_PROPERTY" },
+      ];
+      if (after) {
+        filters.push({
+          propertyName: "hs_lastmodifieddate",
+          operator: "GTE",
+          value: after,
+        });
+      }
+      return {
+        object: this.objectSchema,
+        data: {
+          limit: DEFAULT_LIMIT,
+          properties: [ this.property ],
+          sorts: [
+            { propertyName: "hs_lastmodifieddate", direction: "DESCENDING" },
+          ],
+          filterGroups: [ { filters } ],
+        },
+      };
+    },

32-38: Harden timestamp handling to avoid NaN IDs

If HubSpot returns an unexpected timestamp, Date.parse(...) can be NaN, producing IDs like ${id}NaN. Safeguard getTs and use a stable fallback for id.

-    getTs(object) {
-      const history = object.propertiesWithHistory[this.property];
-      if (!history || !(history.length > 0)) {
-        return;
-      }
-      return Date.parse(history[0].timestamp);
-    },
+    getTs(object) {
+      const history = object.propertiesWithHistory?.[this.property];
+      if (!history || history.length === 0) return;
+      const ts = new Date(history[0]?.timestamp).getTime();
+      return Number.isNaN(ts) ? undefined : ts;
+    },
@@
-      return {
-        id: `${id}${ts}`,
+      return {
+        id: `${id}-${ts ?? Date.now()}`,
         summary: properties[this.property],
         ts,
       };

Also applies to: 45-49

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3ab227f and 05d43e6.

📒 Files selected for processing (25)
  • components/hubspot/package.json (1 hunks)
  • components/hubspot/sources/delete-blog-article/delete-blog-article.mjs (1 hunks)
  • components/hubspot/sources/new-company-property-change/new-company-property-change.mjs (1 hunks)
  • components/hubspot/sources/new-contact-property-change/new-contact-property-change.mjs (1 hunks)
  • components/hubspot/sources/new-custom-object-property-change/new-custom-object-property-change.mjs (1 hunks)
  • components/hubspot/sources/new-deal-in-stage/new-deal-in-stage.mjs (1 hunks)
  • components/hubspot/sources/new-deal-property-change/new-deal-property-change.mjs (1 hunks)
  • components/hubspot/sources/new-email-event/new-email-event.mjs (1 hunks)
  • components/hubspot/sources/new-email-subscriptions-timeline/new-email-subscriptions-timeline.mjs (1 hunks)
  • components/hubspot/sources/new-engagement/new-engagement.mjs (1 hunks)
  • components/hubspot/sources/new-event/new-event.mjs (1 hunks)
  • components/hubspot/sources/new-form-submission/new-form-submission.mjs (1 hunks)
  • components/hubspot/sources/new-note/new-note.mjs (1 hunks)
  • components/hubspot/sources/new-or-updated-blog-article/new-or-updated-blog-article.mjs (1 hunks)
  • components/hubspot/sources/new-or-updated-company/new-or-updated-company.mjs (1 hunks)
  • components/hubspot/sources/new-or-updated-contact/new-or-updated-contact.mjs (2 hunks)
  • components/hubspot/sources/new-or-updated-crm-object/new-or-updated-crm-object.mjs (1 hunks)
  • components/hubspot/sources/new-or-updated-custom-object/new-or-updated-custom-object.mjs (1 hunks)
  • components/hubspot/sources/new-or-updated-deal/new-or-updated-deal.mjs (1 hunks)
  • components/hubspot/sources/new-or-updated-line-item/new-or-updated-line-item.mjs (1 hunks)
  • components/hubspot/sources/new-or-updated-product/new-or-updated-product.mjs (1 hunks)
  • components/hubspot/sources/new-social-media-message/new-social-media-message.mjs (1 hunks)
  • components/hubspot/sources/new-task/new-task.mjs (1 hunks)
  • components/hubspot/sources/new-ticket-property-change/new-ticket-property-change.mjs (1 hunks)
  • components/hubspot/sources/new-ticket/new-ticket.mjs (1 hunks)
✅ Files skipped from review due to trivial changes (23)
  • components/hubspot/sources/new-or-updated-product/new-or-updated-product.mjs
  • components/hubspot/sources/new-social-media-message/new-social-media-message.mjs
  • components/hubspot/sources/new-or-updated-custom-object/new-or-updated-custom-object.mjs
  • components/hubspot/sources/new-or-updated-crm-object/new-or-updated-crm-object.mjs
  • components/hubspot/sources/new-email-subscriptions-timeline/new-email-subscriptions-timeline.mjs
  • components/hubspot/sources/new-or-updated-blog-article/new-or-updated-blog-article.mjs
  • components/hubspot/sources/new-email-event/new-email-event.mjs
  • components/hubspot/sources/new-engagement/new-engagement.mjs
  • components/hubspot/sources/new-or-updated-deal/new-or-updated-deal.mjs
  • components/hubspot/sources/new-event/new-event.mjs
  • components/hubspot/package.json
  • components/hubspot/sources/new-or-updated-company/new-or-updated-company.mjs
  • components/hubspot/sources/new-company-property-change/new-company-property-change.mjs
  • components/hubspot/sources/new-or-updated-line-item/new-or-updated-line-item.mjs
  • components/hubspot/sources/new-ticket/new-ticket.mjs
  • components/hubspot/sources/new-form-submission/new-form-submission.mjs
  • components/hubspot/sources/new-deal-in-stage/new-deal-in-stage.mjs
  • components/hubspot/sources/new-note/new-note.mjs
  • components/hubspot/sources/delete-blog-article/delete-blog-article.mjs
  • components/hubspot/sources/new-deal-property-change/new-deal-property-change.mjs
  • components/hubspot/sources/new-ticket-property-change/new-ticket-property-change.mjs
  • components/hubspot/sources/new-task/new-task.mjs
  • components/hubspot/sources/new-contact-property-change/new-contact-property-change.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/hubspot/sources/new-or-updated-contact/new-or-updated-contact.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Lint Code Base
🔇 Additional comments (2)
components/hubspot/sources/new-custom-object-property-change/new-custom-object-property-change.mjs (2)

9-9: Version bump only — LGTM

Metadata bump to 0.0.13 is fine.


100-120: No action needed — initial pagination only requests first page
The getParams(after) in new-custom-object-property-change doesn’t include any top-level after token (it only sets filterGroups for hs_lastmodifieddate), so on first run with after = undefined the initial API call has no paging cursor. The shared getPaginatedItems helper then does a single do…while loop that only continues if paging.next.after is truthy, ensuring only page 1 is fetched initially.

@vunguyenhung
Copy link
Collaborator

Hi everyone, all test cases are passed! Ready for release!

Test report
https://vunguyenhung.notion.site/Hubspot-fix-run-only-on-page-on-first-run-265bf548bb5e8119ae5df85bb9f4e552

@vunguyenhung vunguyenhung merged commit c4316f7 into master Sep 6, 2025
10 checks passed
@vunguyenhung vunguyenhung deleted the hubspot-fix-limit-on-first-run branch September 6, 2025 05:16
@github-project-automation github-project-automation bot moved this from Ready for Release to Done in Component (Source and Action) Backlog Sep 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants