Skip to content

Commit

Permalink
No commit message
Browse files Browse the repository at this point in the history
  • Loading branch information
2 parents 6e91382 + 3bf6938 commit adb3c2c
Show file tree
Hide file tree
Showing 35 changed files with 742 additions and 231 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
<head>
<meta name="Momento .NET Client Library Documentation" content=".NET client software development kit for Momento Serverless Cache">
</head>
<img src="https://docs.momentohq.com/img/logo.svg" alt="logo" width="400"/>

[![project status](https://momentohq.github.io/standards-and-practices/badges/project-status-official.svg)](https://github.com/momentohq/standards-and-practices/blob/main/docs/momento-on-github.md)
Expand Down Expand Up @@ -76,7 +79,7 @@ using (SimpleCacheClient client = new SimpleCacheClient(Configurations.Laptop.La
CacheGetResponse getResponse = await client.GetAsync(CACHE_NAME, KEY);
if (getResponse is CacheGetResponse.Hit hitResponse)
{
Console.WriteLine($"Looked up value: {hitResponse.String()}, Stored value: {VALUE}");
Console.WriteLine($"Looked up value: {hitResponse.ValueString}, Stored value: {VALUE}");
} else if (getResponse is CacheGetResponse.Error getError) {
Console.WriteLine($"Error getting value: {getError.Message}");
}
Expand Down
2 changes: 1 addition & 1 deletion examples/MomentoApplication/MomentoApplication.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Momento.Sdk" Version="0.33.0" />
<PackageReference Include="Momento.Sdk" Version="0.34.0" />
</ItemGroup>
<ItemGroup>
<None Remove="Microsoft.Extensions.Logging.Console" />
Expand Down
2 changes: 1 addition & 1 deletion examples/MomentoApplication/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
CacheGetResponse getResponse = await client.GetAsync(CACHE_NAME, KEY);
if (getResponse is CacheGetResponse.Hit getHit)
{
Console.WriteLine($"Looked up value: {getHit.String()}, Stored value: {VALUE}");
Console.WriteLine($"Looked up value: {getHit.ValueString}, Stored value: {VALUE}");
} else if (getResponse is CacheGetResponse.Miss)
{
// This shouldn't be fatal but should be reported.
Expand Down
2 changes: 1 addition & 1 deletion examples/MomentoLoadGen/MomentoLoadGen.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
<PackageReference Include="Momento.Sdk" Version="0.31.0" />
<PackageReference Include="Momento.Sdk" Version="0.34.0" />
<PackageReference Include="HdrHistogram" Version="2.5.0" />
</ItemGroup>
</Project>
11 changes: 4 additions & 7 deletions examples/MomentoLoadGen/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using HdrHistogram;
using Microsoft.Extensions.Logging;
using Momento.Sdk;
using Momento.Sdk.Auth;
using Momento.Sdk.Config;
using Momento.Sdk.Exceptions;
using Momento.Sdk.Responses;
Expand Down Expand Up @@ -88,15 +89,11 @@ public CsharpLoadGenerator(ILoggerFactory loggerFactory, IConfiguration momentoC

public async Task Run()
{
string? authToken = System.Environment.GetEnvironmentVariable("MOMENTO_AUTH_TOKEN");
if (authToken == null)
{
throw new Exception("Missing required environment variable MOMENTO_AUTH_TOKEN");
}
ICredentialProvider authProvider = new EnvMomentoTokenProvider("MOMENTO_AUTH_TOKEN");

var momento = new SimpleCacheClient(
_momentoClientConfig,
authToken,
authProvider,
CACHE_ITEM_TTL_SECONDS,
_loggerFactory
);
Expand Down Expand Up @@ -236,7 +233,7 @@ private async Task IssueAsyncSetGet(SimpleCacheClient client, CsharpLoadGenerato
await Task.Delay((int)(delayMillisBetweenRequests - getDuration));
}

string value = hitResponse.String();
string value = hitResponse.ValueString;
string valueString = $"{value.Substring(0, 10)}... (len: {value.Length})";

var globalRequestCount = context.GlobalRequestCount;
Expand Down
2 changes: 1 addition & 1 deletion examples/MomentoUsage/MomentoUsage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
<None Remove="Momento.Sdk" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Momento.Sdk" Version="0.33.0" />
<PackageReference Include="Momento.Sdk" Version="0.34.0" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion examples/MomentoUsage/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
CacheGetResponse getResponse = await client.GetAsync(CACHE_NAME, KEY);
if (getResponse is CacheGetResponse.Hit hitResponse)
{
Console.WriteLine($"Looked up value: {hitResponse.String()}, Stored value: {VALUE}");
Console.WriteLine($"Looked up value: {hitResponse.ValueString}, Stored value: {VALUE}");
} else if (getResponse is CacheGetResponse.Error getError) {
Console.WriteLine($"Error getting value: {getError.Message}");
}
Expand Down
23 changes: 19 additions & 4 deletions src/Momento.Sdk/Auth/EnvMomentoTokenProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,22 @@ namespace Momento.Sdk.Auth;
using Momento.Sdk.Exceptions;
using Momento.Sdk.Internal;

/// <summary>
/// Reads and parses a JWT token stored as an environment variable.
/// </summary>
public class EnvMomentoTokenProvider : ICredentialProvider
{
/// <summary>
/// JWT provided by user
/// </summary>
public string AuthToken { get; private set; }
public string ControlEndpoint {get; private set; }
/// <summary>
/// Control endpoint extracted from JWT
/// </summary>
public string ControlEndpoint { get; private set; }
/// <summary>
/// Cache endpoint extracted from JWT
/// </summary>
public string CacheEndpoint { get; private set; }

/// <summary>
Expand All @@ -16,16 +28,19 @@ public class EnvMomentoTokenProvider : ICredentialProvider
/// <param name="name">Name of the environment variable that contains the JWT token.</param>
public EnvMomentoTokenProvider(string name)
{
AuthToken = Environment.GetEnvironmentVariable(name);
AuthToken = Environment.GetEnvironmentVariable(name);
if (String.IsNullOrEmpty(AuthToken))
{
throw new InvalidArgumentException($"Environment variable '{name}' is empty or null.");
}

Claims claims;
try {
try
{
claims = JwtUtils.DecodeJwt(AuthToken);
} catch (InvalidArgumentException) {
}
catch (InvalidArgumentException)
{
throw new InvalidArgumentException("The supplied Momento authToken is not valid.");
}
ControlEndpoint = claims.ControlEndpoint;
Expand Down
14 changes: 13 additions & 1 deletion src/Momento.Sdk/Auth/ICredentialProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,21 @@ namespace Momento.Sdk.Auth;

using System.Collections.Generic;

/// <summary>
/// Interface for credentials
/// </summary>
public interface ICredentialProvider
{
/// <summary>
/// JWT provided by user
/// </summary>
string AuthToken { get; }
string ControlEndpoint {get; }
/// <summary>
/// Control endpoint
/// </summary>
string ControlEndpoint { get; }
/// <summary>
/// Cache endpoint
/// </summary>
string CacheEndpoint { get; }
}
89 changes: 79 additions & 10 deletions src/Momento.Sdk/Config/Configuration.cs
Original file line number Diff line number Diff line change
@@ -1,60 +1,129 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Momento.Sdk.Config.Middleware;
using Momento.Sdk.Config.Retry;
using Momento.Sdk.Config.Transport;

namespace Momento.Sdk.Config;

/// <inheritdoc cref="Momento.Sdk.Config.IConfiguration" />
public class Configuration : IConfiguration
{
/// <inheritdoc cref="Microsoft.Extensions.Logging.ILoggerFactory" />
public ILoggerFactory LoggerFactory { get; }
/// <inheritdoc cref="Momento.Sdk.Config.Retry.IRetryStrategy" />
public IRetryStrategy RetryStrategy { get; }
/// <inheritdoc cref="Momento.Sdk.Config.Middleware.IMiddleware" />
public IList<IMiddleware> Middlewares { get; }
/// <inheritdoc cref="Momento.Sdk.Config.Transport.ITransportStrategy" />
public ITransportStrategy TransportStrategy { get; }

public Configuration(IRetryStrategy retryStrategy, ITransportStrategy transportStrategy)
: this(retryStrategy, new List<IMiddleware>(), transportStrategy)
/// <summary>
/// <inheritdoc cref="Momento.Sdk.Config.IConfiguration" />
/// </summary>
/// <param name="retryStrategy">Defines a contract for how and when to retry a request</param>
/// <param name="transportStrategy">This is responsible for configuring network tunables.</param>
/// <param name="loggerFactory">This is responsible for configuraing logging.</param>
public Configuration(IRetryStrategy retryStrategy, ITransportStrategy transportStrategy, ILoggerFactory? loggerFactory = null)
: this(retryStrategy, new List<IMiddleware>(), transportStrategy, loggerFactory)
{

}

public Configuration(IRetryStrategy retryStrategy, IList<IMiddleware> middlewares, ITransportStrategy transportStrategy)
/// <summary>
/// <inheritdoc cref="Momento.Sdk.Config.IConfiguration" />
/// </summary>
/// <param name="retryStrategy">Defines a contract for how and when to retry a request</param>
/// <param name="middlewares">The Middleware interface allows the Configuration to provide a higher-order function that wraps all requests.</param>
/// <param name="transportStrategy">This is responsible for configuring network tunables.</param>
/// <param name="loggerFactory">This is responsible for configuraing logging.</param>
public Configuration(IRetryStrategy retryStrategy, IList<IMiddleware> middlewares, ITransportStrategy transportStrategy, ILoggerFactory? loggerFactory = null)

{
this.RetryStrategy = retryStrategy;
this.Middlewares = middlewares;
this.LoggerFactory = loggerFactory ?? NullLoggerFactory.Instance;

var retryStrategyWithLogger = retryStrategy.LoggerFactory != null ? retryStrategy : retryStrategy.WithLoggerFactory(loggerFactory!);
var middlewaresWithLogger = middlewares.Select(m => m.LoggerFactory != null ? m : m.WithLoggerFactory(loggerFactory!)).ToList();

this.RetryStrategy = retryStrategyWithLogger;
this.Middlewares = middlewaresWithLogger;
this.TransportStrategy = transportStrategy;
}

/// <summary>
/// Configures logging
/// </summary>
/// <param name="loggerFactory">This is responsible for configuraing logging.</param>
/// <returns>Configuration object with custom logging provided</returns>
public IConfiguration WithLoggerFactory(ILoggerFactory loggerFactory)
{
return new Configuration(RetryStrategy, Middlewares, TransportStrategy, loggerFactory);
}

/// <summary>
/// Configures retry strategy
/// </summary>
/// <param name="retryStrategy">Defines a contract for how and when to retry a request</param>
/// <returns>Configuration object with custom retry strategy provided</returns>
public IConfiguration WithRetryStrategy(IRetryStrategy retryStrategy)
{
return new Configuration(retryStrategy, Middlewares, TransportStrategy);
return new Configuration(retryStrategy, Middlewares, TransportStrategy, LoggerFactory);
}

/// <summary>
/// Configures middlewares
/// </summary>
/// <param name="middlewares">The Middleware interface allows the Configuration to provide a higher-order function that wraps all requests.</param>
/// <returns>Configuration object with custom middlewares provided</returns>
public IConfiguration WithMiddlewares(IList<IMiddleware> middlewares)
{
return new Configuration(RetryStrategy, middlewares, TransportStrategy);
return new Configuration(RetryStrategy, middlewares, TransportStrategy, LoggerFactory);
}

/// <summary>
/// Configures transport trategy
/// </summary>
/// <param name="transportStrategy">This is responsible for configuring network tunables.</param>
/// <returns>Configuration object with custom transport strategy provided</returns>
public IConfiguration WithTransportStrategy(ITransportStrategy transportStrategy)
{
return new Configuration(RetryStrategy, Middlewares, transportStrategy);
return new Configuration(RetryStrategy, Middlewares, transportStrategy, LoggerFactory);
}

/// <summary>
/// Configures middlewares
/// </summary>
/// <param name="additionalMiddlewares">The Middleware interface allows the Configuration to provide a higher-order function that wraps all requests.</param>
/// <returns>Configuration object with custom middlewares provided</returns>
public Configuration WithAdditionalMiddlewares(IList<IMiddleware> additionalMiddlewares)
{
return new(
retryStrategy: RetryStrategy,
middlewares: Middlewares.Concat(additionalMiddlewares).ToList(),
transportStrategy: TransportStrategy
transportStrategy: TransportStrategy,
loggerFactory: LoggerFactory
);
}

/// <summary>
/// Configures client timeout for transport strategy
/// </summary>
/// <param name="clientTimeoutMillis">Client timeout in milliseconds.</param>
/// <returns>Configuration object with client timeout provided</returns>
public Configuration WithClientTimeoutMillis(uint clientTimeoutMillis)
{
return new(
retryStrategy: RetryStrategy,
middlewares: Middlewares,
transportStrategy: TransportStrategy.WithClientTimeoutMillis(clientTimeoutMillis)
transportStrategy: TransportStrategy.WithClientTimeoutMillis(clientTimeoutMillis),
loggerFactory: LoggerFactory
);
}

IConfiguration IConfiguration.WithClientTimeoutMillis(uint clientTimeoutMillis)
{
return WithClientTimeoutMillis(clientTimeoutMillis);
}
}
6 changes: 5 additions & 1 deletion src/Momento.Sdk/Config/Configurations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

namespace Momento.Sdk.Config;

/// <summary>
/// Provide pre-build configurations.
/// </summary>
public class Configurations
{
/// <summary>
Expand All @@ -27,7 +30,8 @@ public static Laptop Latest
IRetryStrategy retryStrategy = new FixedCountRetryStrategy(maxAttempts: 3);
ITransportStrategy transportStrategy = new StaticTransportStrategy(
maxConcurrentRequests: 200,
grpcConfig: new StaticGrpcConfiguration(deadlineMilliseconds: 5000));
grpcConfig: new StaticGrpcConfiguration(deadlineMilliseconds: 5000)
);
return new Laptop(retryStrategy, transportStrategy);
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/Momento.Sdk/Config/IConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Momento.Sdk.Config.Middleware;
using Momento.Sdk.Config.Retry;
using Momento.Sdk.Config.Transport;
Expand All @@ -11,11 +12,16 @@ namespace Momento.Sdk.Config;
/// </summary>
public interface IConfiguration
{
public ILoggerFactory LoggerFactory { get; }

public IRetryStrategy RetryStrategy { get; }
public IList<IMiddleware> Middlewares { get; }
public ITransportStrategy TransportStrategy { get; }

public IConfiguration WithLoggerFactory(ILoggerFactory loggerFactory);
public IConfiguration WithRetryStrategy(IRetryStrategy retryStrategy);
public IConfiguration WithMiddlewares(IList<IMiddleware> middlewares);
public IConfiguration WithTransportStrategy(ITransportStrategy transportStrategy);

public IConfiguration WithClientTimeoutMillis(uint clientTimeoutMillis);
}
7 changes: 6 additions & 1 deletion src/Momento.Sdk/Config/Middleware/IMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Interceptors;
using Microsoft.Extensions.Logging;
using Momento.Sdk.Config.Retry;

namespace Momento.Sdk.Config.Middleware;
Expand Down Expand Up @@ -35,6 +36,10 @@ Func<Metadata> GetTrailers
/// </summary>
public interface IMiddleware
{
public ILoggerFactory? LoggerFactory { get; }

public IMiddleware WithLoggerFactory(ILoggerFactory loggerFactory);

/// <summary>
/// Called as a wrapper around each request; can be used to time the request and collect metrics etc.
/// </summary>
Expand All @@ -49,6 +54,6 @@ public Task<MiddlewareResponseState<TResponse>> WrapRequest<TRequest, TResponse>
TRequest request,
CallOptions callOptions,
Func<TRequest, CallOptions, Task<MiddlewareResponseState<TResponse>>> continuation
);
) where TRequest : class where TResponse: class;

}
Loading

0 comments on commit adb3c2c

Please sign in to comment.