Skip to content

Feature 026: UI Resilience & Error Boundaries#30

Merged
ovation22 merged 6 commits intomainfrom
feature/026-ui-resilience-error-boundaries
Jan 29, 2026
Merged

Feature 026: UI Resilience & Error Boundaries#30
ovation22 merged 6 commits intomainfrom
feature/026-ui-resilience-error-boundaries

Conversation

@ovation22
Copy link
Copy Markdown
Owner

@ovation22 ovation22 commented Jan 29, 2026

Summary

Implements comprehensive error handling and resilience patterns across the TripleDerby Web application (Phases 1-6 of Feature 026).

What's Included

Phase 1: HTTP Resilience Infrastructure

  • Added Polly-based resilience policies with retry (3 attempts, exponential backoff) and circuit breaker
  • Applied to all 9 API clients (Breeding, Horse, Race, Stats, Training, etc.)
  • Comprehensive integration tests validating retry and circuit breaker behavior

Phase 2: Reusable Error UI Components

  • Created ErrorWidget component with FluentUI MessageBar for consistent error display
  • Supports retry callbacks and optional technical details
  • Added demo page at /error-widget-demo (Development mode only)

Phase 3: Widget Extraction

  • HorseFlipCard: Extracted from Breeding page, eliminated ~50 lines of duplication
  • RaceDetailsHeader: Extracted race metadata display from RaceRuns page

Phase 5: Dashboard Widgets Error Handling

  • Added error handling to HorseGenderStats, HorseColorStats, HorseLegTypeStats
  • Wrapped all dashboard widgets in ErrorBoundary for isolation
  • Components fail gracefully without breaking the page

Phase 6: Data Grid Pages Error Handling

  • Added comprehensive error handling to Horses, Races, and RaceRuns grids
  • Try/catch blocks with structured logging
  • ErrorWidget display with retry functionality
  • Graceful degradation on API failures

Multi-Layered Error Handling

  1. Layer 1 (Polly): Automatic retries with exponential backoff, circuit breaker
  2. Layer 2 (Component): Try/catch with structured logging
  3. Layer 3 (UI): ErrorWidget for user-friendly messages
  4. Layer 4 (Boundary): ErrorBoundary isolates unexpected failures

Files Changed

  • Created: 7 new files (PollyPoliciesTests, HttpResilienceExtensions, ErrorWidget, HorseFlipCard, RaceDetailsHeader, ErrorWidgetDemo)
  • Modified: 9 files (Program.cs, 3 grid pages, 3 stat widgets, Home, Breeding)
  • Documentation: Feature spec and implementation plan in /docs

Future Work

Phase 7 (deferred): Enhance error handling in complex polling workflows (Breeding, TrainHorse pages)

Test Plan

  • Run application and verify all pages load without errors
  • Test error scenarios by stopping backend services
  • Verify ErrorWidget displays with retry button
  • Confirm retry functionality works correctly
  • Visit /error-widget-demo to see ErrorWidget examples
  • Verify dashboard widgets fail gracefully in isolation
  • Test grid pages handle API failures without crashing
  • Confirm Polly resilience policies retry on transient failures
  • Verify circuit breaker opens after sustained failures

Related Documentation

  • Feature Spec: docs/features/026-ui-resilience-error-boundaries.md
  • Implementation Plan: docs/implementation/026-ui-resilience-error-boundaries-implementation-plan.md

ovation22 and others added 5 commits January 28, 2026 15:06
Implemented comprehensive resilience for all API clients using Microsoft.Extensions.Http.Resilience:

- Retry Policy: 3 attempts with exponential backoff (1s, 2s, 4s)
  - Retries on: 5xx errors, timeouts, network errors
  - No retry on: 4xx client errors (fail fast)
- Circuit Breaker: Opens after 5 consecutive failures, breaks for 30s
- Timeouts: 30s per attempt, 2min total including retries
- Built-in logging for all resilience events

Applied to all 9 API clients (Breeding, Horse, Stats, User, Race, RaceRun, Track, Trainings, Feedings).

Tests:
- 6 integration tests covering retry, circuit breaker, and backoff behavior
- All tests passing

Files created:
- TripleDerby.Web/Resilience/HttpResilienceExtensions.cs
- TripleDerby.Tests.Unit/Web/Resilience/PollyPoliciesTests.cs
- docs/features/026-ui-resilience-error-boundaries.md
- docs/implementation/026-ui-resilience-error-boundaries-implementation-plan.md

Files modified:
- TripleDerby.Web/Program.cs - Applied resilience to HttpClient registrations
- TripleDerby.Web/TripleDerby.Web.csproj - Added resilience package
- TripleDerby.Tests.Unit/TripleDerby.Tests.Unit.csproj - Added resilience package

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Created ErrorWidget component for consistent error display across the application:

Features:
- Uses FluentUI Blazor components (FluentMessageBar, FluentButton)
- Conditional retry button (only shows when OnRetry callback provided)
- Optional technical details section (collapsible, for development)
- Full accessibility with ARIA labels (role="alert", aria-live="assertive")
- Scoped CSS with dark mode support
- Responsive design with FluentUI design tokens

Demo Page:
- Added ErrorWidgetDemo.razor with 5 scenarios
- Simulated API failures with realistic error codes
- Shows all ErrorWidget features and usage patterns
- Navigation link (Development mode only)

Files created:
- TripleDerby.Web/Components/Shared/ErrorWidget.razor
- TripleDerby.Web/Components/Shared/ErrorWidget.razor.css
- TripleDerby.Web/Components/Pages/ErrorWidgetDemo.razor

Files modified:
- TripleDerby.Web/Components/Layout/NavMenu.razor - Added demo link

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Created two new reusable widgets to eliminate code duplication:

HorseFlipCard widget:
- Extracted from Breeding.razor (eliminated ~50 lines of duplication)
- Displays horse info with flip card animation
- Front: emoji, name, earnings
- Back: race stats (starts, wins, place, show, sire, dam)
- Configurable height, width, minimal style

RaceDetailsHeader widget:
- Extracted from RaceRuns.razor
- Displays race metadata (name, track, distance, surface, class, purse)
- Responsive layout with flexbox
- Scoped CSS styling

Updated pages:
- Breeding.razor: Now uses HorseFlipCard component (2 instances)
- RaceRuns.razor: Now uses RaceDetailsHeader component

All components follow FluentUI Blazor patterns and build successfully.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added comprehensive error handling to all dashboard statistics widgets:

HorseGenderStats, HorseColorStats, HorseLegTypeStats:
- Added ILogger injection for structured error logging
- Added error state with ErrorWidget display
- Updated LoadAsync with null/empty validation
- Catches and logs exceptions with context
- Added HandleRetryAsync for recovery without page reload
- User-friendly error messages

Home.razor ErrorBoundary isolation:
- Wrapped each stats widget in ErrorBoundary
- Widgets fail independently without affecting others
- Custom error messages per widget type
- Page remains functional when widgets fail

Error handling features:
- API response validation (null/empty check)
- Exception catching with logging
- Retry functionality on all widgets
- Loading state clears errors on retry
- Warning logs for null/empty data
- Error logs for exceptions

Observable behavior:
- Failed widgets show ErrorWidget with retry button
- Other widgets continue functioning normally
- Unhandled exceptions caught by ErrorBoundary
- Error isolation prevents cascading failures

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added comprehensive error handling to all data grid pages:

Horses.razor, Races.razor, RaceRuns.razor:
- Added ILogger injection for structured error logging
- Added errorMessage and hasError state fields
- Updated RefreshItemsAsync with try/catch error handling
- Validates API response is not null
- Catches and logs exceptions with context
- Sets user-friendly error messages
- Clears grid data and pagination on error
- Added HandleRetryAsync for retry functionality
- ErrorWidget displays above grid with retry button

Error handling features:
- API response null validation
- Exception catching with structured logging (RaceId context for RaceRuns)
- Retry functionality via dataGrid.RefreshDataAsync()
- Empty grid state on error (prevents stale data display)
- Loading state management (clears error on retry)

Observable behavior:
- Failed grid loads show ErrorWidget with retry button
- Grid pagination/sorting remain functional after error
- Retry button successfully reloads grid data
- Error messages are user-friendly and actionable

Build: Succeeded with 3 warnings (unused hasError field - acceptable for future extensibility)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Test Results

723 tests  +6   723 ✅ +6   8s ⏱️ +3s
  1 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 4037a66. ± Comparison against base commit a52cd63.

Added a mandatory pre-flight checklist at the top of CLAUDE.md to ensure git operations follow project standards. The checklist enforces: no AI attribution in commits, no automated signatures in PRs, and requiring explicit approval before any git operations.

Also expanded the PR guidelines section to explicitly forbid automated tool signatures in pull request descriptions.
@ovation22 ovation22 merged commit 7048779 into main Jan 29, 2026
1 check passed
@ovation22 ovation22 deleted the feature/026-ui-resilience-error-boundaries branch January 29, 2026 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant