-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add resilience layer with caching and graceful degradation for … #2
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
feat: add resilience layer with caching and graceful degradation for … #2
Conversation
…Supabase outages see website/#1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements a resilience layer to handle Supabase outages gracefully by adding caching and fallback mechanisms.
Key Changes
- Implements a caching strategy that pre-fetches signatories data during build/start and stores it locally
- Adds graceful degradation with automatic fallback to cached data when Supabase is unavailable
- Includes a testing mode to simulate Supabase outages via environment variable
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/pages/signatories.tsx |
Enables error banner display on the signatories page |
src/components/SignersList.tsx |
Implements core resilience logic with error handling and cache fallback |
src/components/SignersList.module.css |
Adds styling for error banner showing cache status |
src/components/SignManifest.tsx |
Adds outage detection and disables signing when Supabase is unavailable |
src/components/SignManifest.module.css |
Adds styling for warning banner |
scripts/cache-signatories.cjs |
Creates script to fetch and cache signatories data from Supabase |
package.json |
Integrates cache script into prebuild and prestart hooks |
docusaurus.config.ts |
Adds configuration for simulating Supabase outages |
.gitignore |
Excludes generated cache file from version control |
.env |
Adds simulation toggle environment variable |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| console.log('🔄 Fetching signatories from Supabase...'); | ||
|
|
||
| // Use fetch API to query Supabase REST API directly | ||
| const response = await fetch( |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The script uses the global fetch API which is only available in Node.js 18+. Consider adding a comment documenting the minimum Node.js version requirement, or add a runtime check with a helpful error message if fetch is not available.
| window.addEventListener('signature-changed', handler); | ||
| return () => window.removeEventListener('signature-changed', handler); | ||
| }, [supabase]); | ||
| }, [supabase, simulateDown]); |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dependency array is missing shouldUseMockData. Since shouldUseMockData is calculated from USE_MOCK_DATA and simulateDown, and simulateDown is included in the dependency array, consider adding shouldUseMockData to the dependency array or simplifying by using simulateDown directly in the condition on line 45.
| {cachedSignatories.cached_at && ( | ||
| <span className={styles.cacheDate}> | ||
| {' '} | ||
| (as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')}) | ||
| </span> | ||
| )} |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling if cachedSignatories.cached_at contains an invalid date string. Consider wrapping the new Date() call in a try-catch or validating the date before rendering to prevent potential runtime errors.
| {cachedSignatories.cached_at && ( | |
| <span className={styles.cacheDate}> | |
| {' '} | |
| (as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')}) | |
| </span> | |
| )} | |
| {cachedSignatories.cached_at && (() => { | |
| const cacheDate = new Date(cachedSignatories.cached_at); | |
| if (!isNaN(cacheDate.getTime())) { | |
| return ( | |
| <span className={styles.cacheDate}> | |
| {' '} | |
| (as of {cacheDate.toLocaleString('en-US')}) | |
| </span> | |
| ); | |
| } | |
| return ( | |
| <span className={styles.cacheDate}> | |
| {' '} | |
| (as of unknown date) | |
| </span> | |
| ); | |
| })()} |
| {showErrorBanner && error && usingCache && ( | ||
| <div className={styles.errorBanner}> | ||
| {error}. Showing cached signatories | ||
| {cachedSignatories.cached_at && ( | ||
| <span className={styles.cacheDate}> | ||
| {' '} | ||
| (as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')}) | ||
| </span> |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error banner only displays when both error AND usingCache are true. This means if there's an error but no cached data is available (lines 89-91), no error message is shown to the user. Consider showing an error message even when cached data is not available, so users are informed of the issue.
| {showErrorBanner && error && usingCache && ( | |
| <div className={styles.errorBanner}> | |
| {error}. Showing cached signatories | |
| {cachedSignatories.cached_at && ( | |
| <span className={styles.cacheDate}> | |
| {' '} | |
| (as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')}) | |
| </span> | |
| {showErrorBanner && error && ( | |
| <div className={styles.errorBanner}> | |
| {error}. | |
| {usingCache ? ( | |
| <> | |
| {' '}Showing cached signatories | |
| {cachedSignatories.cached_at && ( | |
| <span className={styles.cacheDate}> | |
| {' '} | |
| (as of {new Date(cachedSignatories.cached_at).toLocaleString('en-US')}) | |
| </span> | |
| )} | |
| </> | |
| ) : ( | |
| <> No cached data available.</> |
| SUPABASE_URL=https://cuwxnggcavvzbqbidaml.supabase.co | ||
| SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImN1d3huZ2djYXZ2emJxYmlkYW1sIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjMzMTA5NzAsImV4cCI6MjA3ODg4Njk3MH0.X0BjHpf6hR3v3Iwv7BN5wkJhewLTzCZnbTq090vuGi0 | ||
| SIMULATE_SUPABASE_DOWN=false |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .env file should not be committed to version control as it contains sensitive credentials. Add .env to .gitignore and create a .env.example file with placeholder values to document required environment variables.
…Supabase outages
see website/#1