Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ MyGet Pre-release feed: https://www.myget.org/gallery/stackoverflow
| ------- | ------------ | ----------------- | --------- | ----- |
| [StackExchange.Redis](https://www.nuget.org/packages/StackExchange.Redis/) | [![StackExchange.Redis](https://img.shields.io/nuget/v/StackExchange.Redis.svg)](https://www.nuget.org/packages/StackExchange.Redis/) | [![StackExchange.Redis](https://img.shields.io/nuget/vpre/StackExchange.Redis.svg)](https://www.nuget.org/packages/StackExchange.Redis/absoluteLatest) | [![StackExchange.Redis](https://img.shields.io/nuget/dt/StackExchange.Redis.svg)](https://www.nuget.org/packages/StackExchange.Redis/) | [![StackExchange.Redis MyGet](https://img.shields.io/myget/stackoverflow/vpre/StackExchange.Redis.svg)](https://www.myget.org/feed/stackoverflow/package/nuget/StackExchange.Redis) |

Release notes at: https://github.com/StackExchange/StackExchange.Redis/releases (3.0 onwards; earlier releases at https://seredis.dev/ReleaseNotes)
Release notes at: [GitHub Releases](https://github.com/StackExchange/StackExchange.Redis/releases) (3.0 onwards; [earlier releases](https://seredis.dev/ReleaseNotes))
50 changes: 50 additions & 0 deletions docs/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
layout: default
title: Page not found
sitemap: false
---

<p>There is nothing at this address.</p>

<p id="suggestion" hidden></p>

<p>If you got here from a link in an exception message or a log line, the punctuation after the URL was
probably picked up as part of it &mdash; most link detectors will happily swallow a closing bracket or a
quote.</p>

<ul>
<li><a href="/">Documentation index</a></li>
<li><a href="/Timeouts">Timeouts</a> &mdash; reading a timeout message</li>
<li><a href="/Configuration">Configuration</a></li>
<li><a href="/Basics">Basics</a></li>
<li><a href="https://github.com/StackExchange/StackExchange.Redis/releases">Release notes</a>
(3.0 onwards; <a href="/ReleaseNotes">earlier releases</a>)</li>
</ul>

<script>
// Much of this site's 404 traffic is one page's URL pasted out of an exception message or a log, with the
// trailing punctuation of the surrounding sentence attached. Strip the characters that can never end a page
// here and offer what is left. Cleaning is idempotent, so a cleaned path that also 404s offers nothing and
// there is no loop; and the suggestion is a link rather than a redirect, so a wrong guess costs nothing.
(function () {
var path = location.pathname;
try { path = decodeURIComponent(path); } catch (e) { /* malformed escape; use it raw */ }

var cleaned = path
.replace(/(?:\/r)?\/n$/, "") // a trailing "\r\n" from a log line: URL parsing reads \ as /
.replace(/[)\]}"'.,;:>]+$/, "") // punctuation belonging to the prose around the link
.replace(/\/+$/, ""); // every page here is a file, so a trailing slash never resolves

if (!cleaned || cleaned === path || cleaned.charAt(0) !== "/") return;

var link = document.createElement("a");
link.href = cleaned;
link.textContent = cleaned;

var target = document.getElementById("suggestion");
target.appendChild(document.createTextNode("Did you mean "));
target.appendChild(link);
target.appendChild(document.createTextNode("?"));
target.hidden = false;
})();
</script>
4 changes: 2 additions & 2 deletions docs/CompareAndSwap.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,6 @@ var condition = ValueCondition.CalculateDigest(largeValueBytes);

## See Also

- [Transactions](Transactions.md) - For multi-key atomic operations
- [Keys and Values](KeysValues.md) - Understanding Redis data types
- [Transactions](Transactions) - For multi-key atomic operations
- [Keys and Values](KeysValues) - Understanding Redis data types
- [Redis CAS/CAD Documentation](https://redis.io/docs/latest/commands/set/) - Redis 8.4 SET command with IFEQ/IFNE/IFDEQ/IFDNE modifiers
4 changes: 2 additions & 2 deletions docs/Profiling.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ The profiling API has undergone breaking changes between 1.* and 2.*; in 1.*; in
the `object GetContext()` API was unintuitive for consumers and expensive for the library (due to book-keeping). The API in 2.* is much
simpler and more "obvious". This is a breaking change.

[Profiling in 1.\*](Profiling_v1.md)
[Profiling in 1.\*](Profiling_v1)

[Profiling in 2.\*](Profiling_v2.md)
[Profiling in 2.\*](Profiling_v2)
2 changes: 1 addition & 1 deletion docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ Changes:
- **Soft Break**: The `PreserveAsyncOrder` behaviour of the pub/sub API has been deprecated; a *new* API has been provided for scenarios that require in-order pub/sub handling -
the `Subscribe` method has a new overload *without* a handler parameter which returns a `ChannelMessageQueue`, which provides `async` ordered access to messages)
- Internal: The network architecture has moved to use `System.IO.Pipelines`; this has allowed us to simplify and unify a lot of the network code, and in particular fix a lot of problems relating to how the library worked with TLS and/or .NETStandard
- Change: As a result of the `System.IO.Pipelines` change, the error-reporting on timeouts is now much simpler and clearer; the [timeouts documentation](Timeouts.md) has been updated
- Change: As a result of the `System.IO.Pipelines` change, the error-reporting on timeouts is now much simpler and clearer; the [timeouts documentation](Timeouts) has been updated
- Removed: The `HighPriority` (queue-jumping) flag is now deprecated
- Internal: Most buffers internally now make use of pooled memory; `RedisValue` no longer preemptively allocates buffers
- Internal: Added new custom thread-pool for handling async continuations to avoid thread-pool starvation issues
Expand Down
7 changes: 5 additions & 2 deletions src/StackExchange.Redis/ExceptionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,12 @@ internal static Exception Timeout(ConnectionMultiplexer multiplexer, string? bas
}
AddCommonDetail(data, sb, message, multiplexer, server);

sb.Append(" (Please take a look at this article for some common client-side issues that can cause timeouts: ")
// Keep the URL away from the end of the message and away from punctuation: linkifiers in log
// viewers, chat and issue trackers greedily swallow a trailing ')' or '"', and the docs site
// then sees a 404 for /Timeouts). The space after it is what makes them stop.
sb.Append(" (see ")
.Append(TimeoutHelpLink)
.Append(')');
.Append(" for some common client-side issues that can cause timeouts)");

// If we're from a backlog timeout scenario, we log a more intuitive connection exception for the timeout...because the timeout was a symptom
// and we have a more direct cause: we had no connection to send it on.
Expand Down
4 changes: 2 additions & 2 deletions tests/StackExchange.Redis.Tests/AbortOnConnectFailTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public async Task DisconnectAndReconnectThrowsConnectionExceptionSync()
Assert.SkipUnless(server.CanSimulateConnectionFailure, "Skipping because server cannot simulate connection failure");
server.SimulateConnectionFailure(SimulatedFailureType.All);

// Exception: The message timed out in the backlog attempting to send because no connection became available (400ms) - Last Connection Exception: SocketFailure (InputReaderCompleted, last-recv: 7) on 127.0.0.1:6379/Interactive, Idle/ReadAsync, last: PING, origin: SimulateConnectionFailure, outstanding: 0, last-read: 0s ago, last-write: 0s ago, keep-alive: 100s, state: ConnectedEstablished, mgr: 10 of 10 available, in: 0, in-pipe: 0, out-pipe: 0, last-heartbeat: never, last-mbeat: 0s ago, global: 0s ago, v: 2.6.120.51136, command=PING, timeout: 100, inst: 13, qu: 1, qs: 0, aw: False, bw: Inactive, last-in: 0, cur-in: 0, sync-ops: 2, async-ops: 0, serverEndpoint: 127.0.0.1:6379, conn-sec: n/a, aoc: 0, mc: 1/1/0, mgr: 10 of 10 available, clientName: CRAVERTOP7(SE.Redis-v2.6.120.51136), IOCP: (Busy=0,Free=1000,Min=16,Max=1000), WORKER: (Busy=2,Free=32765,Min=16,Max=32767), POOL: (Threads=33,QueuedItems=0,CompletedItems=6237,Timers=39), v: 2.6.120.51136 (Please take a look at this article for some common client-side issues that can cause timeouts: https://seredis.dev/Timeouts)
// Exception: The message timed out in the backlog attempting to send because no connection became available (400ms) - Last Connection Exception: SocketFailure (InputReaderCompleted, last-recv: 7) on 127.0.0.1:6379/Interactive, Idle/ReadAsync, last: PING, origin: SimulateConnectionFailure, outstanding: 0, last-read: 0s ago, last-write: 0s ago, keep-alive: 100s, state: ConnectedEstablished, mgr: 10 of 10 available, in: 0, in-pipe: 0, out-pipe: 0, last-heartbeat: never, last-mbeat: 0s ago, global: 0s ago, v: 2.6.120.51136, command=PING, timeout: 100, inst: 13, qu: 1, qs: 0, aw: False, bw: Inactive, last-in: 0, cur-in: 0, sync-ops: 2, async-ops: 0, serverEndpoint: 127.0.0.1:6379, conn-sec: n/a, aoc: 0, mc: 1/1/0, mgr: 10 of 10 available, clientName: CRAVERTOP7(SE.Redis-v2.6.120.51136), IOCP: (Busy=0,Free=1000,Min=16,Max=1000), WORKER: (Busy=2,Free=32765,Min=16,Max=32767), POOL: (Threads=33,QueuedItems=0,CompletedItems=6237,Timers=39), v: 2.6.120.51136 (see https://seredis.dev/Timeouts for some common client-side issues that can cause timeouts)
var ex = Assert.ThrowsAny<Exception>(() => db.Ping());
Log("Exception: " + ex.Message);
Assert.True(ex is RedisConnectionException or RedisTimeoutException);
Expand All @@ -75,7 +75,7 @@ public async Task DisconnectAndNoReconnectThrowsConnectionExceptionAsync()
Assert.SkipUnless(server.CanSimulateConnectionFailure, "Skipping because server cannot simulate connection failure");
server.SimulateConnectionFailure(SimulatedFailureType.All);

// Exception: The message timed out in the backlog attempting to send because no connection became available (400ms) - Last Connection Exception: SocketFailure (InputReaderCompleted, last-recv: 7) on 127.0.0.1:6379/Interactive, Idle/ReadAsync, last: PING, origin: SimulateConnectionFailure, outstanding: 0, last-read: 0s ago, last-write: 0s ago, keep-alive: 100s, state: ConnectedEstablished, mgr: 8 of 10 available, in: 0, in-pipe: 0, out-pipe: 0, last-heartbeat: never, last-mbeat: 0s ago, global: 0s ago, v: 2.6.120.51136, command=PING, timeout: 100, inst: 0, qu: 0, qs: 0, aw: False, bw: CheckingForTimeout, last-in: 0, cur-in: 0, sync-ops: 1, async-ops: 1, serverEndpoint: 127.0.0.1:6379, conn-sec: n/a, aoc: 0, mc: 1/1/0, mgr: 8 of 10 available, clientName: CRAVERTOP7(SE.Redis-v2.6.120.51136), IOCP: (Busy=0,Free=1000,Min=16,Max=1000), WORKER: (Busy=6,Free=32761,Min=16,Max=32767), POOL: (Threads=33,QueuedItems=0,CompletedItems=5547,Timers=60), v: 2.6.120.51136 (Please take a look at this article for some common client-side issues that can cause timeouts: https://seredis.dev/Timeouts)
// Exception: The message timed out in the backlog attempting to send because no connection became available (400ms) - Last Connection Exception: SocketFailure (InputReaderCompleted, last-recv: 7) on 127.0.0.1:6379/Interactive, Idle/ReadAsync, last: PING, origin: SimulateConnectionFailure, outstanding: 0, last-read: 0s ago, last-write: 0s ago, keep-alive: 100s, state: ConnectedEstablished, mgr: 8 of 10 available, in: 0, in-pipe: 0, out-pipe: 0, last-heartbeat: never, last-mbeat: 0s ago, global: 0s ago, v: 2.6.120.51136, command=PING, timeout: 100, inst: 0, qu: 0, qs: 0, aw: False, bw: CheckingForTimeout, last-in: 0, cur-in: 0, sync-ops: 1, async-ops: 1, serverEndpoint: 127.0.0.1:6379, conn-sec: n/a, aoc: 0, mc: 1/1/0, mgr: 8 of 10 available, clientName: CRAVERTOP7(SE.Redis-v2.6.120.51136), IOCP: (Busy=0,Free=1000,Min=16,Max=1000), WORKER: (Busy=6,Free=32761,Min=16,Max=32767), POOL: (Threads=33,QueuedItems=0,CompletedItems=5547,Timers=60), v: 2.6.120.51136 (see https://seredis.dev/Timeouts for some common client-side issues that can cause timeouts)
var ex = await Assert.ThrowsAsync<RedisConnectionException>(() => db.PingAsync());
Log("Exception: " + ex.Message);
Assert.StartsWith("The message timed out in the backlog attempting to send because no connection became available (1000ms) - Last Connection Exception: ", ex.Message);
Expand Down
4 changes: 2 additions & 2 deletions tests/StackExchange.Redis.Tests/ExceptionFactoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public async Task TimeoutException()
var ex = Assert.IsType<RedisTimeoutException>(rawEx);
Log("Exception: " + ex.Message);

// Example format: "Test Timeout, command=PING, inst: 0, qu: 0, qs: 0, aw: False, in: 0, in-pipe: 0, out-pipe: 0, last-in: 0, cur-in: 0, serverEndpoint: 127.0.0.1:6379, mgr: 10 of 10 available, clientName: TimeoutException, IOCP: (Busy=0,Free=1000,Min=8,Max=1000), WORKER: (Busy=2,Free=2045,Min=8,Max=2047), v: 2.1.0 (Please take a look at this article for some common client-side issues that can cause timeouts: https://seredis.dev/Timeouts)";
// Example format: "Test Timeout, command=PING, inst: 0, qu: 0, qs: 0, aw: False, in: 0, in-pipe: 0, out-pipe: 0, last-in: 0, cur-in: 0, serverEndpoint: 127.0.0.1:6379, mgr: 10 of 10 available, clientName: TimeoutException, IOCP: (Busy=0,Free=1000,Min=8,Max=1000), WORKER: (Busy=2,Free=2045,Min=8,Max=2047), v: 2.1.0 (see https://seredis.dev/Timeouts for some common client-side issues that can cause timeouts)";
Assert.StartsWith("Test Timeout, command=PING", ex.Message);
Assert.Contains("clientName: " + nameof(TimeoutException), ex.Message);
// Ensure our pipe numbers are in place
Expand All @@ -138,7 +138,7 @@ public async Task TimeoutException()
Assert.Contains("Timers=", ex.Message);
#endif
Assert.DoesNotContain("Unspecified/", ex.Message);
Assert.EndsWith(" (Please take a look at this article for some common client-side issues that can cause timeouts: https://seredis.dev/Timeouts)", ex.Message);
Assert.EndsWith(" (see https://seredis.dev/Timeouts for some common client-side issues that can cause timeouts)", ex.Message);
Assert.Null(ex.InnerException);
}
finally
Expand Down
Loading