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
68 changes: 67 additions & 1 deletion src/Couchbase.Analytics/Internal/ConnectionString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,73 @@ public bool TryGetParameter(string key, out TimeSpan parameter)
{
if (TryGetParameter(key, out string value))
{
parameter = TimeSpan.FromMilliseconds(Convert.ToUInt32(value));
var trimmed = value.Trim();
if (trimmed.Length == 0)
{
parameter = default;
return false;
}

// Parse optional unit suffix: us, ms, s, m, h (case-insensitive)
// Default unit is milliseconds if no suffix is provided
var lower = trimmed.ToLowerInvariant();

// Determine unit and numeric portion (check longest suffixes first)
string unit;
string numericPortion;
if (lower.EndsWith("us"))
{
unit = "us";
numericPortion = trimmed[..^2].Trim();
}
else if (lower.EndsWith("ms"))
{
unit = "ms";
numericPortion = trimmed[..^2].Trim();
}
else if (lower.EndsWith("s"))
{
unit = "s";
numericPortion = trimmed[..^1].Trim();
}
else if (lower.EndsWith("m"))
{
unit = "m";
numericPortion = trimmed[..^1].Trim();
}
else if (lower.EndsWith("h"))
{
unit = "h";
numericPortion = trimmed[..^1].Trim();
}
else
{
unit = "ms";
numericPortion = trimmed;
}

if (numericPortion.Length == 0)
{
parameter = TimeSpan.Zero;
return false;
}

// Allow integer or decimal values
if (!double.TryParse(numericPortion, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out var amount))
{
parameter = TimeSpan.Zero;
throw new FormatException($"Invalid numeric value for parameter '{key}': '{value}'");
}

parameter = unit switch
{
"us" => TimeSpan.FromMicroseconds(amount),
"ms" => TimeSpan.FromMilliseconds(amount),
"s" => TimeSpan.FromSeconds(amount),
"m" => TimeSpan.FromMinutes(amount),
"h" => TimeSpan.FromHours(amount),
_ => TimeSpan.FromMilliseconds(amount)
};
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,27 @@ public void Test_ConnectionString_TimeoutParameter_QueryTimeout_Values(string ti
Assert.Equal(TimeSpan.FromMilliseconds(expectedMilliseconds), options.TimeoutOptions.QueryTimeout);
}

[Theory]
[InlineData("500us", 5_000L)] // 500 microseconds -> 5000 ticks
[InlineData("250ms", 2_500_000L)] // 250 milliseconds -> 2,500,000 ticks
[InlineData("30s", 300_000_000L)] // 30 seconds -> 300,000,000 ticks
[InlineData("2m", 1_200_000_000L)] // 2 minutes -> 1,200,000,000 ticks
[InlineData("1h", 36_000_000_000L)] // 1 hour -> 36,000,000,000 ticks
[InlineData("30S", 300_000_000L)] // case-insensitive
[InlineData("1.5s", 15_000_000L)] // fractional seconds
[InlineData("0s", 0L)] // zero value
public void Test_ConnectionString_TimeoutParameter_ConnectTimeout_WithUnits(string timeoutValue, long expectedTicks)
{
var connectionString = $"http://localhost:8095?timeout.connect_timeout={timeoutValue}";

var options = new ClusterOptions
{
ConnectionString = connectionString
};

Assert.Equal(expectedTicks, options.TimeoutOptions.ConnectTimeout.Ticks);
}

[Theory]
[InlineData("true", true)]
[InlineData("false", false)]
Expand Down
Loading