Skip to content

perf: use repository for webhooks list query & caching in /settings/developer/webhooks/... RSC #21781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 5, 2025

Conversation

Amit91848
Copy link
Contributor

@Amit91848 Amit91848 commented Jun 12, 2025

What does this PR do?

Caches

  • settings/developer/webhooks
  • settings/developer/webhooks/{id}
  • settings/developer/webhooks/new

Video Demo (if applicable):

BEFORE

Screencast.from.2025-06-13.02-40-55.webm

AFTER

Screencast.from.2025-06-13.02-44-45.webm

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

Summary by cubic

Improved performance of the webhooks settings pages by switching to repository-based queries and adding caching for webhook lists and details.

  • Performance
    • Replaced direct TRPC queries with repository methods for listing and fetching webhooks.
    • Added server-side caching with revalidation for webhook data in settings pages.

@Amit91848 Amit91848 requested a review from hbjORbj June 12, 2025 06:48
Copy link

vercel bot commented Jun 12, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
cal ⬜️ Ignored (Inspect) Visit Preview Jun 22, 2025 7:52pm
cal-eu ⬜️ Ignored (Inspect) Visit Preview Jun 22, 2025 7:52pm

@Amit91848 Amit91848 marked this pull request as ready for review June 12, 2025 21:16
@graphite-app graphite-app bot requested a review from a team June 12, 2025 21:16
@dosubot dosubot bot added performance area: performance, page load, slow, slow endpoints, loading screen, unresponsive webhooks area: webhooks, callback, webhook payload labels Jun 12, 2025
Copy link

graphite-app bot commented Jun 12, 2025

Graphite Automations

"Add consumer team as reviewer" took an action on this PR • (06/12/25)

1 reviewer was added to this PR based on Keith Williams's automation.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic found 3 issues across 11 files. Review them in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

});

if (Array.isArray(where.AND)) {
if (input?.eventTypeId) {
Copy link
Contributor

Choose a reason for hiding this comment

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

When eventTypeId is provided, the query omits any filter based on userId or team membership, allowing the caller to fetch webhooks that belong to other users or teams. This breaks access control and can expose private data.

}
} else {
where.AND?.push({
OR: [{ userId }, { teamId: { in: user?.teams.map((membership) => membership.teamId) } }],
Copy link
Contributor

Choose a reason for hiding this comment

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

user?.teams may be undefined when the user is not found, causing .map to be called on undefined and throw at runtime. Use optional chaining or a fallback empty array before mapping.

Suggested change
OR: [{ userId }, { teamId: { in: user?.teams.map((membership) => membership.teamId) } }],
OR: [{ userId }, { teamId: { in: (user?.teams?.map((membership) => membership.teamId) ?? []) } }],

@@ -15,12 +16,24 @@ export const generateMetadata = async ({ params }: { params: Promise<{ id: strin
`/settings/developer/webhooks/${(await params).id}`
);

const getCachedWebhook = (id?: string) => {
const fn = unstable_cache(
Copy link
Contributor

Choose a reason for hiding this comment

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

unstable_cache is instantiated inside getCachedWebhook on every call, so caching cannot persist between calls because a new cache instance is created each time and no explicit cache key is provided; this largely defeats the purpose of caching and wastes memory.

Copy link
Contributor

github-actions bot commented Jun 12, 2025

E2E results are ready!

Copy link
Contributor

@hbjORbj hbjORbj left a comment

Choose a reason for hiding this comment

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

Great job! Left 2 comments!

Comment on lines +19 to +20
const getCachedWebhook = (id?: string) => {
const fn = unstable_cache(
Copy link
Contributor

Choose a reason for hiding this comment

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

unnecessary nesting

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wouldn't we want to only revalidate cache of only a particular webhook? We cannot pass id directly to tags when using unstable_cache, so we need to wrap it

return await prisma.webhook.findMany({
where,
});
return WebhookRepository.findWebhooksByFilters({ userId: ctx.user.id, input });
Copy link
Contributor

Choose a reason for hiding this comment

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

await

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@github-actions github-actions bot marked this pull request as draft June 13, 2025 18:47
@Amit91848 Amit91848 marked this pull request as ready for review June 16, 2025 18:30
@dosubot dosubot bot added the 🧹 Improvements Improvements to existing features. Mostly UX/UI label Jun 16, 2025
@Amit91848 Amit91848 requested a review from hbjORbj June 16, 2025 18:33
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic found 1 issue across 11 files. Review it in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

async () => {
return await WebhookRepository.findByWebhookId(id);
},
undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

Passing undefined as the keyParts argument means a new cached function (and therefore a new cache entry) is created every time getCachedWebhook is called, which largely negates the purpose of unstable_cache. Provide a stable key (e.g. the webhook id) or hoist the cached function outside the wrapper so that the same cache entry is reused.

Suggested change
undefined,
[`webhook:${id}`],

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic found 3 issues across 11 files. Review them in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

async () => {
return await WebhookRepository.findByWebhookId(id);
},
undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

Passing undefined as the keyParts argument means a new cached function (and therefore a new cache entry) is created every time getCachedWebhook is called, which largely negates the purpose of unstable_cache. Provide a stable key (e.g. the webhook id) or hoist the cached function outside the wrapper so that the same cache entry is reused.

Suggested change
undefined,
[`webhook:${id}`],

}
} else {
where.AND?.push({
OR: [{ userId }, { teamId: { in: user?.teams.map((membership) => membership.teamId) } }],
Copy link
Contributor

Choose a reason for hiding this comment

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

user can be null when the lookup fails, causing in: undefined and a Prisma runtime error. Provide a fallback array or ensure the user exists before constructing the filter.

Suggested change
OR: [{ userId }, { teamId: { in: user?.teams.map((membership) => membership.teamId) } }],
OR: [{ userId }, { teamId: { in: (user?.teams ?? []).map((membership) => membership.teamId) } }],

id: userId,
},
select: {
teams: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

Selecting the entire teams relation fetches all membership fields and nested team data even though only teamId is subsequently used. This increases query payload size and may expose unnecessary data.

Suggested change
teams: true,
teams: { select: { teamId: true } },

Copy link
Contributor

github-actions bot commented Jul 7, 2025

This PR is being marked as stale due to inactivity.

@github-actions github-actions bot added the Stale label Jul 7, 2025
Copy link
Contributor

@emrysal emrysal left a comment

Choose a reason for hiding this comment

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

Fundamentally looks like an improvement but it should be updated to use the latest patterns - instantiation for di.

@emrysal emrysal enabled auto-merge (squash) August 5, 2025 00:25
@emrysal emrysal merged commit 0829929 into main Aug 5, 2025
41 checks passed
@emrysal emrysal deleted the perf/cache-settings-developers-webhooks branch August 5, 2025 00:25
joeauyeung added a commit that referenced this pull request Aug 7, 2025
…ttings/developer/webhooks/... RSC (#21781)"

This reverts commit 0829929.
zomars pushed a commit that referenced this pull request Aug 7, 2025
zomars pushed a commit that referenced this pull request Aug 7, 2025
Pallava-Joshi pushed a commit to Pallava-Joshi/cal.com that referenced this pull request Aug 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core area: core, team members only 🧹 Improvements Improvements to existing features. Mostly UX/UI performance area: performance, page load, slow, slow endpoints, loading screen, unresponsive ready-for-e2e Stale webhooks area: webhooks, callback, webhook payload
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants