-
Notifications
You must be signed in to change notification settings - Fork 270
DOC-5880 DOC-5881 DOC-5882 DOC-5883 DOC-5885 DOC-5886 Error checking pages #2349
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
Changes from all commits
33f6d61
89cfafd
38119d0
ac4a837
4d32b3c
05bf935
ecae0bb
0216a51
7352dc5
8ebfc68
293a1d1
d407ed9
fd9e48a
afdd9b0
60162f0
7d1d8eb
5a67374
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| --- | ||
| title: Error handling | ||
| description: Learn how to handle errors when using NRedisStack. | ||
| linkTitle: Error handling | ||
| weight: 60 | ||
| --- | ||
|
|
||
| NRedisStack uses **exceptions** to signal errors. Code examples in the documentation often omit error handling for brevity, but it is essential in production code. This page explains how NRedisStack's error handling works and how to apply common error handling patterns. | ||
|
|
||
| For an overview of error types and handling strategies, see [Error handling]({{< relref "/develop/clients/error-handling" >}}). | ||
| See also [Production usage]({{< relref "/develop/clients/dotnet/produsage" >}}) | ||
| for more information on connection management, timeouts, and other aspects of | ||
| app reliability. | ||
|
|
||
| ## Exception types | ||
|
|
||
| NRedisStack throws exceptions to signal errors. Common exception types include: | ||
|
|
||
| | Exception | When it occurs | Recoverable | Recommended action | | ||
| |---|---|---|---| | ||
| | `RedisConnectionException` | Connection refused or lost | ✅ | Retry with backoff or fall back | | ||
| | `RedisTimeoutException` | Operation exceeded timeout | ✅ | Retry with backoff | | ||
| | `RedisCommandException` | Invalid command or arguments | ❌ | Fix the command or arguments | | ||
| | `RedisServerException` | Invalid operation on server | ❌ | Fix the operation or data | | ||
|
|
||
| See [Categories of errors]({{< relref "/develop/clients/error-handling#categories-of-errors" >}}) | ||
| for a more detailed discussion of these errors and their causes. | ||
|
|
||
| ## Applying error handling patterns | ||
|
|
||
| The [Error handling]({{< relref "/develop/clients/error-handling" >}}) overview | ||
| describes four main patterns. The sections below show how to implement them in | ||
| NRedisStack: | ||
|
|
||
| ### Pattern 1: Fail fast | ||
|
|
||
| Catch specific exceptions that represent unrecoverable errors and re-throw them (see | ||
| [Pattern 1: Fail fast]({{< relref "/develop/clients/error-handling#pattern-1-fail-fast" >}}) | ||
| for a full description): | ||
|
|
||
| ```csharp | ||
| using NRedisStack; | ||
| using StackExchange.Redis; | ||
|
|
||
| var muxer = ConnectionMultiplexer.Connect("localhost:6379"); | ||
| var db = muxer.GetDatabase(); | ||
|
|
||
| try { | ||
| var result = db.StringGet("key"); | ||
| } catch (RedisCommandException) { | ||
| // This indicates a bug in the code, such as using | ||
| // StringGet on a list key. | ||
| throw; | ||
| } | ||
| ``` | ||
|
|
||
| ### Pattern 2: Graceful degradation | ||
|
|
||
| Catch specific errors and fall back to an alternative, where possible (see | ||
| [Pattern 2: Graceful degradation]({{< relref "/develop/clients/error-handling#pattern-2-graceful-degradation" >}}) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one too. Maybe the diagrams are throwing something off? |
||
| for a full description): | ||
|
|
||
| ```csharp | ||
| try { | ||
| var cachedValue = db.StringGet(key); | ||
| return cachedValue.ToString(); | ||
| } catch (RedisConnectionException) { | ||
| logger.LogWarning("Cache unavailable, using database"); | ||
|
|
||
| // Fallback to database | ||
| return database.Get(key); | ||
| } | ||
| ``` | ||
|
|
||
| ### Pattern 3: Retry with backoff | ||
|
|
||
| Retry on temporary errors such as timeouts (see | ||
| [Pattern 3: Retry with backoff]({{< relref "/develop/clients/error-handling#pattern-3-retry-with-backoff" >}}) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same. |
||
| for a full description): | ||
|
|
||
| ```csharp | ||
| const int maxRetries = 3; | ||
| int retryDelay = 100; | ||
|
|
||
| for (int attempt = 0; attempt < maxRetries; attempt++) { | ||
| try { | ||
| return db.StringGet(key).ToString(); | ||
| } catch (RedisTimeoutException) { | ||
| if (attempt < maxRetries - 1) { | ||
| Thread.Sleep(retryDelay); | ||
| retryDelay *= 2; // Exponential backoff | ||
| } else { | ||
| throw; | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| See also [Timeouts]({{< relref "/develop/clients/dotnet/produsage#timeouts" >}}) | ||
| for more information on configuring timeouts in NRedisStack. | ||
|
|
||
| ### Pattern 4: Log and continue | ||
|
|
||
| Log non-critical errors and continue (see | ||
| [Pattern 4: Log and continue]({{< relref "/develop/clients/error-handling#pattern-4-log-and-continue" >}}) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't make this problem happen in staging or locally, so I'm not sure if I've accidentally fixed it or if I just haven't had the right circumstances to see it. I'll keep an eye open for this, though - it would be great to keep using the Mermaid diagrams, so if they introduce any faults then I'll definitely try to fix them. |
||
| for a full description): | ||
|
|
||
| ```csharp | ||
| try { | ||
| db.StringSet(key, value, TimeSpan.FromSeconds(3600)); | ||
| } catch (RedisConnectionException) { | ||
| logger.LogWarning($"Failed to cache {key}, continuing without cache"); | ||
| // Application continues normally | ||
| } | ||
| ``` | ||
|
|
||
| ## Async error handling | ||
|
|
||
| Error handling works the usual way with `async`/`await`, as shown in the | ||
| example below: | ||
|
|
||
| ```csharp | ||
| using NRedisStack; | ||
| using StackExchange.Redis; | ||
|
|
||
| var muxer = ConnectionMultiplexer.Connect("localhost:6379"); | ||
| var db = muxer.GetDatabase(); | ||
|
|
||
| async Task<string> GetWithFallbackAsync(string key) { | ||
| try { | ||
| var result = await db.StringGetAsync(key); | ||
| if (result.HasValue) { | ||
| return result.ToString(); | ||
| } | ||
| } catch (RedisConnectionException) { | ||
| logger.LogWarning("Cache unavailable"); | ||
| return await database.GetAsync(key); | ||
| } | ||
|
|
||
| return await database.GetAsync(key); | ||
| } | ||
| ``` | ||
|
|
||
| ## See also | ||
|
|
||
| - [Error handling]({{< relref "/develop/clients/error-handling" >}}) | ||
| - [Production usage]({{< relref "/develop/clients/dotnet/produsage" >}}) | ||
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.
I'm not sure why, but this anchor goes to a location well above the actually section.