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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,8 @@ In case you need consistent cache across clusters or data centers you can use ca
"Interval": "00:01:00",
"MaxErrors": 50,
"SwitchOffTime": "00:02:00"
}
},
"SyncEndpointsAuthAllowAnonymous": false
}
}
}
Expand Down Expand Up @@ -626,6 +627,8 @@ app.UseEndpoints(endpoints =>

`Configuration` argument here is a property on a `Startup` instance

If you have implicit authorization configured for your service you can allow anonymous access to sync endpoints by setting `MemcachedConfiguration.SyncSettings.SyncEndpointsAuthAllowAnonymous` to `true`.

When using cache synchronization feature, the `MemcachedClientResult.SyncSuccess` property can be inspected to determine whether the sync operation succeeded. When cache synchronization is not used this property is set to `false`.

To check whether the cache synchronization is configured and enabled call the `IMemcachedClient.IsCacheSyncEnabled` method.
Expand Down
5 changes: 5 additions & 0 deletions src/Aer.Memcached.Client/Config/MemcachedConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,11 @@ public class SynchronizationSettings
/// Settings of circuit breaker.
/// </summary>
public CacheSyncCircuitBreakerSettings CacheSyncCircuitBreaker { get; set; }

/// <summary>
/// If set to <c>true</c> allows anonymous access to cache sync endpoints.
/// </summary>
public bool SyncEndpointsAuthAllowAnonymous { get; set; }
}

public class SyncServer
Expand Down
2 changes: 1 addition & 1 deletion src/Aer.Memcached.Client/ConnectionPool/PooledSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public async Task WriteAsync(IList<ArraySegment<byte>> buffers)
/// <summary>
/// Releases all resources used by this instance and shuts down the inner <see cref="Socket"/>. This instance will not be usable anymore.
/// </summary>
/// <remarks>Use the <see cref="Dispose"/> method if you want to release this instance back into the pool.</remarks>
/// <remarks>Use the <see cref="PooledSocket.Dispose(bool)"/> method if you want to release this instance back into the pool.</remarks>
public void Destroy()
{
Dispose(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ internal static MemcachedClientValueResult<T> Cancelled(string operationName)
/// <summary>
/// Creates an instance of <see cref="MemcachedClientValueResult{T}"/> that indicates request cancellation.
/// </summary>
/// <param name="operationName">The memcached operation that was cancelled.</param>
/// <param name="defaultResultValue">The default value for <see cref="Result"/> property.</param>
internal static MemcachedClientValueResult<T> Cancelled(string operationName, T defaultResultValue)
=> new(
Expand Down
6 changes: 5 additions & 1 deletion src/Aer.Memcached/Abstractions/INodeHealthChecker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

namespace Aer.Memcached.Abstractions;

public interface INodeHealthChecker<in TNode> where TNode: class, INode
internal interface INodeHealthChecker<in TNode> where TNode: class, INode
{
/// <summary>
/// Checks if the given node is dead.
/// </summary>
/// <param name="node">The node to check.</param>
Task<bool> CheckNodeIsDeadAsync(TNode node);
}
12 changes: 11 additions & 1 deletion src/Aer.Memcached/Abstractions/INodeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@

namespace Aer.Memcached.Abstractions;

public interface INodeProvider<TNode> where TNode : class, INode
/// <summary>
/// Provides a collection of nodes for the consistent hashing algorithm.
/// </summary>
/// <typeparam name="TNode">The type of the node.</typeparam>
internal interface INodeProvider<TNode> where TNode : class, INode
{
/// <summary>
/// Indicates whether the node provider is properly configured and ready to provide nodes.
/// </summary>
bool IsConfigured();

/// <summary>
/// Gets the collection of nodes.
/// </summary>
ICollection<TNode> GetNodes();
}
3 changes: 3 additions & 0 deletions src/Aer.Memcached/Aer.Memcached.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

internal enum MetricsProviderType
{
Prometheus,
OpenTelemetry
Prometheus,
OpenTelemetry
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Aer.Memcached.Diagnostics.Listeners;

public class LoggingMemcachedDiagnosticListener
internal class LoggingMemcachedDiagnosticListener
{
private readonly ILogger<LoggingMemcachedDiagnosticListener> _logger;
private readonly MemcachedConfiguration _config;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ internal class MetricsMemcachedDiagnosticListener
private readonly MemcachedMetricsProvider _metricsProvider;
private readonly MemcachedConfiguration _config;

public MetricsMemcachedDiagnosticListener(MemcachedMetricsProvider metricsProvider, IOptions<MemcachedConfiguration> config)
public MetricsMemcachedDiagnosticListener(
MemcachedMetricsProvider metricsProvider,
IOptions<MemcachedConfiguration> config)
{
_metricsProvider = metricsProvider;
_config = config.Value;
Expand All @@ -23,18 +25,18 @@ public void ObserveCommandDuration(string commandName, double duration)
{
return;
}

_metricsProvider.ObserveCommandDurationSeconds(commandName, duration);
}

[DiagnosticName(MemcachedDiagnosticSource.CommandsTotalDiagnosticName)]
public void ObserveCommandsTotal(string commandName, string isSuccessful)
{
if (_config.Diagnostics.DisableDiagnostics)
{
return;
}

_metricsProvider.ObserveExecutedCommand(commandName, isSuccessful);
}

Expand All @@ -45,7 +47,7 @@ public void ObserveSocketPoolUsedSocketsCount(string enpointAddress, int usedSoc
{
return;
}

_metricsProvider.ObserveSocketPoolUsedSocketsCount(enpointAddress, usedSocketCount);
}
}
12 changes: 6 additions & 6 deletions src/Aer.Memcached/Diagnostics/MemcachedMetricsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ internal class MemcachedMetricsProvider

public static readonly Dictionary<string, double[]> MetricsBuckets = new()
{
[CommandDurationSecondsMetricName] = new[] {0.0005, 0.001, 0.005, 0.007, 0.015, 0.05, 0.2, 0.5, 1},
[SocketPoolUsedSocketsCountsMetricName] = new[] {0, 10.0, 20.0, 50.0, 100.0, 200.0, 500.0}
[CommandDurationSecondsMetricName] = [0.0005, 0.001, 0.005, 0.007, 0.015, 0.05, 0.2, 0.5, 1],
[SocketPoolUsedSocketsCountsMetricName] = [0, 10.0, 20.0, 50.0, 100.0, 200.0, 500.0]
};

private const string CommandNameLabel = "command_name";
Expand Down Expand Up @@ -79,18 +79,18 @@ public MemcachedMetricsProvider(
CommandDurationSecondsMetricName,
"",
MetricsBuckets[CommandDurationSecondsMetricName],
labelNames: new[] {CommandNameLabel});
labelNames: [CommandNameLabel]);

_socketPoolUsedSocketsCounts = metricFactory.CreateHistogram(
SocketPoolUsedSocketsCountsMetricName,
"",
MetricsBuckets[SocketPoolUsedSocketsCountsMetricName],
labelNames: new[] {SocketPoolEndpointAddressLabel});
labelNames: [SocketPoolEndpointAddressLabel]);

_commandsTotal = metricFactory.CreateCounter(
CommandsTotalOtelMetricName,
"",
labelNames: new[] {CommandNameLabel, IsSuccessfulLabel});
labelNames: [CommandNameLabel, IsSuccessfulLabel]);
}

/// <summary>
Expand Down Expand Up @@ -129,7 +129,7 @@ public void ObserveExecutedCommand(string commandName, string isSuccessful)
/// <summary>
/// Observes specified endpoint socket pool used sockets count.
/// </summary>
/// <param name="endpointAddress">The address of an endpoint to obeserve socket pool state for.</param>
/// <param name="endpointAddress">The address of an endpoint to observe socket pool state for.</param>
/// <param name="usedSocketCount">The number of currently used sockets for the specified pool.</param>
public void ObserveSocketPoolUsedSocketsCount(string endpointAddress, int usedSocketCount)
{
Expand Down
24 changes: 24 additions & 0 deletions src/Aer.Memcached/Helpers/EndpointBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Aer.Memcached.Client.Config;
using Microsoft.AspNetCore.Builder;

namespace Aer.Memcached.Helpers;

internal static class EndpointBuilderExtensions
{
public static RouteHandlerBuilder AllowAnonymousIfConfigured(
this RouteHandlerBuilder endpointBuilder,
MemcachedConfiguration configuration)
{
if (configuration.SyncSettings == null)
{
return endpointBuilder;
}

if (configuration.SyncSettings.SyncEndpointsAuthAllowAnonymous)
{
endpointBuilder.AllowAnonymous();
}

return endpointBuilder;
}
}
36 changes: 30 additions & 6 deletions src/Aer.Memcached/Pod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,29 @@

namespace Aer.Memcached;

public class Pod: INode
/// <summary>
/// Represents a Memcached pod (node) in the cluster.
/// </summary>
public class Pod : INode
{
private readonly string _nodeKey;

/// <summary>
/// The IP address of the Memcached pod.
/// </summary>
public string IpAddress { get; }


/// <summary>
/// The port on which the Memcached pod is listening.
/// </summary>
public int MemcachedPort { get; }

/// <summary>
/// Initializes a new instance of the <see cref="Pod"/> class with the specified IP address and port.
/// </summary>
/// <param name="ipAddress">The IP address of the Memcached pod.</param>
/// <param name="port">The port on which the Memcached pod is listening.</param>
/// <exception cref="ArgumentException">Occurs when either <paramref name="ipAddress"/> or <paramref name="port"/> is not specified or empty.</exception>
public Pod(string ipAddress, int port = MemcachedConfiguration.DefaultMemcachedPort)
{
if (ipAddress is null or {Length: 0})
Expand All @@ -26,30 +41,38 @@ public Pod(string ipAddress, int port = MemcachedConfiguration.DefaultMemcachedP

IpAddress = ipAddress;
MemcachedPort = port;
_nodeKey = $"{IpAddress}:{MemcachedPort}";

_nodeKey = $"{IpAddress}:{MemcachedPort}";
}

/// <inheritdoc/>
public string GetKey()
{
return _nodeKey;
}

/// <inheritdoc/>
public EndPoint GetEndpoint()
{
return new DnsEndPoint(IpAddress, MemcachedPort);
}

/// <summary>
/// Determines whether the specified Pod is equal to the current Pod.
/// </summary>
/// <param name="other">The pod to compare this pod to.</param>
protected bool Equals(Pod other)
{
return IpAddress == other.IpAddress && MemcachedPort == other.MemcachedPort;
}

/// <inheritdoc/>
public bool Equals(INode other)
{
return GetKey() == other?.GetKey();
}

/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
Expand All @@ -67,15 +90,16 @@ public override bool Equals(object obj)
return false;
}

return Equals((Pod)obj);
return Equals((Pod) obj);
}

/// <inheritdoc/>
public override int GetHashCode()
{
var ipAddressHash = IpAddress.GetHashCode();

var portHash = MemcachedPort.GetHashCode();

return HashCode.Combine(ipAddressHash, portHash);
}
}
Loading
Loading