fix: gracefully handle calendar failures when bypassBusyCalendarTimes is enabled (#23061)

* fix: gracefully handle calendar failures when bypassBusyCalendarTimes is enabled

- When _bypassCalendarBusyTimes parameter is true and third-party calendar fetching fails
- System now falls back to internal bookings only instead of throwing error
- Maintains existing error behavior when bypass is disabled

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* feat: add _silentCalendarFailures parameter to handle calendar failures gracefully

- Add silentlyHandleCalendarFailures parameter to getBusyTimes service
- Add _silentCalendarFailures parameter to getUserAvailability schema
- Add _silentCalendarFailures parameter to tRPC slots endpoint
- Add _silentCalendarFailures parameter to API v2 slots/available endpoint
- Parameter attempts calendar calls first, falls back silently on failure
- Different from bypassCalendarBusyTimes which skips calendar calls entirely

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* refactor: remove bypassBusyCalendarTimes logic from error handling

- Keep only silentlyHandleCalendarFailures logic in getBusyTimes error handling
- Remove redundant bypassBusyCalendarTimes condition from calendar failure handling
- Maintain existing bypassBusyCalendarTimes logic that skips calendar calls entirely

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* feat: add silentlyHandleCalendarFailures prop to Booker atom

- Pass silentlyHandleCalendarFailures prop from BookerPlatformWrapper to useAvailableSlots
- Forward prop as _silentCalendarFailures parameter to API v2 slots/available endpoint
- Complete the parameter flow from Booker atom to underlying service layer
- Enables silent handling of calendar provider failures in Booker component

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* chore: fix type and bump library

* chore: bump library

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: morgan@cal.com <morgan@cal.com>
Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
devin-ai-integration[bot]
2025-08-14 18:41:53 +03:00
committed by GitHub
co-authored by morgan@cal.com <morgan@cal.com> Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> morgan@cal.com <morgan@cal.com> Somay Chauhan Morgan
parent 994a36d039
commit e237749abd
11 changed files with 102 additions and 302 deletions
+10 -242
View File
@@ -4264,9 +4264,7 @@
}
}
},
"tags": [
"Orgs / Teams / Event Types / Private Links"
]
"tags": ["Orgs / Teams / Event Types / Private Links"]
},
"get": {
"operationId": "OrganizationsEventTypesPrivateLinksController_getPrivateLinks",
@@ -4328,9 +4326,7 @@
}
}
},
"tags": [
"Orgs / Teams / Event Types / Private Links"
]
"tags": ["Orgs / Teams / Event Types / Private Links"]
}
},
"/v2/organizations/{orgId}/teams/{teamId}/event-types/{eventTypeId}/private-links/{linkId}": {
@@ -4402,9 +4398,7 @@
}
}
},
"tags": [
"Orgs / Teams / Event Types / Private Links"
]
"tags": ["Orgs / Teams / Event Types / Private Links"]
},
"delete": {
"operationId": "OrganizationsEventTypesPrivateLinksController_deletePrivateLink",
@@ -4474,9 +4468,7 @@
}
}
},
"tags": [
"Orgs / Teams / Event Types / Private Links"
]
"tags": ["Orgs / Teams / Event Types / Private Links"]
}
},
"/v2/organizations/{orgId}/teams/{teamId}/memberships": {
@@ -22121,13 +22113,7 @@
"example": "2025-12-31T23:59:59.000Z"
}
},
"required": [
"linkId",
"eventTypeId",
"isExpired",
"bookingUrl",
"expiresAt"
]
"required": ["linkId", "eventTypeId", "isExpired", "bookingUrl", "expiresAt"]
},
"UsageBasedPrivateLinkOutput": {
"type": "object",
@@ -22164,14 +22150,7 @@
"example": 3
}
},
"required": [
"linkId",
"eventTypeId",
"isExpired",
"bookingUrl",
"maxUsageCount",
"usageCount"
]
"required": ["linkId", "eventTypeId", "isExpired", "bookingUrl", "maxUsageCount", "usageCount"]
},
"CreatePrivateLinkOutput": {
"type": "object",
@@ -22193,10 +22172,7 @@
]
}
},
"required": [
"status",
"data"
]
"required": ["status", "data"]
},
"GetPrivateLinksOutput": {
"type": "object",
@@ -22221,10 +22197,7 @@
}
}
},
"required": [
"status",
"data"
]
"required": ["status", "data"]
},
"UpdatePrivateLinkOutput": {
"type": "object",
@@ -22246,10 +22219,7 @@
]
}
},
"required": [
"status",
"data"
]
"required": ["status", "data"]
},
"DeletePrivateLinkOutput": {
"type": "object",
@@ -22274,10 +22244,7 @@
}
}
},
"required": [
"status",
"data"
]
"required": ["status", "data"]
},
"StripConnectOutputDto": {
"type": "object",
@@ -26267,205 +26234,6 @@
},
"required": ["status", "data"]
},
"CreatePrivateLinkInput": {
"type": "object",
"properties": {
"expiresAt": {
"type": "string",
"description": "Expiration date for time-based links",
"format": "date-time",
"example": "2024-12-31T23:59:59.000Z"
},
"maxUsageCount": {
"type": "number",
"description": "Maximum number of times the link can be used. If omitted and expiresAt is not provided, defaults to 1 (one time use).",
"example": 10,
"minimum": 1,
"default": 1
}
}
},
"TimeBasedPrivateLinkOutput": {
"type": "object",
"properties": {
"linkId": {
"type": "string",
"description": "The private link ID",
"example": "abc123def456"
},
"eventTypeId": {
"type": "number",
"description": "Event type ID this link belongs to",
"example": 123
},
"isExpired": {
"type": "boolean",
"description": "Whether the link is currently expired",
"example": false
},
"bookingUrl": {
"type": "string",
"description": "Full booking URL for this private link",
"format": "uri",
"example": "https://cal.com/d/abc123def456/30min"
},
"expiresAt": {
"type": "string",
"description": "Expiration date for this time-based link",
"format": "date-time",
"example": "2025-12-31T23:59:59.000Z"
}
},
"required": ["linkId", "eventTypeId", "isExpired", "bookingUrl", "expiresAt"]
},
"UsageBasedPrivateLinkOutput": {
"type": "object",
"properties": {
"linkId": {
"type": "string",
"description": "The private link ID",
"example": "abc123def456"
},
"eventTypeId": {
"type": "number",
"description": "Event type ID this link belongs to",
"example": 123
},
"isExpired": {
"type": "boolean",
"description": "Whether the link is currently expired",
"example": false
},
"bookingUrl": {
"type": "string",
"description": "Full booking URL for this private link",
"format": "uri",
"example": "https://cal.com/d/abc123def456/30min"
},
"maxUsageCount": {
"type": "number",
"description": "Maximum number of times this link can be used",
"example": 10
},
"usageCount": {
"type": "number",
"description": "Current usage count for this link",
"example": 3
}
},
"required": ["linkId", "eventTypeId", "isExpired", "bookingUrl", "maxUsageCount", "usageCount"]
},
"CreatePrivateLinkOutput": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Response status",
"example": "success"
},
"data": {
"description": "Created private link data (either time-based or usage-based)",
"oneOf": [
{
"$ref": "#/components/schemas/TimeBasedPrivateLinkOutput"
},
{
"$ref": "#/components/schemas/UsageBasedPrivateLinkOutput"
}
]
}
},
"required": ["status", "data"]
},
"GetPrivateLinksOutput": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Response status",
"example": "success"
},
"data": {
"type": "array",
"description": "Array of private links for the event type (mix of time-based and usage-based)",
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/TimeBasedPrivateLinkOutput"
},
{
"$ref": "#/components/schemas/UsageBasedPrivateLinkOutput"
}
]
}
}
},
"required": ["status", "data"]
},
"UpdatePrivateLinkBody": {
"type": "object",
"properties": {
"expiresAt": {
"format": "date-time",
"type": "string",
"description": "New expiration date for time-based links",
"example": "2024-12-31T23:59:59.000Z"
},
"maxUsageCount": {
"type": "number",
"description": "New maximum number of times the link can be used",
"example": 10,
"minimum": 1
}
}
},
"UpdatePrivateLinkOutput": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Response status",
"example": "success"
},
"data": {
"description": "Updated private link data (either time-based or usage-based)",
"oneOf": [
{
"$ref": "#/components/schemas/TimeBasedPrivateLinkOutput"
},
{
"$ref": "#/components/schemas/UsageBasedPrivateLinkOutput"
}
]
}
},
"required": ["status", "data"]
},
"DeletePrivateLinkOutput": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Response status",
"example": "success"
},
"data": {
"type": "object",
"description": "Deleted link information",
"properties": {
"linkId": {
"type": "string",
"example": "abc123def456"
},
"message": {
"type": "string",
"example": "Private link deleted successfully"
}
}
}
},
"required": ["status", "data"]
},
"UserWebhookOutputDto": {
"type": "object",
"properties": {