Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,9 @@ public static DefaultOptionsProvider GetProvider(EndPoint endpoint)
/// Gets the default client name for a connection.
/// </summary>
protected virtual string GetDefaultClientName() =>
(TryGetAzureRoleInstanceIdNoThrow()
$"{TryGetAzureRoleInstanceIdNoThrow()
?? ComputerName
?? "StackExchange.Redis") + "(SE.Redis-v" + LibraryVersion + ")";
?? "StackExchange.Redis"}({LibraryName}-v{LibraryVersion})";

/// <summary>
/// Gets the library name to use for CLIENT SETINFO lib-name calls to Redis during handshake.
Expand All @@ -248,9 +248,9 @@ protected virtual string GetDefaultClientName() =>
public virtual string LibraryName => "SE.Redis";

/// <summary>
/// String version of the StackExchange.Redis library, for use in any options.
/// String version of the StackExchange.Redis library, for use in other options and in CLIENT SETINFO lib-ver.
/// </summary>
protected static string LibraryVersion => Utils.GetLibVersion();
public virtual string LibraryVersion => Utils.GetLibVersion();

/// <summary>
/// Name of the machine we're running on, for use in any options.
Expand Down
33 changes: 28 additions & 5 deletions src/StackExchange.Redis/ConfigurationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ internal const string
SetClientLibrary = "setlib",
Protocol = "protocol",
HighIntegrity = "highIntegrity",
TcpKeepAlive = "tcpKeepAlive";
TcpKeepAlive = "tcpKeepAlive",
LibraryName = "libraryName",
LibraryVersion = "libraryVersion";

private static readonly Dictionary<string, string> normalizedOptions = new[]
{
Expand Down Expand Up @@ -152,6 +154,8 @@ internal const string
Protocol,
HighIntegrity,
TcpKeepAlive,
LibraryName,
LibraryVersion,
}.ToDictionary(x => x, StringComparer.OrdinalIgnoreCase);

public static string TryNormalize(string value)
Expand Down Expand Up @@ -209,7 +213,7 @@ private enum OptionFlags : ulong

private OptionFlags optionFlags;

private string? tieBreaker, sslHost, configChannel, user, password;
private string? tieBreaker, sslHost, configChannel, user, password, libraryName, libraryVersion;

private TimeSpan heartbeatInterval;

Expand Down Expand Up @@ -368,7 +372,22 @@ public bool SetClientLibrary
/// </summary>
/// <remarks>If the value is null, empty or whitespace, then the value from the options-provider is used;
/// to disable the library name feature, use <see cref="SetClientLibrary"/> instead.</remarks>
public string? LibraryName { get; set; }
public string? LibraryName
{
get => libraryName ?? Defaults.LibraryName;
set => libraryName = value;
}

/// <summary>
/// Gets or sets the library version to use for CLIENT SETINFO lib-ver calls to Redis during handshake.
/// Defaults to the StackExchange.Redis version, but can be overridden by extensions or for other purposes.
/// </summary>
/// <remarks>To disable the library version feature, use <see cref="SetClientLibrary"/> instead.</remarks>
public string? LibraryVersion
{
get => libraryVersion ?? Defaults.LibraryVersion;
set => libraryVersion = value;
}

/// <summary>
/// Automatically encodes and decodes channels.
Expand Down Expand Up @@ -967,7 +986,8 @@ public static ConfigurationOptions Parse(string configuration, bool ignoreUnknow
SslClientAuthenticationOptions = SslClientAuthenticationOptions,
#endif
Tunnel = Tunnel,
LibraryName = LibraryName,
libraryName = libraryName,
libraryVersion = libraryVersion,
_protocol = _protocol,
heartbeatInterval = heartbeatInterval,
WriteMode = WriteMode,
Expand Down Expand Up @@ -1063,6 +1083,8 @@ public string ToString(bool includePassword)
{
Append(sb, OptionKeys.Tunnel, tunnel.ToString());
}
Append(sb, OptionKeys.LibraryName, libraryName);
Append(sb, OptionKeys.LibraryVersion, libraryVersion);
commandMap?.AppendDeltas(sb);
return sb.ToString();

Expand Down Expand Up @@ -1164,7 +1186,8 @@ private void Clear()
CertificateValidation = null;
BeforeSocketConnect = null;
ChannelPrefix = default;
LibraryName = null;
libraryName = null;
libraryVersion = null;
#pragma warning disable CS0618 // Type or member is obsolete
SocketManager = null;
#pragma warning restore CS0618 // Type or member is obsolete
Expand Down
17 changes: 5 additions & 12 deletions src/StackExchange.Redis/ConnectionMultiplexer.LibraryName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public partial class ConnectionMultiplexer
/// <inheritdoc cref="IConnectionMultiplexer.AddLibraryNameSuffix(string)" />
public void AddLibraryNameSuffix(string suffix)
{
if (!RawConfig.SetClientLibrary) return; // disabled

if (string.IsNullOrWhiteSpace(suffix)) return; // trivial

// sanitize and re-check
Expand All @@ -28,7 +30,7 @@ public void AddLibraryNameSuffix(string suffix)
}

// if we get here, we *actually changed something*; we can retroactively fixup the connections
var libName = GetFullLibraryName(); // note this also checks SetClientLibrary
var libName = GetFullLibraryName();
if (string.IsNullOrWhiteSpace(libName) || !CommandMap.IsAvailable(RedisCommand.CLIENT)) return; // disabled on no lib name

// note that during initial handshake we use raw Message; this is low frequency - no
Expand Down Expand Up @@ -56,18 +58,9 @@ public void AddLibraryNameSuffix(string suffix)

internal string GetFullLibraryName()
{
var config = RawConfig;
if (!config.SetClientLibrary) return ""; // disabled

var libName = config.LibraryName;
if (string.IsNullOrWhiteSpace(libName))
{
// defer to provider if missing (note re null vs blank; if caller wants to disable
// it, they should set SetClientLibrary to false, not set the name to empty string)
libName = config.Defaults.LibraryName;
}

var libName = RawConfig.LibraryName;
libName = ServerEndPoint.ClientInfoSanitize(libName);

// if no primary name, return nothing, even if suffixes exist
if (string.IsNullOrWhiteSpace(libName)) return "";

Expand Down
1 change: 0 additions & 1 deletion src/StackExchange.Redis/PublicAPI/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1693,7 +1693,6 @@ static StackExchange.Redis.Configuration.DefaultOptionsProvider.AddProvider(Stac
static StackExchange.Redis.Configuration.DefaultOptionsProvider.ComputerName.get -> string!
static StackExchange.Redis.Configuration.DefaultOptionsProvider.GetProvider(StackExchange.Redis.EndPointCollection! endpoints) -> StackExchange.Redis.Configuration.DefaultOptionsProvider!
static StackExchange.Redis.Configuration.DefaultOptionsProvider.GetProvider(System.Net.EndPoint! endpoint) -> StackExchange.Redis.Configuration.DefaultOptionsProvider!
static StackExchange.Redis.Configuration.DefaultOptionsProvider.LibraryVersion.get -> string!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mgravell is there any chance this change is "okay"? I really want to change LibraryVersion from a protected static to public virtual, but that means removing this line from the shipped API.

If this is too much of a break, I can either a) leave the static and add a new instance property with a different name, or b) have the extension package set ConfigurationOptions.LibraryVersion directly rather than bubbling it up form its custom DefaultOptionsProvider. But that's a weird divergence from the other options and risks interacting with customers' use of ConfigurationOptions.LibraryVersion

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem isn't changing the shipped file - the problem is the MissingMethodException etc at runtime when someone builds against one version and gets given another - this applies doubly for libraries that package SE.Redis such as azure. I think maybe the right thing here is to accept a sucky name for a new member.

static StackExchange.Redis.ConfigurationOptions.Parse(string! configuration) -> StackExchange.Redis.ConfigurationOptions!
static StackExchange.Redis.ConfigurationOptions.Parse(string! configuration, bool ignoreUnknown) -> StackExchange.Redis.ConfigurationOptions!
static StackExchange.Redis.ConnectionMultiplexer.Connect(StackExchange.Redis.ConfigurationOptions! configuration, System.IO.TextWriter? log = null) -> StackExchange.Redis.ConnectionMultiplexer!
Expand Down
3 changes: 3 additions & 0 deletions src/StackExchange.Redis/PublicAPI/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
#nullable enable
StackExchange.Redis.ConfigurationOptions.LibraryVersion.get -> string?
StackExchange.Redis.ConfigurationOptions.LibraryVersion.set -> void
virtual StackExchange.Redis.Configuration.DefaultOptionsProvider.LibraryVersion.get -> string!
2 changes: 1 addition & 1 deletion src/StackExchange.Redis/ServerEndPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,7 @@ private async Task HandshakeAsync(PhysicalConnection connection, ILogger? log)
await WriteDirectOrQueueFireAndForgetAsync(connection, msg, ResultProcessor.DemandOK).ForAwait();
}

var version = ClientInfoSanitize(Utils.GetLibVersion());
var version = ClientInfoSanitize(config.LibraryVersion);
if (!string.IsNullOrWhiteSpace(version))
{
msg = Message.Create(-1, CommandFlags.FireAndForget | Message.NoFlushFlag, RedisCommand.CLIENT, RedisLiterals.SETINFO, RedisLiterals.lib_ver, version);
Expand Down
3 changes: 2 additions & 1 deletion tests/StackExchange.Redis.Tests/ConfigTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ orderby name
"EndPoints",
"heartbeatInterval",
"keepAlive",
"LibraryName",
"libraryName",
"libraryVersion",
"loggerFactory",
"optionFlags",
#if DEBUG
Expand Down
Loading