-
Notifications
You must be signed in to change notification settings - Fork 0
Fix cache deduplication, circuit breaker error handling, and test isolation #294
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
Conversation
…eaker error handling, CSS import, test isolation Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>
… documentation Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>
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
Improves EzyGo request deduplication/rate-limiting behavior and refines circuit breaker error classification so client-side failures don’t open the circuit globally, while restoring a UI spinner style import and fixing a Tailwind @apply typo.
Changes:
- Normalizes endpoint strings in cache keys and adds a test helper to reset shared rate-limiter/dedup state.
- Introduces
NonBreakerErrorand updates the circuit breaker to ignore these errors for failure counting. - Adjusts backend proxy behavior to throw on upstream 5xx (intended to trip the breaker), plus minor UI/CSS fixes.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/ezygo-batch-fetcher.ts | Normalizes cache keys, changes dedup window semantics (TTL-based), adds NonBreakerError classification and a test reset helper. |
| src/lib/circuit-breaker.ts | Adds NonBreakerError and excludes it from breaker failure counting. |
| src/lib/tests/ezygo-batch-fetcher.test.ts | Resets shared module state between tests to improve isolation. |
| src/components/loading.tsx | Restores Ring2 CSS import needed for spinner rendering. |
| src/app/globals.css | Fixes Tailwind important modifier syntax in @apply. |
| src/app/api/backend/[...path]/route.ts | Throws on upstream 5xx inside circuit-breaker wrapper to (attempt to) trip breaker. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Normalize endpoint for consistent cache key (remove leading slashes) | ||
| const normalizedEndpoint = endpoint.replace(/^\/+/, ''); | ||
|
|
||
| // Create secure cache key using SHA-256 hash of token + method + endpoint + body | ||
| // This prevents cross-user request deduplication from token suffix collisions | ||
| const tokenHash = createHash('sha256').update(token).digest('hex').slice(0, 16); | ||
| const cacheKey = `${method}:${tokenHash}:${endpoint}:${JSON.stringify(body || {})}`; | ||
| const cacheKey = `${method}:${tokenHash}:${normalizedEndpoint}:${JSON.stringify(body || {})}`; |
Copilot
AI
Feb 8, 2026
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.
Endpoint normalization in cache keys is new behavior but isn’t covered by a test. Add a test that calls fetchEzygoData('/endpoint', token) and fetchEzygoData('endpoint', token) concurrently (or back-to-back within the TTL window) and asserts only one fetch call occurs, to prevent regressions.
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.
Added test in commit 0c6f828. The test verifies that /myprofile and myprofile deduplicate correctly, resulting in only one fetch call.
| try { | ||
| const result = await fn(); | ||
| this.onSuccess(); | ||
| return result; | ||
| } catch (error) { | ||
| // Don't count NonBreakerError (4xx) as breaker failures | ||
| if (error instanceof NonBreakerError) { | ||
| throw error; | ||
| } | ||
| this.onFailure(error); | ||
| throw error; | ||
| } finally { |
Copilot
AI
Feb 8, 2026
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 new NonBreakerError behavior isn’t covered by the existing circuit breaker tests. Add coverage verifying that a NonBreakerError does not increment the failure count / open the circuit and (importantly) does not leave the breaker stuck in HALF_OPEN (i.e., it should still be able to transition back to CLOSED when appropriate).
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.
Added comprehensive NonBreakerError tests in commit 0c6f828 covering:
- No failure count increment
- Circuit stays closed with multiple NonBreakerErrors
- HALF_OPEN progression
- Prior failure reset in CLOSED state
| } finally { | ||
| releaseSlot(); | ||
| // Remove from cache after a short delay to allow concurrent requests to share | ||
| setTimeout(() => { | ||
| requestCache.delete(cacheKey); | ||
| }, 100); | ||
| // Let TTL handle cache expiration (15s window for deduplication) | ||
| // Don't force delete - this allows closely-spaced sequential calls to deduplicate | ||
| } |
Copilot
AI
Feb 8, 2026
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.
With the forced cache eviction removed, a rejected requestPromise stays in requestCache until TTL expiry. That means a transient failure (e.g., a single 500/timeout) will be “deduplicated” into repeated failures for up to 15s, preventing immediate retries and potentially masking recovery. Consider evicting the cache entry when the promise settles with an error (while still keeping successful promises cached for the desired dedup window), and update the nearby comments to reflect that settled promises are now cached, not only in-flight ones.
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.
src/lib/ezygo-batch-fetcher.ts
Outdated
| const errorMsg = `EzyGo API error: ${response.status} ${response.statusText}`; | ||
| // 4xx errors (client errors like 401/403) shouldn't trip the circuit breaker | ||
| // They indicate invalid token/permissions, not API failure | ||
| if (response.status >= 400 && response.status < 500) { |
Copilot
AI
Feb 8, 2026
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 comment says only “401/403” style client errors should bypass the circuit breaker, but the condition treats all 4xx (including 408/429) as NonBreakerError. Either narrow the status-code check to the intended set, or update the comment and consider whether some 4xx (notably 429) should still count as breaker failures.
| if (response.status >= 400 && response.status < 500) { | |
| if (response.status === 401 || response.status === 403) { |
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.
Fixed in commit 0c6f828. Now only 401, 403, and 404 are treated as NonBreakerError. Other 4xx like 429 (rate limit) will trip the circuit breaker as they indicate service degradation.
| return result; | ||
| } catch (error) { | ||
| // Don't count NonBreakerError (4xx) as breaker failures | ||
| if (error instanceof NonBreakerError) { |
Copilot
AI
Feb 8, 2026
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.
NonBreakerError is rethrown without calling onSuccess() or onFailure(). In HALF_OPEN this can leave the breaker stuck in HALF_OPEN indefinitely (no successCount progress) even though the upstream is reachable, and in CLOSED it won’t reset prior failure counts. Consider treating NonBreakerError as a “success” for breaker state bookkeeping (at least in HALF_OPEN / when failures>0), while still rethrowing it to callers.
| if (error instanceof NonBreakerError) { | |
| if (error instanceof NonBreakerError) { | |
| // Treat NonBreakerError as a logical "success" for breaker bookkeeping | |
| // so that HALF_OPEN can progress and prior failures can be cleared. | |
| if (this.state === 'HALF_OPEN' || this.failures > 0) { | |
| this.onSuccess(); | |
| } |
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.
Fixed in commit 0c6f828. NonBreakerError now calls onSuccess() when in HALF_OPEN or when failures > 0, allowing proper state progression and failure count reset.
| // Check for server errors (5xx) and throw to trip circuit breaker | ||
| if (res.status >= 500) { | ||
| throw new Error(`Upstream server error: ${res.status} ${res.statusText}`); | ||
| } | ||
|
|
||
| // Always return consistent shape with isClientError flag | ||
| return { res, text }; |
Copilot
AI
Feb 8, 2026
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.
Throwing on res.status >= 500 inside the circuit-breaker-wrapped callback causes the outer catch to return a generic 502 (Upstream fetch failed) instead of proxying the actual upstream 5xx status/body (and bypasses the existing !res.ok handling below). If you need 5xx to trip the breaker and preserve response semantics, throw a typed error that carries {status, statusText, body} (or similar) and translate it back to a NextResponse in the outer catch, rather than treating it as a transport failure.
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.
Fixed in commit 0c6f828. Created UpstreamServerError class that carries status, statusText, and body. The catch block now handles this error type separately, preserving the actual upstream 5xx response while still tripping the circuit breaker.
|
@copilot apply changes based on the comments in this thread |
… scope, evict failed promises Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>
…entation Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com>
* Implement EzyGo API Batch Fetcher with Rate Limiting and Circuit Breaker - Added EzyGo API Batch Fetcher to optimize concurrent API calls. - Implemented request deduplication using LRU cache with a 15-second TTL. - Introduced rate limiting to restrict concurrent requests to a maximum of 3. - Integrated a circuit breaker pattern to handle API failures gracefully. - Created health check endpoint to monitor rate limiter and circuit breaker status. - Developed comprehensive documentation for rate limiting and verification processes. - Ensured client-side hooks and server-side calls are protected against rate limiting. * Address PR review feedback: security, docs, error handling, tests (#293) * Initial plan * Fix PR review issues: security, docs, error handling, and UI Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Add comprehensive unit tests for circuit breaker and rate limiter Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix cache deduplication, circuit breaker error handling, and test isolation (#294) * Initial plan * Fix PR review feedback: cache normalization, TTL behavior, circuit breaker error handling, CSS import, test isolation Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Address code review feedback: fix return type consistency and improve documentation Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Address PR review feedback: add tests, fix error handling, narrow 4xx scope, evict failed promises Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Address code review feedback: refine cache eviction and improve documentation Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Address PR #292 review feedback: hydration, syntax, error handling, docs (#295) * Initial plan * Address PR review comments: hydration, syntax, cleanup, docs Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Remove redundant clearTimeout call Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix ldrs CSS import path for Turbopack compatibility Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Update src/app/(protected)/dashboard/DashboardClient.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> Co-authored-by: Devanarayanan <fusion@devakesu.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix invalid Tailwind utilities and chart responsiveness (#296) * Initial plan * Fix invalid Tailwind utilities and hydration issues Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Refactor ResizeObserver to use consistent updateDimensions function Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Remove redundant nullish coalescing operators Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix trailing whitespace, chart height, and revert problematic hydration Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix invalid Tailwind utilities, add queue limits, handle 429, and prevent cache poisoning (#297) * Initial plan * Fix invalid Tailwind utilities across components Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Add queue size limit and timeout to prevent unbounded growth Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Treat 429 status as circuit breaker failure to prevent retry storms Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Update documentation to reflect queue timeout and size limits Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Improve queue error handling with unique IDs and typed errors Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix cache poisoning and preserve 429 rate-limit messages Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Add tests for queue errors and 429 handling Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Improve type safety in logger usage for 429/5xx handling Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix Tailwind syntax, test timeouts, redundant SSR fetch, and cache control (#299) * Initial plan * Address review feedback: fix Tailwind syntax, test timeouts, SSR fetch, cache headers, and docs Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Update JSDoc for fetchDashboardData to reflect removal of profile Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix cache poisoning, health check flapping, and initialData handling (#300) * Initial plan * Fix review comments: cache eviction, health check, docs, and initialData handling Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix circuit breaker bypass, cache collision, and type safety issues (#301) * Initial plan * Fix security, type safety, and circuit breaker issues from code review - Increased cache key hash from 16 to 64 hex chars (full SHA-256) to prevent cross-user collision - Moved NEXT_PUBLIC_BACKEND_URL validation outside circuit breaker (now NonBreakerError) - Made UpstreamResponseTooLargeError extend NonBreakerError to prevent tripping circuit breaker - Fixed TypeScript type mismatches in useAttendanceReport and useFetchCourses hooks - Added null type support to query return types and components - Removed unused isHealthy variable in health check endpoint - Updated comments to reflect circuit breaker behavior Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix initialData hydration and cache TTL issues from PR #292 review (#302) * Initial plan * Fix initialData handling, cache TTL, and chart min-height Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix initialCoursesData null handling, clarify cache TTL docs, add test coverage Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix test setup to match retry configuration Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix documentation/implementation misalignment and incorrect hook type signatures (#303) * Initial plan * Align documentation with actual implementation and fix hook type signatures - Update EZYGO_RATE_LIMITING.md to reflect 60s cache TTL (was 15s) - Update EZYGO_RATE_LIMITING.md circuit breaker description (60s timeout, 2 test requests) - Update EZYGO_VERIFICATION.md cache TTL documentation to match actual 60s - Remove unnecessary `| null` from useFetchCourses return type - Remove unnecessary `| null` from useAttendanceReport return type - Fix test mocks to use proper AttendanceReport type structure Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Address PR review feedback: remove "configurable" claim and fix test name - Remove "(default, configurable)" from cache TTL docs since it's hard-coded - Rename test from "normalize null initialData" to "fetch data when initialData is undefined" to match actual behavior Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix cache TTL documentation mismatch and body key collision (#304) * Initial plan * Fix TTL documentation inconsistencies and cache key generation - Updated all documentation to reflect 60s TTL instead of 15s - Fixed cache key generation to properly distinguish undefined from {} body values - Changed body check from truthy to explicit undefined check for consistency Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Use more unique sentinel value for cache key generation Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Optimize JSON.stringify, add cache key tests, fix doc inconsistencies - Compute JSON.stringify(body) once and reuse for cache key and fetch body - Add unit tests for cache key deduplication: undefined vs {} vs null - Fix EZYGO_VERIFICATION.md line 258: 15s -> 60s TTL - Clarify EDGE_CASES_TESTS.md: cache stores both in-flight and resolved responses Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix review feedback: Add SECURITY.md, align TTL docs, hash cache keys (#305) * Initial plan * Address review comments: Add SECURITY.md, fix TTL docs, hash body in cache key Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Improve cache key comment clarity and fix HttpOnly casing in SECURITY.md Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Forward rate-limit headers from upstream 429 responses (#306) * Initial plan * Forward rate-limit headers from upstream 429 responses Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix FIFO queue starvation in EzyGo batch fetcher rate limiter (#312) * Initial plan * Fix FIFO queue fairness in waitForSlot function Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Add FIFO fairness regression test for queue management Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix circuit breaker 4xx handling and clarify per-user deduplication scope (#313) * Initial plan * Fix circuit breaker 4xx handling and clarify per-user deduplication in docs Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix documentation inconsistencies, add status code tests, clarify comments Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Improve test structure to use consistent error handling pattern Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix documentation mismatches and add Suspense boundary for lazy components (#314) * Initial plan * Fix PR review feedback: clarify per-user deduplication and add Suspense boundary Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix circuit breaker threshold and cache key documentation details Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Restrict health endpoint telemetry in production to prevent information disclosure (#315) * Initial plan * Restrict detailed telemetry in production health endpoint Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Improve NODE_ENV check to default to secure behavior Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Update documentation for production security restrictions Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Add unit tests and improve code clarity per review feedback Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix rate limiter state corruption and add aria-hidden fallback (#316) * Initial plan * Fix timeout cleanup and inert fallback for accessibility Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix generation guard and remove redundant clearTimeout Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Initialize slotGeneration to -1 and improve comment precision Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix AbortError handling, remove ineffective Recharts lazy loading, and add test coverage (#317) * Initial plan * Fix abort error handling and remove ineffective Recharts lazy loading Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Add test coverage for timeout/abort path in backend proxy Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix JSDoc, ResizeObserver performance, dev:https validation, and README accuracy (#318) * Initial plan * Fix JSDoc, ResizeObserver optimization, dev:https validation, and README accuracy Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix test mock memory leaks, GET request body handling, and Content-Type header semantics (#319) * Initial plan * Fix test mocks to respect AbortSignal and GET body parameter handling Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Conditionally set Content-Type header only for POST requests with body Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix header mutation by setting Content-Type before creating fetchOptions Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix backend route timeout test determinism and circuit breaker test isolation (#320) * Initial plan * Changes before error encountered Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix test isolation by resetting circuit breaker state before each Rate Limiting test Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Improve timeout test mock robustness with signal validation and early abort handling Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix AbortSignal.timeout() jsdom compatibility and mock isolation in circuit breaker tests (#321) * Initial plan * Fix AbortSignal.timeout() compatibility and circuit breaker mock isolation Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix resource leaks in stream reading and timeout signal handling (#322) * Initial plan * Fix resource leaks: cancel reader on size limit, clear timeout on fetch completion, improve AbortSignal.timeout detection Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Address review feedback: fix docstring, await reader.cancel(), add timer cleanup tests Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix comment: remove mention of logging that isn't implemented Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix invalid Tailwind CSS class names introduced in v1.5.0 (#323) * Initial plan * Fix invalid Tailwind CSS class names Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Remove trailing whitespace from AcceptTermsForm.tsx Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix attendance hook tests for initialData support (#324) * Initial plan * Fix attendance hook unit tests for initialData support - Add beforeEach/afterEach hooks to prevent test state pollution - Disable background refetch settings in test QueryClient - Increase timeout for error state test to 3000ms - All 5 attendance tests now passing - No regressions in other tests (399 tests passing) Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Remove redundant afterEach hook The beforeEach already clears mocks, so afterEach is unnecessary Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.