cal.com
cal.com copied to clipboard
chore: platform api usage based billing using queue
What does this PR do?
Usage based billing for platform api using Bull Queue
- Creating a booking
- a job is created to increment the usage when the booking will start
- Canceling a booking
- cancel the job that was supposed to run to increment usage when booking would start
- Reschedule
- cancel the job that was supposed to run to increment usage when booking would start
- create a new job to increment usage when rescheduled booking will happen
if you are wondering why we don't simply tell stripe to decrement usage, it's simply because stripe does not allow it.
Thank you for following the naming conventions! 🙏 Feel free to join our discord and post your PR link.
Graphite Automations
"Add foundation team as reviewer" took an action on this PR • (05/16/24)
1 reviewer was added to this PR based on Keith Williams's automation.
"Add platform team as reviewer" took an action on this PR • (05/16/24)
1 reviewer was added to this PR based on Keith Williams's automation.
New and removed dependencies detected. Learn more about Socket for GitHub ↗︎
| Package | New capabilities | Transitives | Size | Publisher |
|---|---|---|---|---|
| npm/[email protected] | environment | 0 |
31.4 kB | streamich |
🚮 Removed packages: npm/[email protected], npm/[email protected]
No dependency changes detected. Learn more about Socket for GitHub ↗︎
👍 No dependency changes detected in pull request
The latest updates on your projects. Learn more about Vercel for Git ↗︎
3 Skipped Deployments
| Name | Status | Preview | Comments | Updated (UTC) |
|---|---|---|---|---|
| ai | ⬜️ Ignored (Inspect) | Visit Preview | Jul 24, 2024 2:19pm | |
| cal | ⬜️ Ignored (Inspect) | Visit Preview | Jul 24, 2024 2:19pm | |
| calcom-web-canary | ⬜️ Ignored (Inspect) | Visit Preview | Jul 24, 2024 2:19pm |
📦 Next.js Bundle Analysis for @calcom/web
This analysis was generated by the Next.js Bundle Analysis action. 🤖
Eighty-five Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
| Page | Size (compressed) | First Load | % of Budget (350 KB) |
|---|---|---|---|
/apps |
277.5 KB |
505.16 KB | 144.33% (🟢 -1.91%) |
/apps/[slug] |
294.88 KB |
522.54 KB | 149.30% (🟢 -1.97%) |
/apps/[slug]/[...pages] |
587.32 KB |
814.97 KB | 232.85% (🟢 -1.52%) |
/apps/categories |
254.55 KB |
482.21 KB | 137.77% (🟢 -1.71%) |
/apps/categories/[category] |
259.36 KB |
487.01 KB | 139.15% (🟢 -1.99%) |
/apps/installation/[[...step]] |
467.39 KB |
695.05 KB | 198.59% (🔴 +85.63%) |
/apps/installed/[category] |
278.5 KB |
506.15 KB | 144.61% (🟢 -1.74%) |
/auth/saml-idp |
12.22 KB |
239.88 KB | 68.54% (🟢 -20.80%) |
/availability |
426.9 KB |
654.56 KB | 187.02% (🟢 -1.58%) |
/availability/[schedule] |
410.77 KB |
638.43 KB | 182.41% (🟢 -1.59%) |
/booking/[uid] |
236.87 KB |
464.52 KB | 132.72% (🟡 +0.26%) |
/booking/[uid]/embed |
236.87 KB |
464.53 KB | 132.72% (🟡 +0.26%) |
/bookings/[status] |
324.57 KB |
552.23 KB | 157.78% (🟢 -1.61%) |
/enterprise |
254.6 KB |
482.26 KB | 137.79% (🟢 -1.71%) |
/event-types |
559.92 KB |
787.58 KB | 225.02% (🟢 -1.55%) |
/event-types/[type] |
435.69 KB |
663.35 KB | 189.53% (🟢 -1.67%) |
/getting-started/[[...step]] |
448.15 KB |
675.8 KB | 193.09% (🟡 +10.72%) |
/insights |
474.55 KB |
702.2 KB | 200.63% (🟢 -1.71%) |
/more |
254.11 KB |
481.77 KB | 137.65% (🟢 -1.72%) |
/payment/[uid] |
121.27 KB |
348.93 KB | 99.69% (🟡 +0.20%) |
/settings/admin |
260.58 KB |
488.24 KB | 139.50% (🟢 -1.69%) |
/settings/admin/apps |
273.96 KB |
501.62 KB | 143.32% (🟢 -1.68%) |
/settings/admin/apps/[category] |
273.95 KB |
501.6 KB | 143.32% (🟢 -1.68%) |
/settings/admin/flags |
264.41 KB |
492.07 KB | 140.59% (🟢 -1.69%) |
/settings/admin/impersonation |
260.97 KB |
488.63 KB | 139.61% (🟢 -1.69%) |
/settings/admin/lockedSMS |
282.07 KB |
509.72 KB | 145.63% (🟢 -1.66%) |
/settings/admin/lockedSMS/lockedSMSView |
119.52 KB |
347.17 KB | 99.19% (🟢 -0.15%) |
/settings/admin/oAuth |
272.69 KB |
500.35 KB | 142.96% (🟢 -1.69%) |
/settings/admin/oAuth/oAuthView |
95.41 KB |
323.07 KB | 92.30% (🟢 -0.20%) |
/settings/admin/orgMigrations/_OrgMigrationLayout |
249.36 KB |
477.02 KB | 136.29% (🟢 -1.73%) |
/settings/admin/orgMigrations/moveTeamToOrg |
299.28 KB |
526.94 KB | 150.55% (🟢 -1.66%) |
/settings/admin/orgMigrations/moveUserToOrg |
319.11 KB |
546.77 KB | 156.22% (🟢 -1.64%) |
/settings/admin/orgMigrations/removeTeamFromOrg |
299.05 KB |
526.7 KB | 150.49% (🟢 -1.67%) |
/settings/admin/orgMigrations/removeUserFromOrg |
299.06 KB |
526.71 KB | 150.49% (🟢 -1.66%) |
/settings/admin/organizations |
262.47 KB |
490.12 KB | 140.03% (🟢 -1.68%) |
/settings/admin/organizations/[id]/edit |
261.13 KB |
488.78 KB | 139.65% (🟢 -1.69%) |
/settings/admin/users |
263.24 KB |
490.89 KB | 140.26% (🟢 -1.69%) |
/settings/admin/users/[id]/edit |
392.44 KB |
620.1 KB | 177.17% (🟢 -1.65%) |
/settings/admin/users/add |
392.11 KB |
619.77 KB | 177.08% (🟢 -1.66%) |
/settings/billing |
260.79 KB |
488.44 KB | 139.55% (🟢 -1.68%) |
/settings/developer/api-keys |
265.18 KB |
492.84 KB | 140.81% (🟢 -1.69%) |
/settings/developer/webhooks |
265.36 KB |
493.01 KB | 140.86% (🟢 -1.69%) |
/settings/developer/webhooks/[id] |
266.34 KB |
493.99 KB | 141.14% (🟢 -1.67%) |
/settings/developer/webhooks/new |
266.36 KB |
494.02 KB | 141.15% (🟢 -1.67%) |
/settings/my-account/appearance |
313.8 KB |
541.46 KB | 154.70% (🟢 -1.68%) |
/settings/my-account/calendars |
272.21 KB |
499.86 KB | 142.82% (🟢 -1.73%) |
/settings/my-account/conferencing |
273.12 KB |
500.78 KB | 143.08% (🟢 -1.72%) |
/settings/my-account/general |
376.29 KB |
603.95 KB | 172.56% (🟢 -1.68%) |
/settings/my-account/out-of-office |
265.82 KB |
493.47 KB | 140.99% (🟢 -1.69%) |
/settings/my-account/profile |
408.81 KB |
636.47 KB | 181.85% (🟢 -1.66%) |
/settings/organizations/[id]/about |
159.7 KB |
387.36 KB | 110.67% (🟡 +0.49%) |
/settings/organizations/[id]/add-teams |
159.7 KB |
387.35 KB | 110.67% (🟡 +0.49%) |
/settings/organizations/admin-api |
260.74 KB |
488.39 KB | 139.54% (🟢 -1.69%) |
/settings/organizations/appearance |
122.37 KB |
350.03 KB | 100.01% (🟢 -48.01%) |
/settings/organizations/billing |
260.82 KB |
488.48 KB | 139.57% (🟢 -1.69%) |
/settings/organizations/dsync |
293.44 KB |
521.1 KB | 148.89% (🟢 -1.69%) |
/settings/organizations/general |
349.13 KB |
576.79 KB | 164.80% (🟢 -1.69%) |
/settings/organizations/members |
400.3 KB |
627.96 KB | 179.42% (🟢 -1.68%) |
/settings/organizations/new |
159.71 KB |
387.36 KB | 110.68% (🟡 +0.48%) |
/settings/organizations/privacy |
266.34 KB |
493.99 KB | 141.14% (🟢 -1.69%) |
/settings/organizations/profile |
417.35 KB |
645 KB | 184.29% (🟡 +2.92%) |
/settings/organizations/sso |
271.41 KB |
499.07 KB | 142.59% (🟢 -1.69%) |
/settings/organizations/teams/other |
261.65 KB |
489.31 KB | 139.80% (🟢 -1.69%) |
/settings/organizations/teams/other/[id]/appearance |
273.56 KB |
501.21 KB | 143.20% (🟢 -1.63%) |
/settings/organizations/teams/other/[id]/members |
268.25 KB |
495.91 KB | 141.69% (🟢 -1.69%) |
/settings/organizations/teams/other/[id]/profile |
472.03 KB |
699.68 KB | 199.91% (🟢 -1.67%) |
/settings/platform |
259.21 KB |
486.87 KB | 139.10% (🟢 -1.71%) |
/settings/platform/new |
120.72 KB |
348.37 KB | 99.53% (🟡 +0.52%) |
/settings/platform/oauth-clients/[clientId]/edit |
257.52 KB |
485.17 KB | 138.62% (🟢 -1.71%) |
/settings/platform/oauth-clients/create |
256.66 KB |
484.31 KB | 138.38% (🟢 -1.72%) |
/settings/security/impersonation |
265.99 KB |
493.65 KB | 141.04% (🟢 -1.69%) |
/settings/security/password |
304.18 KB |
531.83 KB | 151.95% (🟢 -1.66%) |
/settings/security/sso |
270.86 KB |
498.52 KB | 142.43% (🟢 -1.69%) |
/settings/security/two-factor-auth |
269.47 KB |
497.13 KB | 142.04% (🟢 -1.69%) |
/settings/teams |
260.32 KB |
487.97 KB | 139.42% (🟢 -1.69%) |
/settings/teams/[id]/appearance |
273.54 KB |
501.2 KB | 143.20% (🟢 -1.64%) |
/settings/teams/[id]/billing |
260.82 KB |
488.48 KB | 139.57% (🟢 -1.69%) |
/settings/teams/[id]/members |
378.37 KB |
606.03 KB | 173.15% (🟢 -1.68%) |
/settings/teams/[id]/profile |
472.86 KB |
700.51 KB | 200.15% (🟢 -1.66%) |
/settings/teams/new |
193.05 KB |
420.71 KB | 120.20% (🟢 -1.81%) |
/teams |
254.34 KB |
481.99 KB | 137.71% (🟢 -1.71%) |
/upgrade |
254.46 KB |
482.12 KB | 137.75% (🟢 -1.71%) |
/video/[uid] |
291.31 KB |
518.97 KB | 148.28% (🟢 -0.15%) |
/workflows |
286.36 KB |
514.02 KB | 146.86% (🟢 -1.65%) |
/workflows/[workflow] |
414.66 KB |
642.31 KB | 183.52% (🟢 -1.43%) |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
The "Budget %" column shows what percentage of your performance budget the First Load total takes up. For example, if your budget was 100kb, and a given page's first load size was 10kb, it would be 10% of your budget. You can also see how much this has increased or decreased compared to the base branch of your PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this. If you see "+/-
Current Playwright Test Results Summary
✅ 321 Passing - ⚠️ 13 Flaky
Run may still be in progress, this comment will be updated as current testing workflow or job completes...
(Last updated on 05/18/2024 06:12:57am UTC)
Run Details
Running Workflow PR Update on Github Actions
Commit: 2f0fdf0d6507984e56d1515d634c1e50d9ea573c
Started: 05/18/2024 06:10:46am UTC
⚠️ Flakes
📄 apps/web/playwright/booking-seats.e2e.ts • 1 Flake
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
Reschedule for booking with seats If rescheduled/cancelled booking with seats it should display the correct number of seats
Retry 1 • Initial Attempt |
0% (0)0 / 212 runsfailed over last 7 days |
1.89% (4)4 / 212 runsflaked over last 7 days |
📄 apps/web/playwright/profile.e2e.ts • 1 Flake
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
Update Profile Can update a users email (verification enabled)
Retry 2 • Retry 1 • Initial Attempt |
38.02% (92)92 / 242 runsfailed over last 7 days |
33.47% (81)81 / 242 runsflaked over last 7 days |
📄 packages/app-store/routing-forms/playwright/tests/basic.e2e.ts • 1 Flake
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
Routing Forms Seeded Routing Form Test preview should return correct route
Retry 1 • Initial Attempt |
0.91% (2)2 / 219 runsfailed over last 7 days |
31.05% (68)68 / 219 runsflaked over last 7 days |
📄 apps/web/playwright/event-types.e2e.ts • 1 Flake
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
Event Types tests -- legacy user Different Locations Tests Can remove location from multiple locations that are saved
Retry 1 • Initial Attempt |
4.48% (10)10 / 223 runsfailed over last 7 days |
19.28% (43)43 / 223 runsflaked over last 7 days |
📄 apps/web/playwright/managedBooking/advancedOptions.e2e.ts • 1 Flake
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
Check advanced options in a managed team event type Check advanced options in a managed team event type without offer seats
Retry 1 • Initial Attempt |
0.45% (1)1 / 220 runfailed over last 7 days |
48.18% (106)106 / 220 runsflaked over last 7 days |
📄 apps/web/playwright/signup.e2e.ts • 1 Flake
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
Signup Flow Test Email verification sent if enabled
Retry 1 • Initial Attempt |
0.85% (2)2 / 234 runsfailed over last 7 days |
25.64% (60)60 / 234 runsflaked over last 7 days |
📄 packages/embeds/embed-core/playwright/tests/namespacing.e2e.ts • 4 Flakes
Top 1 Common Error Messages
|
|
4 Test Cases Affected |
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
Namespacing Inline Embed Add inline embed using a namespace without reload
Retry 1 • Initial Attempt |
0.46% (1)1 / 219 runfailed over last 7 days |
60.27% (132)132 / 219 runsflaked over last 7 days |
|
Namespacing Inline Embed Double install Embed Snippet with inline embed without a namespace(i.e. default namespace)
Retry 1 • Initial Attempt |
0% (0)0 / 219 runsfailed over last 7 days |
63.01% (138)138 / 219 runsflaked over last 7 days |
|
Namespacing Inline Embed Double install Embed Snippet with inline embed using a namespace
Retry 1 • Initial Attempt |
0.46% (1)1 / 219 runfailed over last 7 days |
60.27% (132)132 / 219 runsflaked over last 7 days |
|
Namespacing Different namespaces can have different init configs
Retry 1 • Initial Attempt |
0% (0)0 / 217 runsfailed over last 7 days |
60.37% (131)131 / 217 runsflaked over last 7 days |
📄 apps/web/playwright/hash-my-url.e2e.ts • 1 Flake
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
hash my url generate url hash
Retry 2 • Retry 1 • Initial Attempt |
5.96% (13)13 / 218 runsfailed over last 7 days |
27.98% (61)61 / 218 runsflaked over last 7 days |
📄 apps/web/playwright/teams.e2e.ts • 1 Flake
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
Teams - NonOrg -- legacy Can create a booking for Round Robin EventType
Retry 2 • Retry 1 • Initial Attempt |
7.30% (17)17 / 233 runsfailed over last 7 days |
28.76% (67)67 / 233 runsflaked over last 7 days |
📄 apps/web/playwright/organization/booking.e2e.ts • 1 Flake
Test Case Results
| Test Case | Last 7 days Failures | Last 7 days Flakes |
|---|---|---|
|
Bookings Team Event Can create a booking for Round Robin EventType
Retry 2 • Retry 1 • Initial Attempt |
7.89% (18)18 / 228 runsfailed over last 7 days |
27.63% (63)63 / 228 runsflaked over last 7 days |
Putting this back in draft until we have the proper discussion around Bull
need to change the logic to increment usage of managed user instead of relying on oauth client id ,
@ThyMinimalDev Curious if you think we could achieve the same result by having a cron running every X minutes that calculates number of bookings completed and updates usage?
With that approach, we don't need to handle all this logic to chase down the message that was pushed to the queue in the future.
@ThyMinimalDev Curious if you think we could achieve the same result by having a cron running every X minutes that calculates number of bookings completed and updates usage?
With that approach, we don't need to handle all this logic to chase down the message that was pushed to the queue in the future.
@ThyMinimalDev Curious if you think we could achieve the same result by having a cron running every X minutes that calculates number of bookings completed and updates usage?
With that approach, we don't need to handle all this logic to chase down the message that was pushed to the queue in the future.
A cron is a good option as well, we could have it look at the non cancelled booking of managed users that are in the past, we would need to add en entry in the database to index and filter the ones that have not yet been counted toward usage
I don't think we would need to worry about stripe rate limiting until some time
need to add en entry in the database to index and filter the ones that have not yet been counted toward usage
Would we actually need this if you can just compare the count of the current bookings - even if you keep a running count elsewhere - redis for example?
Then every billing period we just compare the current usage to the value we have in redis and charge accordingly. I was just thinking of ways to do this without queues as it feels weird if i booking is 3 months in advance, do i want that job sitting waiting to run for that long?
need to add en entry in the database to index and filter the ones that have not yet been counted toward usage
Would we actually need this if you can just compare the count of the current bookings - even if you keep a running count elsewhere - redis for example?
Then every billing period we just compare the current usage to the value we have in redis and charge accordingly. I was just thinking of ways to do this without queues as it feels weird if i booking is 3 months in advance, do i want that job sitting waiting to run for that long?
that's a good idea, only difficulty I can see is that everyone has different billing cycles
in the end I think the complexity is same-same, but different
need to add en entry in the database to index and filter the ones that have not yet been counted toward usage
Would we actually need this if you can just compare the count of the current bookings - even if you keep a running count elsewhere - redis for example? Then every billing period we just compare the current usage to the value we have in redis and charge accordingly. I was just thinking of ways to do this without queues as it feels weird if i booking is 3 months in advance, do i want that job sitting waiting to run for that long?
that's a good idea, only difficulty I can see is that everyone has different billing cycles
in the end I think the complexity is same-same, but different
Agreed - I just wonder if that is a easier / better approach than doing it via canceling a job.
I dont think billing cycles are an issue here if we already have a cron running every day to update this "count" we can check if its like a day before the billing date for that subscription then push the usage record to stripe?
Should probably be an RFC where we come up with a standard to do this cause private-api needs it too
I think the ea
need to add en entry in the database to index and filter the ones that have not yet been counted toward usage
Would we actually need this if you can just compare the count of the current bookings - even if you keep a running count elsewhere - redis for example? Then every billing period we just compare the current usage to the value we have in redis and charge accordingly. I was just thinking of ways to do this without queues as it feels weird if i booking is 3 months in advance, do i want that job sitting waiting to run for that long?
that's a good idea, only difficulty I can see is that everyone has different billing cycles in the end I think the complexity is same-same, but different
Agreed - I just wonder if that is a easier / better approach than doing it via canceling a job.
I dont think billing cycles are an issue here if we already have a cron running every day to update this "count" we can check if its like a day before the billing date for that subscription then push the usage record to stripe?
Should probably be an RFC where we come up with a standard to do this cause private-api needs it too
If we don't want to use jobs, the easiest is to increment a count in a redis store, and have a cron that runs often enough to push the usage to stripe and reset it to 0, that way we don't to worry about billing cycles
This PR is being marked as stale due to inactivity.
ready for review