feat: add calendar cache status and actions (#22532)#11
Conversation
* feat: add calendar cache status dropdown - Add updatedAt field to CalendarCache schema with migration - Create tRPC cacheStatus endpoint for fetching cache timestamps - Add action dropdown to CalendarSwitch for Google Calendar entries - Display formatted last updated timestamp in dropdown - Add placeholder for cache deletion functionality - Include translation strings for dropdown content The dropdown only appears for Google Calendar integrations that have active cache entries and provides cache management options for future extensibility. Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: resolve Prisma type incompatibilities in repository files - Remove problematic satisfies clause in selectedCalendar.ts - Add missing cacheStatus parameter to ConnectedCalendarList component - Fixes type errors that were preventing CI from passing Co-Authored-By: zomars@cal.com <zomars@me.com> * refactor: integrate cache status into connectedCalendars handler - Remove separate cacheStatus tRPC endpoint as requested - Return cache status as separate field in connectedCalendars response - Update UI components to use cache data from connectedCalendars - Fix Prisma type incompatibilities in repository files Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: resolve Prisma type incompatibilities and fix data flow for cache status - Fix Prisma.SortOrder usage in membership.ts orderBy clauses - Remove problematic satisfies clause in selectedCalendar.ts - Fix TeamSelect type reference in team.ts - Update SelectedCalendarsSettingsWebWrapper to properly pass cacheStatus data flow Co-Authored-By: zomars@cal.com <zomars@me.com> * Discard changes to packages/lib/server/repository/membership.ts * Discard changes to packages/lib/server/repository/team.ts * fix: improve calendar cache dropdown with proper formatting and subscription logic - Fix timestamp HTML entity encoding with interpolation escapeValue: false - Only show dropdown for subscribed Google calendars (googleChannelId exists) - Hide delete option when no cache data exists - Include updatedAt and googleChannelId fields upstream in user repository - Update data flow to pass subscription status through components Co-Authored-By: zomars@cal.com <zomars@me.com> * feat: update SelectedCalendar.updatedAt when Google webhooks trigger cache refresh - Add updateManyByCredentialId method to SelectedCalendarRepository - Update fetchAvailabilityAndSetCache to refresh SelectedCalendar timestamps - Ensure webhook flow updates both CalendarCache and SelectedCalendar records - Maintain proper timestamp tracking for calendar cache operations Co-Authored-By: zomars@cal.com <zomars@me.com> * Add script to automate Tunnelmole webhook setup Introduces test-gcal-webhooks.sh to start Tunnelmole, extract the public URL, and update GOOGLE_WEBHOOK_URL in the .env file. Handles process management, rate limits, and ensures environment configuration for Google Calendar webhooks. * Update dev:cron script to use npx tsx Replaces 'ts-node' with 'npx tsx' in the dev:cron script for running cron-tester.ts, likely to improve compatibility or leverage tsx features. * Update cache status string and improve CalendarSwitch UI Renamed 'last_updated' to 'cache_last_updated' in locale file for clarity and updated CalendarSwitch to use the new string. Also added dark mode text color support for cache status display. * refactor: move cache management to credential-level dropdown with Remove App - Create CredentialActionsDropdown component consolidating cache and app removal actions - Add deleteCache tRPC mutation for credential-level cache deletion - Update connectedCalendars handler to include cacheUpdatedAt at credential level - Move dropdown from individual CalendarSwitch to credential level in SelectedCalendarsSettingsWebWrapper - Remove cache-related props from CalendarSwitch component - Add translation strings for cache management actions - Consolidate all credential-level actions (cache management + Remove App) in one dropdown Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: remove duplicate translation keys in common.json - Remove duplicate cache-related keys at lines 51-56 - Keep properly positioned keys later in file - Addresses GitHub comment from zomars about duplicate keys Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: rename translation key to cache_last_updated - Address GitHub comment from zomars - Rename 'last_updated' to 'cache_last_updated' for specificity - Update usage in CredentialActionsDropdown component Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: remove duplicate last_updated translation key Co-Authored-By: zomars@cal.com <zomars@me.com> * fix: add confirmation dialog for cache deletion and use repository pattern - Add confirmation dialog for destructive cache deletion action - Replace direct Prisma calls with CalendarCacheRepository pattern - Add getCacheStatusByCredentialIds method to repository interface - Fix import paths for UI components - Address GitHub review comments from zomars Co-Authored-By: zomars@cal.com <zomars@me.com> * Update CredentialActionsDropdown.tsx * Update common.json * Update common.json * fix: remove nested div wrapper to resolve HTML structure error - Remove wrapping div around DisconnectIntegration component - Fixes nested <p> tag validation error preventing Remove App functionality - Maintains existing confirmation dialog patterns Co-Authored-By: zomars@cal.com <zomars@me.com> * Fix API handler response termination logic Removed unnecessary return values after setting status in the integrations API handler. This clarifies response handling and prevents returning the response object when not needed. Resolves "API handler should not return a value, received object". * fix: 400 is correct error code for computing slot for past booking (#22574) * fix * add test * chore: release v5.5.1 * Refactor credential disconnect to use confirmation dialog Replaces the DisconnectIntegration component with an inline confirmation dialog for removing app credentials. Adds disconnect mutation logic and updates UI to improve user experience and consistency. * Set default value for CalendarCache.updatedAt Added a default value of NOW() for the updatedAt column in the CalendarCache table to ensure existing and future rows have a valid timestamp. Updated the Prisma schema to reflect this change and provide compatibility for legacy data and raw inserts. --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Benny Joo <sldisek783@gmail.com> Co-authored-by: emrysal <me@alexvanandel.com>
WalkthroughThis set of changes introduces cache management features for calendar integrations, including new database fields, repository methods, and UI components. It adds localization strings, updates data fetching to include cache timestamps, and implements TRPC endpoints and handlers for cache deletion. The UI now provides dropdown actions for cache and credential management. Supporting scripts and type definitions are also updated. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI (CredentialActionsDropdown)
participant TRPC
participant deleteCacheHandler
participant DB (CalendarCache)
participant DB (Credential)
User->>UI (CredentialActionsDropdown): Click "Delete Cache"
UI (CredentialActionsDropdown)->>TRPC: Call deleteCache mutation with credentialId
TRPC->>deleteCacheHandler: Invoke handler with user context, credentialId
deleteCacheHandler->>DB (Credential): Verify credential ownership
alt Credential valid
deleteCacheHandler->>DB (CalendarCache): Delete cache entries for credentialId
deleteCacheHandler-->>TRPC: Return { success: true }
TRPC-->>UI (CredentialActionsDropdown): Return success
UI (CredentialActionsDropdown)-->>User: Show success toast
else Invalid credential
deleteCacheHandler-->>TRPC: Throw access denied error
TRPC-->>UI (CredentialActionsDropdown): Return error
UI (CredentialActionsDropdown)-->>User: Show error toast
end
sequenceDiagram
participant UI (Settings Wrapper)
participant TRPC
participant connectedCalendarsHandler
participant CalendarCacheRepository
participant DB
UI (Settings Wrapper)->>TRPC: Fetch connected calendars
TRPC->>connectedCalendarsHandler: Handle request
connectedCalendarsHandler->>DB: Fetch connected calendars
connectedCalendarsHandler->>CalendarCacheRepository: getCacheStatusByCredentialIds(credentialIds)
CalendarCacheRepository->>DB: Query cache groupBy credentialId, max(updatedAt)
CalendarCacheRepository-->>connectedCalendarsHandler: Return cache status map
connectedCalendarsHandler-->>TRPC: Return enriched calendars with cacheUpdatedAt
TRPC-->>UI (Settings Wrapper): Return enriched data
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~18 minutes Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (5)
scripts/test-gcal-webhooks.sh (2)
41-52: Fix unused loop variable.The static analysis tool correctly identified that the loop variable
iis unused. Consider using an underscore to indicate an intentionally unused variable:- for i in {1..20}; do + for _ in {1..20}; doOtherwise, the retry logic and rate limit handling are well-implemented.
67-71: Consider portability for sed command.The
sed -i ''syntax is macOS-specific. For better portability across Linux and macOS, consider using a more portable approach:-if grep -q '^GOOGLE_WEBHOOK_URL=' "$ENV_FILE"; then - sed -i '' -E "s|^GOOGLE_WEBHOOK_URL=.*|GOOGLE_WEBHOOK_URL=$TUNNEL_URL|" "$ENV_FILE" -else +if grep -q '^GOOGLE_WEBHOOK_URL=' "$ENV_FILE"; then + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' -E "s|^GOOGLE_WEBHOOK_URL=.*|GOOGLE_WEBHOOK_URL=$TUNNEL_URL|" "$ENV_FILE" + else + sed -i -E "s|^GOOGLE_WEBHOOK_URL=.*|GOOGLE_WEBHOOK_URL=$TUNNEL_URL|" "$ENV_FILE" + fi +elseAlternatively, use a temporary file approach that works consistently across platforms.
apps/web/public/static/locales/en/common.json (1)
3382-3388: Maintain placeholder & punctuation consistency across new i18n keys
cache_last_updatedcurrently uses{{timestamp}}whereas existing keys (e.g.refund_failed_subject,event_type_seats) rely on more descriptive placeholders like{{date}}or{{count}}. Consider renaming to something less implementation-specific such as{{date}}or{{value}}so translators have clearer context and you avoid leaking internal variable names into translation workflows.For user-facing strings, keep terminal punctuation consistent.
cache_deleted_successfullyends without a period while similar success toasts earlier (team_upgraded_successfully,profile_updated_successfully, etc.) omit punctuation, so this is fine.error_deleting_cachefollows the same pattern as other_errorkeys—good.No pluralisation or html tags are required here, but remember to escape colons in translation files (
Last updated:) for certain i18n tools if they treat:specially.Nothing blocking, just a light clean-up to stay aligned with existing conventions.
packages/app-store/googlecalendar/lib/CalendarService.ts (1)
1023-1024: Good integration of timestamp tracking with cache operations.The call to
SelectedCalendarRepository.updateManyByCredentialIdafter cache operations is well-positioned and follows the logical flow. The empty object parameter suggests it's leveraging automaticupdatedAtfield updates.Consider adding error handling for the repository call to prevent cache operations from failing if the timestamp update encounters issues:
+ try { // Update SelectedCalendar.updatedAt for all calendars under this credential await SelectedCalendarRepository.updateManyByCredentialId(this.credential.id, {}); + } catch (error) { + this.log.error("Failed to update selected calendar timestamps", safeStringify(error)); + // Continue execution as this is not critical for cache functionality + }packages/features/apps/components/CredentialActionsDropdown.tsx (1)
75-128: Well-structured dropdown UI with good UX patterns.The implementation demonstrates solid UX practices:
- Clear cache status display with formatted timestamps
- Logical separation between cache and credential actions
- Appropriate destructive styling for delete operations
- Proper state management for modal interactions
Consider using a more accessible date formatting approach:
- {t("cache_last_updated", { - timestamp: new Intl.DateTimeFormat("en-US", { - dateStyle: "short", - timeStyle: "short", - }).format(new Date(cacheUpdatedAt)), - interpolation: { escapeValue: false }, - })} + {t("cache_last_updated", { + timestamp: new Intl.DateTimeFormat(undefined, { + dateStyle: "short", + timeStyle: "short", + }).format(new Date(cacheUpdatedAt)), + interpolation: { escapeValue: false }, + })}Using
undefinedinstead of"en-US"respects the user's locale preferences.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
apps/web/package.json(1 hunks)apps/web/public/static/locales/en/common.json(1 hunks)packages/app-store/googlecalendar/lib/CalendarService.ts(1 hunks)packages/features/apps/components/CredentialActionsDropdown.tsx(1 hunks)packages/features/calendar-cache/calendar-cache.repository.interface.ts(1 hunks)packages/features/calendar-cache/calendar-cache.repository.mock.ts(1 hunks)packages/features/calendar-cache/calendar-cache.repository.ts(1 hunks)packages/lib/getConnectedDestinationCalendars.ts(1 hunks)packages/lib/server/repository/selectedCalendar.ts(2 hunks)packages/lib/server/repository/user.ts(1 hunks)packages/platform/atoms/selected-calendars/wrappers/SelectedCalendarsSettingsWebWrapper.tsx(5 hunks)packages/prisma/migrations/20250715160635_add_calendar_cache_updated_at/migration.sql(1 hunks)packages/prisma/schema.prisma(1 hunks)packages/trpc/server/routers/viewer/calendars/_router.tsx(2 hunks)packages/trpc/server/routers/viewer/calendars/connectedCalendars.handler.ts(2 hunks)packages/trpc/server/routers/viewer/calendars/deleteCache.handler.ts(1 hunks)scripts/test-gcal-webhooks.sh(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
packages/trpc/server/routers/viewer/calendars/_router.tsx (1)
packages/trpc/server/routers/viewer/calendars/deleteCache.handler.ts (1)
deleteCacheHandler(13-33)
packages/app-store/googlecalendar/lib/CalendarService.ts (2)
packages/lib/server/repository/selectedCalendar.ts (1)
SelectedCalendarRepository(42-438)packages/platform/libraries/index.ts (1)
SelectedCalendarRepository(112-112)
packages/features/apps/components/CredentialActionsDropdown.tsx (1)
packages/ui/components/dropdown/Dropdown.tsx (5)
Dropdown(12-12)DropdownMenuTrigger(15-26)DropdownMenuContent(34-51)DropdownMenuItem(63-71)DropdownItem(161-181)
packages/lib/getConnectedDestinationCalendars.ts (1)
packages/types/Calendar.d.ts (1)
SelectedCalendar(318-321)
🪛 Shellcheck (0.10.0)
scripts/test-gcal-webhooks.sh
[warning] 41-41: i appears unused. Verify use (or export if used externally).
(SC2034)
🔇 Additional comments (28)
packages/lib/server/repository/selectedCalendar.ts (2)
260-260: LGTM! Good refactoring.The simplification by removing the intermediate variable and directly passing parameters makes the code more concise and readable while maintaining the same functionality.
400-405: LGTM! Well-implemented bulk update method.The new
updateManyByCredentialIdmethod provides a clean abstraction for bulk updating selected calendars by credential ID. The implementation correctly usesupdateManyfor efficient bulk operations and follows the repository pattern consistently.scripts/test-gcal-webhooks.sh (3)
1-20: LGTM! Well-structured initialization.The script has proper configuration setup with clear variable names, appropriate signal trapping for cleanup, and good process management using
pgrepto check for existing Tunnelmole instances.
11-18: LGTM! Proper resource cleanup.The cleanup function correctly handles process termination by only killing processes owned by the script and uses proper signal handling with
killandwait.
76-79: LGTM! Proper process lifecycle management.The conditional wait logic correctly handles different scenarios - only waiting for processes the script started while allowing immediate exit when reusing existing tunnels.
packages/prisma/schema.prisma (1)
718-719: LGTM! Well-designed timestamp field.The addition of the
updatedAtfield with@default(now())and@updatedAtis properly implemented. The default value ensures existing records receive appropriate timestamps during migration, while the@updatedAtattribute provides automatic timestamp management for future updates.packages/features/calendar-cache/calendar-cache.repository.mock.ts (1)
27-30: LGTM! Consistent mock implementation.The new
getCacheStatusByCredentialIdsmethod follows the established mock pattern with appropriate logging and returns a sensible empty array result for the disabled cache scenario.packages/lib/server/repository/user.ts (1)
899-900: LGTM! Appropriate addition of cache metadata fields.The addition of
updatedAtandgoogleChannelIdto theselectedCalendarsselection is consistent with the calendar cache status feature. These fields will enable the UI to display cache freshness information and manage Google Calendar integrations effectively.packages/prisma/migrations/20250715160635_add_calendar_cache_updated_at/migration.sql (1)
1-9: LGTM! Well-structured migration with safe default handling.The migration correctly adds the
updatedAtcolumn withDEFAULT NOW()to handle existing rows safely. TheTIMESTAMP(3)type is appropriate for millisecond precision tracking.Note: The warning comment at the top mentions "without a default value" but the actual SQL includes
DEFAULT NOW(), which resolves the issue safely.packages/features/calendar-cache/calendar-cache.repository.interface.ts (1)
30-32: LGTM! Clean interface addition.The new method signature is well-designed with clear parameter and return types. The nullable
updatedAtfield appropriately handles cases where cache entries may not have update timestamps.packages/trpc/server/routers/viewer/calendars/_router.tsx (1)
28-33: LGTM! Follows established patterns.The new
deleteCachemutation properly usesauthedProcedurefor authentication, includes appropriate input validation with zod, and follows the consistent dynamic import pattern used elsewhere in the router.packages/features/calendar-cache/calendar-cache.repository.ts (1)
173-188: LGTM! Efficient implementation.The method correctly uses Prisma's
groupBywith_maxaggregation to efficiently retrieve the latest cache update timestamp for each credential. Theinoperator appropriately handles the array of credential IDs, and the result mapping matches the interface contract.packages/trpc/server/routers/viewer/calendars/deleteCache.handler.ts (2)
17-26: Security validation implemented correctly.The credential ownership verification is essential and properly implemented. The handler correctly ensures that only the authenticated user can delete their own credential's cache data.
28-30: Cache deletion is appropriate.The
deleteManyoperation correctly removes all cache entries associated with the credential. This is the expected behavior when a user wants to clear their calendar cache.packages/lib/getConnectedDestinationCalendars.ts (1)
21-28: LGTM! Consistent type updates.The addition of
"updatedAt"and"googleChannelId"to both selected calendar arrays is consistent and supports the new cache status tracking functionality. The type changes align well with the broader calendar cache management features being introduced.packages/trpc/server/routers/viewer/calendars/connectedCalendars.handler.ts (2)
1-1: LGTM!The import of
CalendarCacheRepositoryis correctly structured and follows standard module import conventions.
39-39: LGTM!The return statement correctly uses the enriched connected calendars data, ensuring cache timestamps are available to the frontend.
packages/platform/atoms/selected-calendars/wrappers/SelectedCalendarsSettingsWebWrapper.tsx (4)
5-5: LGTM!The import change from
DisconnectIntegrationtoCredentialActionsDropdowncorrectly reflects the component upgrade.
70-79: Excellent implementation of the new dropdown component.The
CredentialActionsDropdownintegration is well-executed:
- Properly wrapped in a flex container for consistent styling
- All necessary props are provided including cache timestamp
- Maintains existing functionality while adding cache management capabilities
- Clean and readable implementation
98-98: Good defensive programming practice.Explicitly providing
|| nullensures a clear API contract and prevents undefined values from being passed to the component.
123-132: Consistent dropdown implementation in error scenarios.The
CredentialActionsDropdownusage in the alert matches the main implementation perfectly, providing users with consistent management options regardless of calendar status.packages/features/apps/components/CredentialActionsDropdown.tsx (7)
1-18: Well-organized imports.The imports are comprehensive and appropriately sourced. Good use of destructuring for dropdown components and clear separation of concerns.
20-27: Well-designed props interface.The interface clearly distinguishes required from optional props and uses appropriate TypeScript types. The naming is descriptive and covers all necessary use cases.
29-40: Clean component setup.The function signature with proper destructuring and state management using hooks follows React best practices. State variables are appropriately named and scoped.
42-50: Well-implemented cache deletion mutation.The TRPC mutation properly handles both success and error cases with appropriate user feedback via toast notifications. The integration with the success callback is clean.
52-65: Excellent disconnect mutation with proper cache management.The mutation implementation includes crucial cache invalidation in the
onSettledhook, ensuring UI consistency after credential removal. The invalidation of bothconnectedCalendarsandapps.integrationsqueries is thorough.
67-73: Sound conditional rendering logic.The conditions appropriately check integration type, permissions, and cache availability. The early return pattern prevents unnecessary rendering when no actions are available.
130-155: Excellent implementation of confirmation dialogs.Both dialogs follow consistent patterns with:
- Appropriate danger styling for destructive actions
- Clear confirmation messaging
- Proper mutation parameter passing
- Good modal state management
This provides essential user protection against accidental data loss.
| "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next", | ||
| "dev": "yarn copy-static && next dev --turbopack", | ||
| "dev:cron": "ts-node cron-tester.ts", | ||
| "dev:cron": "npx tsx cron-tester.ts", |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Include tsx as a pinned devDependency and clean up ts-node
npx tsx cron-tester.ts implicitly downloads the latest tsx on demand.
Pinning tsx in devDependencies makes CI runs deterministic, speeds up local
invocations, and allows lock-file auditing. If no other script still requires
ts-node, you can drop that package to reduce install size.
Example patch:
@@
- "ts-node": "^10.9.1",
+ "tsx": "^4.7.0"Verify whether any remaining scripts call ts-node; if none do, remove it.
🏁 Script executed:
#!/bin/bash
set -e
echo "=== apps/web/package.json: devDependencies ==="
jq '{devDependencies}' apps/web/package.json || true
echo
echo "=== apps/web/package.json: scripts ==="
jq '{scripts}' apps/web/package.json || true
echo
echo "=== Searching entire repo for ts-node usage ==="
rg --no-heading --line-number --color never 'ts-node' --glob '!node_modules/*' .
echo
echo "=== Searching entire repo for tsx usage ==="
rg --no-heading --line-number --color never 'tsx' --glob '!node_modules/*' .Length of output: 294982
Include and Pin tsx, Don’t Remove ts-node Yet
- Add
tsxto apps/web/package.json devDependencies (pin to a specific version for stability):"devDependencies": { - "ts-node": "^10.9.1",
- "ts-node": "^10.9.1",
- "tsx": "^4.7.0"
}
- Update the cron script to use the installed binary instead of `npx`:
```diff
"scripts": {
- "dev:cron": "npx tsx cron-tester.ts",
+ "dev:cron": "tsx cron-tester.ts",
…
}
- Leave
ts-nodein place for now—it's still used by:yarn check-changed-files(ts-node scripts/ts-check-changed-files.ts)yarn translate-locales(ts-node scripts/check-missing-translations.ts)
Migrate these totsxwhen you’re ready, then removets-node.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "dev:cron": "npx tsx cron-tester.ts", | |
| "devDependencies": { | |
| "ts-node": "^10.9.1", | |
| "tsx": "^4.7.0" | |
| }, | |
| "scripts": { | |
| "dev:cron": "tsx cron-tester.ts", | |
| … | |
| } |
🤖 Prompt for AI Agents
In apps/web/package.json at line 11, add tsx as a pinned devDependency with a
specific version for stability. Update the "dev:cron" script to use the locally
installed tsx binary instead of npx. Do not remove ts-node yet, as it is still
required by other scripts; keep it until those scripts are migrated to tsx.
| const credentialIds = connectedCalendars.map((cal) => cal.credentialId); | ||
| const cacheRepository = new CalendarCacheRepository(); | ||
| const cacheStatuses = await cacheRepository.getCacheStatusByCredentialIds(credentialIds); | ||
|
|
||
| const cacheStatusMap = new Map(cacheStatuses.map((cache) => [cache.credentialId, cache.updatedAt])); | ||
|
|
||
| const enrichedConnectedCalendars = connectedCalendars.map((calendar) => ({ | ||
| ...calendar, | ||
| cacheUpdatedAt: cacheStatusMap.get(calendar.credentialId) || null, | ||
| })); |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Well-structured cache enrichment logic.
The implementation correctly:
- Extracts credential IDs from connected calendars
- Uses repository pattern for data access
- Creates an efficient lookup map for cache statuses
- Enriches data without mutating original objects
- Handles missing cache entries gracefully with
|| null
Consider adding error handling for the cache repository call to ensure robustness:
🏁 Script executed:
#!/bin/bash
# Verify error handling patterns in similar repository calls
ast-grep --pattern 'await $_.getCacheStatusByCredentialIds($_)'Length of output: 236
Add robust error handling around cache status fetching
While the cache enrichment logic is solid, it’s safer to guard against failures and edge cases in getCacheStatusByCredentialIds. Specifically:
- Early-exit when there are no credential IDs:
const credentialIds = connectedCalendars.map(c => c.credentialId); if (credentialIds.length === 0) { return connectedCalendars.map(c => ({ ...c, cacheUpdatedAt: null })); }
- Wrap the repository call in a try/catch to prevent unhandled rejections:
let cacheStatuses; try { cacheStatuses = await cacheRepository.getCacheStatusByCredentialIds(credentialIds); } catch (error) { // Replace with your logging mechanism console.error('Failed to fetch cache statuses', error); cacheStatuses = []; }
Then build the lookup map and enrich as before.
File to update:
- packages/trpc/server/routers/viewer/calendars/connectedCalendars.handler.ts (lines 27–36)
🤖 Prompt for AI Agents
In packages/trpc/server/routers/viewer/calendars/connectedCalendars.handler.ts
around lines 27 to 36, add an early return that maps connectedCalendars to
include cacheUpdatedAt: null if credentialIds is empty. Then wrap the call to
getCacheStatusByCredentialIds in a try/catch block to handle potential errors
gracefully by logging the error and setting cacheStatuses to an empty array.
Keep the rest of the enrichment logic unchanged after these additions.
|
This PR is being marked as stale due to inactivity. |
Test 1
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores