Skip to content

Commit

Permalink
use extension methods
Browse files Browse the repository at this point in the history
  • Loading branch information
jfonseca-aneo committed Feb 6, 2025
1 parent bb21740 commit 30f37b5
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 29 deletions.
3 changes: 3 additions & 0 deletions packages/csharp/ArmoniK.Api.Common/ArmoniK.Api.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="JetBrains.Annotations" Version="2023.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
94 changes: 94 additions & 0 deletions packages/csharp/ArmoniK.Api.Common/Utils/ConfigurationExt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// This file is part of the ArmoniK project
//
// Copyright (C) ANEO, 2021-2025. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System;

using Microsoft.Extensions.Configuration;

namespace ArmoniK.Api.Common.Utils;

/// <summary>
/// Extends the functionality of the <see cref="IConfiguration" />
/// </summary>
public static class ConfigurationExt
{
/// <summary>
/// Configure an object with the given configuration.
/// </summary>
/// <typeparam name="T">Type of the options class</typeparam>
/// <param name="configuration">Configurations used to populate the class</param>
/// <param name="key">Path to the Object in the configuration</param>
/// <returns>
/// The initialized object
/// </returns>
/// <exception cref="InvalidOperationException">the <paramref name="key" /> is not found in the configurations.</exception>
public static T GetRequiredValue<T>(this IConfiguration configuration,
string key)
=> configuration.GetRequiredSection(key)
.Get<T>() ?? throw new InvalidOperationException($"{key} not found");

/// <summary>
/// Configure an object with the given configuration.
/// If the object is not found in the configuration, a new object in returned.
/// </summary>
/// <typeparam name="T">Type of the options class</typeparam>
/// <param name="configuration">Configurations used to populate the class</param>
/// <param name="key">Path to the Object in the configuration</param>
/// <returns>
/// The initialized object
/// </returns>
public static T GetInitializedValue<T>(this IConfiguration configuration,
string key)
where T : new()
=> configuration.GetSection(key)
.Get<T>() ?? new T();

/// <summary>
/// Retrieves a <see cref="TimeSpan"/> from the configuration, or returns the provided default value if not found or invalid.
/// If the configuration contains "MaxValue", it will return <see cref="TimeSpan.MaxValue"/>.
/// </summary>
/// <param name="configuration">The <see cref="IConfiguration"/> instance from which to retrieve the value.</param>
/// <param name="key">The key of the configuration value to retrieve.</param>
/// <param name="defaultValue">The default value to return if the key is not found or the value is invalid.</param>
/// <returns>A <see cref="TimeSpan"/> representing the configuration value, or <paramref name="defaultValue"/> if invalid or missing.</returns>
/// <exception cref="FormatException">Thrown if the value is not a valid <see cref="TimeSpan"/> or "MaxValue".</exception>
public static TimeSpan GetTimeSpanOrDefault(this IConfiguration configuration,
string key,
TimeSpan defaultValue)
{
try
{
return GetRequiredValue<TimeSpan>(configuration,
key);
}
catch (Exception)
{
var value = configuration.GetValue<string>(key);
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}

if (value!.Equals("MaxValue"))
{
return TimeSpan.MaxValue;
}

throw new FormatException($"'{key}' must be a valid TimeSpan or 'MaxValue'.");
}
}
}
32 changes: 3 additions & 29 deletions packages/csharp/ArmoniK.Api.Worker/Utils/WorkerServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

using ArmoniK.Api.Common.Channel.Utils;
using ArmoniK.Api.Common.Options;
using ArmoniK.Api.Common.Utils;

using JetBrains.Annotations;

Expand Down Expand Up @@ -136,40 +137,13 @@ public static WebApplication Create<T>(Action<IServiceCollection, IConfiguration

var channelOptions = context.Configuration.GetRequiredSection(ComputePlane.SettingSection).
GetSection(ComputePlane.WorkerChannelSection);
options.Limits.Http2.KeepAlivePingTimeout = ParseTimeSpan(channelOptions["KeepAlivePingTimeout"],
options.Limits.KeepAliveTimeout = channelOptions.GetTimeSpanOrDefault("KeepAliveTimeOut",TimeSpan.FromSeconds(130));
options.Limits.Http2.KeepAlivePingTimeout = channelOptions.GetTimeSpanOrDefault("KeepAlivePingTimeOut",
TimeSpan.FromSeconds(20));
options.Limits.KeepAliveTimeout = ParseTimeSpan(channelOptions["KeepAliveTimeOut"],
TimeSpan.FromSeconds(130));
var uri = new Uri(address);
options.ListenAnyIP(uri.Port,
listenOptions => listenOptions.Protocols = HttpProtocols.Http2);
break;

/* Local function to parse the KeepAlive options from the configuration section.
If the section to parse does not exist returns the given defaultValue
If a valid Time.Span string has been provided it parses and returns it
Provide support to handle the case where the option has been set to "MaxValue". */
TimeSpan ParseTimeSpan(string? toParse,
TimeSpan defaultValue)
{
if (string.IsNullOrEmpty(toParse))
{
return defaultValue;
}

if (toParse.Equals("MaxValue"))
{
return TimeSpan.MaxValue;
}

if (TimeSpan.TryParse(toParse,
out var result))
{
return result;
}

throw new FormatException($"Provide a valid TimeSpan format: {toParse} or 'MaxValue'");
}
default:
throw new InvalidOperationException("Socket type unknown");
}
Expand Down

0 comments on commit 30f37b5

Please sign in to comment.