Technology

C# MAUI Chaos Engineering

c maui chaos engineering
C# MAUI Chaos Engineering | SiamCafe Blog
2025-08-23· อ. บอม — SiamCafe.net· 8,944 คำ

MAUI Chaos Engineering

C# MAUI Chaos Engineering Fault Injection Network Simulation UI Resilience Error Handling Polly Retry Circuit Breaker Production

Chaos ScenarioSimulationExpected BehaviorTest On
Network TimeoutDelay response 30+ secTimeout message, retry buttonAll platforms
Server Error (500)Return HTTP 500Error message, auto retryAll platforms
Auth Expired (401)Return HTTP 401Redirect to login, refresh tokenAll platforms
OfflineNo internetOffline banner, cached dataAndroid, iOS
Slow Network3-5 sec delayLoading indicator, no freezeAll platforms
Memory PressureLarge data loadNo crash, graceful degradationAndroid, iOS

Fault Injection Setup

# === C# MAUI Chaos Engineering Setup ===

# // IChaosService.cs — Interface for chaos injection
# public interface IApiService
# {
#     Task<List<Item>> GetItemsAsync();
#     Task<Item> GetItemAsync(int id);
#     Task<bool> SaveItemAsync(Item item);
# }
#
# // ChaosApiService.cs — Chaos implementation
# public class ChaosApiService : IApiService
# {
#     private readonly IApiService _realService;
#     private readonly Random _random = new();
#     private readonly double _failureRate;
#
#     public ChaosApiService(IApiService realService, double failureRate = 0.3)
#     {
#         _realService = realService;
#         _failureRate = failureRate;
#     }
#
#     public async Task<List<Item>> GetItemsAsync()
#     {
#         await SimulateChaos();
#         return await _realService.GetItemsAsync();
#     }
#
#     private async Task SimulateChaos()
#     {
#         if (_random.NextDouble() < _failureRate)
#         {
#             var scenario = _random.Next(4);
#             switch (scenario)
#             {
#                 case 0: throw new HttpRequestException("Network error");
#                 case 1: throw new TimeoutException("Request timeout");
#                 case 2: await Task.Delay(5000); break; // Slow response
#                 case 3: throw new UnauthorizedAccessException("Token expired");
#             }
#         }
#     }
# }
#
# // MauiProgram.cs — DI Registration
# #if DEBUG
# builder.Services.AddSingleton<IApiService>(sp =>
#     new ChaosApiService(new RealApiService(sp.GetRequiredService<HttpClient>()), 0.3));
# #else
# builder.Services.AddSingleton<IApiService, RealApiService>();
# #endif

from dataclasses import dataclass

@dataclass
class ChaosScenario:
    scenario: str
    exception: str
    frequency: str
    user_impact: str
    handling: str

scenarios = [
    ChaosScenario("Network Error",
        "HttpRequestException", "30% of requests",
        "Cannot load data, shows error",
        "Retry 3x with backoff, show cached data"),
    ChaosScenario("Timeout",
        "TimeoutException / TaskCanceledException", "20% of requests",
        "Long wait, then error",
        "30s timeout, cancel task, show retry button"),
    ChaosScenario("Auth Expired",
        "UnauthorizedAccessException / HTTP 401", "10% of requests",
        "Redirected to login",
        "Refresh token automatically, retry once"),
    ChaosScenario("Server Error",
        "HttpRequestException (500)", "15% of requests",
        "Feature unavailable",
        "Circuit breaker, show maintenance message"),
    ChaosScenario("Slow Response",
        "Task.Delay(3000-5000)", "25% of requests",
        "Loading feels slow",
        "Show skeleton UI, progress indicator"),
]

print("=== Chaos Scenarios ===")
for s in scenarios:
    print(f"  [{s.scenario}] Exception: {s.exception}")
    print(f"    Frequency: {s.frequency} | Impact: {s.user_impact}")
    print(f"    Handling: {s.handling}")

Polly Resilience

# === Polly Configuration ===

# // Polly setup in MauiProgram.cs
# builder.Services.AddHttpClient("api", client =>
# {
#     client.BaseAddress = new Uri("https://api.example.com");
#     client.Timeout = TimeSpan.FromSeconds(30);
# })
# .AddPolicyHandler(GetRetryPolicy())
# .AddPolicyHandler(GetCircuitBreakerPolicy())
# .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(10));
#
# static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
# {
#     return HttpPolicyExtensions
#         .HandleTransientHttpError()
#         .Or<TimeoutRejectedException>()
#         .WaitAndRetryAsync(3, retryAttempt =>
#             TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
#             onRetry: (outcome, timespan, retryAttempt, context) =>
#             {
#                 Debug.WriteLine($"Retry {retryAttempt} after {timespan.TotalSeconds}s");
#             });
# }
#
# static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
# {
#     return HttpPolicyExtensions
#         .HandleTransientHttpError()
#         .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30),
#             onBreak: (result, duration) =>
#                 Debug.WriteLine($"Circuit OPEN for {duration.TotalSeconds}s"),
#             onReset: () => Debug.WriteLine("Circuit CLOSED"));
# }

@dataclass
class PollyPolicy:
    policy: str
    config: str
    when: str
    behavior: str

policies = [
    PollyPolicy("Retry",
        "3 retries, exponential backoff (2s, 4s, 8s)",
        "Transient HTTP errors (5xx, timeout)",
        "Auto retry, user sees loading longer"),
    PollyPolicy("Circuit Breaker",
        "Open after 5 failures, 30s cooldown",
        "Consecutive failures to same endpoint",
        "Fast fail, no wasted requests, show fallback"),
    PollyPolicy("Timeout",
        "10s per request, 30s overall",
        "Slow API responses",
        "Cancel request, show timeout message"),
    PollyPolicy("Fallback",
        "Return cached data on failure",
        "After all retries exhausted",
        "Show stale data with 'offline' indicator"),
    PollyPolicy("Bulkhead",
        "Max 10 concurrent requests",
        "Prevent resource exhaustion",
        "Queue excess requests, prevent app freeze"),
]

print("=== Polly Policies ===")
for p in policies:
    print(f"  [{p.policy}] Config: {p.config}")
    print(f"    When: {p.when}")
    print(f"    Behavior: {p.behavior}")

UI Resilience Testing

# === UI Testing Checklist ===

@dataclass
class UITest:
    test: str
    scenario: str
    expected: str
    platform: str
    automated: bool

ui_tests = [
    UITest("Loading State", "API call in progress",
        "Skeleton UI or spinner visible, no blank screen",
        "All", True),
    UITest("Error State", "API returns 500",
        "Error message with retry button, no crash",
        "All", True),
    UITest("Offline Banner", "No internet connection",
        "Banner shows 'Offline', cached data displayed",
        "Android, iOS", True),
    UITest("Timeout Recovery", "API timeout then succeeds",
        "Shows timeout, auto retry succeeds, UI updates",
        "All", True),
    UITest("Auth Redirect", "Token expired (401)",
        "Redirect to login, after login return to same page",
        "All", True),
    UITest("Pull to Refresh", "Stale data after error",
        "Pull down refreshes data, loading indicator shows",
        "Android, iOS", True),
    UITest("Back Navigation", "Error on current page",
        "Back button works, no stuck state",
        "All", True),
    UITest("Memory Pressure", "Load 10000 items in list",
        "CollectionView virtualizes, no OOM crash",
        "Android, iOS", False),
]

print("=== UI Resilience Tests ===")
for t in ui_tests:
    auto = "Automated" if t.automated else "Manual"
    print(f"  [{t.test}] {auto} | Platform: {t.platform}")
    print(f"    Scenario: {t.scenario}")
    print(f"    Expected: {t.expected}")

เคล็ดลับ

MAUI Chaos Engineering คืออะไร

ทดสอบความทนทาน .NET MAUI Network หลุด API Timeout Error Memory Leak Android iOS Windows UI ไม่ค้าง Crash Error Message Retry Offline

Fault Injection ทำอย่างไร

Interface IApiService DI Chaos Service Exception Timeout Slow Response สุ่ม Failure Polly Retry Circuit Breaker Feature Flag Scenario

Network Simulation ทำอย่างไร

HttpMessageHandler Timeout 500 Error 401 Unauthorized Slow Network Offline Charles Proxy mitmproxy Device จริง WiFi ปิด

Best Practices มีอะไร

Polly Retry 3 Exponential Backoff Circuit Breaker Timeout 30s Offline Cache Loading Error Message Global Exception Handler ทุก Platform

สรุป

C# MAUI Chaos Engineering Fault Injection Network Simulation Polly Retry Circuit Breaker UI Resilience Offline Cache Error Handling Production

📖 บทความที่เกี่ยวข้อง

AWS Glue ETL Chaos Engineeringอ่านบทความ → Ansible AWX Tower Chaos Engineeringอ่านบทความ → Datadog APM Chaos Engineeringอ่านบทความ → Immutable OS Fedora CoreOS Chaos Engineeringอ่านบทความ → Python Rich Chaos Engineeringอ่านบทความ →

📚 ดูบทความทั้งหมด →