Round #222
07 May 2026, 15:05· csharp· meta/llama-3.3-70b-instruct· r12-real-contracts
- Complexity
- band 1
- ZP / UO / OBS
- 3 / 11 / 0
- Journey weight
- 1041
- Lightshift ΔL
- —
Prompt
Write a circuit breaker for cache reads that falls back to the database
Zero-point index (what the engine surfaced)
ZPI-ZPI-0015 | 2026-05-07T15:05:07Z
Write a circuit breaker for cache reads that falls back to the database
ZERO POINT — 3 entries (structural invariants)
● hsl(145.55, 100%, 21%) IMemoryCache [contract]
● hsl(296.42, 100%, 24%) ResiliencePipeline [contract]
● hsl(211.57, 100%, 24%) ResiliencePipelineBuilder [contract]
UNOBSERVED — 11 entries (implied truths)
○ hsl(348.72, 100%, 22%) IDisposable [feature]
○ hsl(27.69, 100%, 50%) async [feature]
○ hsl(9.23, 100%, 32%) interface [feature]
○ hsl(180.92, 100%, 14%) Database health check [function]
○ hsl(144.00, 100%, 18%) Connection resilience [function]
○ hsl(83.08, 100%, 26%) ILogger of T injection [function]
○ hsl(199.38, 100%, 16%) Redis distributed cache [function]
○ hsl(188.31, 100%, 16%) Distributed cache (IDistributedCache) [function]
○ hsl(31.38, 100%, 40%) Scoped registration [function]
○ hsl(44.31, 100%, 25%) IOptions of T binding [function]
○ hsl(49.23, 100%, 30%) try [feature]
OBSERVED — 0 entries (explicit in request)
COMPLEXITY │ 14 entries │ spread: 339° │ band: MEDIUM
Baseline response (no ZPI)
**Circuit Breaker for Cache Reads with Database Fallback**
===========================================================
Below is an example implementation of a circuit breaker in C# that falls back to the database when cache reads fail.
### Circuit Breaker Interface
```csharp
public interface ICircuitBreaker
{
/// <summary>
/// Execute a cache read operation with a fallback to the database.
/// </summary>
/// <typeparam name="T">Type of the result.</typeparam>
/// <param name="cacheKey">Cache key.</param>
/// <param name="cacheRead">Cache read operation.</param>
/// <param name="databaseRead">Database read operation.</param>
/// <returns>Result of the operation.</returns>
T Execute<T>(string cacheKey, Func<T> cacheRead, Func<T> databaseRead);
}
```
### Circuit Breaker Implementation
```csharp
public class CircuitBreaker : ICircuitBreaker
{
private readonly TimeSpan _timeout;
private readonly int _maxFailures;
private readonly ConcurrentDictionary<string, CircuitState> _states;
public CircuitBreaker(TimeSpan timeout, int maxFailures)
{
_timeout = timeout;
_maxFailures = maxFailures;
_states = new ConcurrentDictionary<string, CircuitState>();
}
public T Execute<T>(string cacheKey, Func<T> cacheRead, Func<T> databaseRead)
{
var state = GetState(cacheKey);
if (state.IsOpen)
{
// If the circuit is open, directly fall back to the database.
return databaseRead();
}
try
{
// Attempt to read from the cache.
var result = cacheRead();
// If the cache read is successful, reset the state.
ResetState(cacheKey);
return result;
}
catch (Exception ex)
{
// If the cache read fails, increment the failure count and check if the circuit should be opened.
state.Failures++;
if (state.Failures >= _maxFailures)
{
OpenCircuit(cacheKey);
}
// Fall back to the database.
return databaseRead();
}
}
private CircuitState GetState(string cacheKey)
{
return _states.GetOrAdd(cacheKey, k => new CircuitState());
}
private void ResetState(string cacheKey)
{
var state = GetState(cacheKey);
state.Failures = 0;
state.LastFailure = DateTime.MinValue;
}
private void OpenCircuit(string cacheKey)
{
var state = GetState(cacheKey);
state.IsOpen = true;
state.LastFailure = DateTime.Now;
Task.Delay(_timeout).ContinueWith(t => CloseCircuit(cacheKey));
}
private void CloseCircuit(string cacheKey)
{
var state = GetState(cacheKey);
state.IsOpen = false;
state.Failures = 0;
}
private class CircuitState
{
public bool IsOpen { get; set; }
public int Failures { get; set; }
public DateTime LastFailure { get; set; }
}
}
```
### Example Usage
```csharp
public class CacheService
{
private readonly ICircuitBreaker _circuitBreaker;
public CacheService(ICircuitBreaker circuitBreaker)
{
_circuitBreaker = circuitBreaker;
}
public string GetData(string cacheKey)
{
return _circuitBreaker.Execute(cacheKey, () =>
{
// Cache read operation.
return Cache.Get(cacheKey);
}, () =>
{
// Database read operation.
return Database.Get(cacheKey);
});
}
}
public class Program
{
public static void Main()
{
var circuitBreaker = new CircuitBreaker(TimeSpan.FromSeconds(30), 3);
var cacheService = new CacheService(circuitBreaker);
var data = cacheService.GetData("exampleKey");
Console.WriteLine(data);
}
}
```
In this example, the `CircuitBreaker` class implements the `ICircuitBreaker` interface and provides a way to execute a cache read operation with a fallback to the database. The `CircuitState` class represents the state of the circuit breaker for a given cache key.
The `Execute` method attempts to read from the cache and falls back to the database if the cache read fails. If the circuit is open, it directly falls back to the database. The `GetState`, `ResetState`, `OpenCircuit`, and `CloseCircuit` methods manage the state of the circuit breaker.
In the example usage, the `CacheService` class uses the `CircuitBreaker` to execute a cache read operation with a fallback to the database. The `GetData` method calls the `Execute` method on the `CircuitBreaker` instance, passing in the cache
Enhanced response (with ZPI)
```csharp
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Polly;
using System;
using System.Threading.Tasks;
public class CacheReadCircuitBreaker
{
private readonly IMemoryCache _cache;
private readonly IDistributedCache _distributedCache;
private readonly ILogger<CacheReadCircuitBreaker> _logger;
private readonly Policy<CacheResult> _policy;
public CacheReadCircuitBreaker(IMemoryCache cache, IDistributedCache distributedCache, ILogger<CacheReadCircuitBreaker> logger)
{
_cache = cache;
_distributedCache = distributedCache;
_logger = logger;
_policy = Policy.Handle<CacheResult>(r => r.IsFailure)
.CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: 3,
durationOfBreak: TimeSpan.FromMinutes(1),
onBreak: (ex, ts) => _logger.LogError($"Cache read circuit breaker broken for {ts.TotalMinutes} minutes"),
onReset: () => _logger.LogInformation("Cache read circuit breaker reset")
);
}
public async Task<CacheResult> GetAsync(string key, Func<Task<object>> databaseRead)
{
return await _policy.ExecuteAsync(async () =>
{
if (_cache.TryGetValue(key, out object cachedValue))
{
return CacheResult.Success(cachedValue);
}
if (await _distributedCache.TryGetValueAsync(key) is { } distributedCachedValue)
{
return CacheResult.Success(distributedCachedValue);
}
try
{
var databaseValue = await databaseRead();
await _distributedCache.SetStringAsync(key, databaseValue.ToString());
_cache.Set(key, databaseValue);
return CacheResult.Success(databaseValue);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error reading from database");
return CacheResult.Failure(ex);
}
});
}
}
public class CacheResult
{
public bool IsFailure { get; }
public object Value { get; }
public Exception Exception { get; }
private CacheResult(object value, Exception exception = null)
{
Value = value;
Exception = exception;
IsFailure = exception != null;
}
public static CacheResult Success(object value) => new CacheResult(value);
public static CacheResult Failure(Exception exception) => new CacheResult(null, exception);
}
```
This implementation uses Polly to create a circuit breaker policy for cache reads. The policy will break the circuit if three consecutive cache reads fail, and will reset the circuit after one minute. The `GetAsync` method uses the policy to execute a cache read, and will fall back to the database if the cache read fails. The result of the cache read or database read is then stored in both the in-memory cache and the distributed cache.
The `CacheResult` class is used to represent the result of a cache read, and includes a `Success` method to create a successful result and a `Failure` method to create a failed result.
To use this circuit breaker, you would need to register the `CacheReadCircuitBreaker` class in the DI container, and then inject it into your services. You would also need to configure the Polly policy to suit your needs.
For example, you could register the `CacheReadCircuitBreaker` class like this:
```csharp
services.AddSingleton<CacheReadCircuitBreaker>();
```
And then inject it into your services like this:
```csharp
public class MyService
{
private readonly CacheReadCircuitBreaker _cacheReadCircuitBreaker;
public MyService(CacheReadCircuitBreaker cacheReadCircuitBreaker)
{
_cacheReadCircuitBreaker = cacheReadCircuitBreaker;
}
public async Task<object> GetAsync(string key)
{
return (await _cacheReadCircuitBreaker.GetAsync(key, async () => await DatabaseReadAsync())).Value;
}
private async Task<object> DatabaseReadAsync()
{
// Database read logic here
}
}
```
This would allow you to use the circuit breaker to read from the cache, and fall back to the database if the cache read fails.
Grader chain
Each grader reads the same baseline + enhanced pair and casts an independent verdict. Disagreement is the framework's own signal — not noise to be averaged away.
V1claude-haiku-4-5-20251001
WorseV4qwen2.5-coder-7b-instruct
BetterComments
Our grader said what it said. What do you say? Comment as a guest below.
No comments yet. Be the first to say what you make of this round.