Refactored the cart service to add more telemetry
1. Added more telemetry around starting redis cache 2. Now if you don't specify redis cache address via command line or environment variable, it will run with local cart (no redis). This is useful for debugging purposes
This commit is contained in:
parent
07bb077c10
commit
ca6e6647ef
5 changed files with 63 additions and 24 deletions
|
@ -3,6 +3,7 @@ using System.IO;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using cartservice.cartstore;
|
||||
using cartservice.interfaces;
|
||||
using CommandLine;
|
||||
using Grpc.Core;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
@ -28,22 +29,23 @@ namespace cartservice
|
|||
public string Redis { get; set; }
|
||||
}
|
||||
|
||||
static object StartServer(string host, int port, string redisAddress)
|
||||
static object StartServer(string host, int port, ICartStore cartStore)
|
||||
{
|
||||
// Run the server in a separate thread and make the main thread busy waiting.
|
||||
// The busy wait is because when we run in a container, we can't use techniques such as waiting on user input (Console.Readline())
|
||||
Task.Run(() =>
|
||||
Task.Run(async () =>
|
||||
{
|
||||
//var store = new LocalCartStore();
|
||||
var store = new RedisCartStore(redisAddress);
|
||||
Console.WriteLine($"Trying to start a grpc server at {host}:{port}");
|
||||
Server server = new Server
|
||||
{
|
||||
Services = { Hipstershop.CartService.BindService(new CartServiceImpl(store)) },
|
||||
Services = { Hipstershop.CartService.BindService(new CartServiceImpl(cartStore)) },
|
||||
Ports = { new ServerPort(host, port, ServerCredentials.Insecure) }
|
||||
};
|
||||
|
||||
Console.WriteLine($"Cart server is listening at {host}:{port}");
|
||||
server.Start();
|
||||
|
||||
await cartStore.InitializeAsync();
|
||||
});
|
||||
|
||||
// Busy wait to keep the process alive
|
||||
|
@ -75,8 +77,8 @@ namespace cartservice
|
|||
hostname = Environment.GetEnvironmentVariable(CART_SERVICE_ADDRESS);
|
||||
if (string.IsNullOrEmpty(hostname))
|
||||
{
|
||||
Console.WriteLine($"Environment variable {CART_SERVICE_ADDRESS} was not set. Setting the host to 127.0.0.1");
|
||||
hostname = "127.0.0.1";
|
||||
Console.WriteLine($"Environment variable {CART_SERVICE_ADDRESS} was not set. Setting the host to 0.0.0.0");
|
||||
hostname = "0.0.0.0";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,19 +100,23 @@ namespace cartservice
|
|||
}
|
||||
|
||||
// Set redis cache host (hostname+port)
|
||||
string redis = options.Redis;
|
||||
if (string.IsNullOrEmpty(redis))
|
||||
ICartStore cartStore;
|
||||
string redis = ReadRedisAddress(options.Redis);
|
||||
|
||||
// Redis was specified via command line or environment variable
|
||||
if (!string.IsNullOrEmpty(redis))
|
||||
{
|
||||
Console.WriteLine($"Reading redis cache address from environment variable {REDIS_ADDRESS}");
|
||||
redis = Environment.GetEnvironmentVariable(REDIS_ADDRESS);
|
||||
if (string.IsNullOrEmpty(redis))
|
||||
{
|
||||
Console.WriteLine("Redis cache host(hostname+port) was not specified. It should be specified via command line or REDIS_ADDRESS environment variable.");
|
||||
return -1;
|
||||
}
|
||||
cartStore = new RedisCartStore(redis);
|
||||
return StartServer(hostname, port, cartStore);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Redis cache host(hostname+port) was not specified. Starting a cart service using local store");
|
||||
Console.WriteLine("If you wanted to use Redis Cache as a backup store, you should provide its address via command line or REDIS_ADDRESS environment variable.");
|
||||
cartStore = new LocalCartStore();
|
||||
}
|
||||
|
||||
return StartServer(hostname, port, redis);
|
||||
return StartServer(hostname, port, cartStore);
|
||||
},
|
||||
errs => 1);
|
||||
break;
|
||||
|
@ -119,5 +125,22 @@ namespace cartservice
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReadRedisAddress(string address)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(address))
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Reading redis cache address from environment variable {REDIS_ADDRESS}");
|
||||
string redis = Environment.GetEnvironmentVariable(REDIS_ADDRESS);
|
||||
if (!string.IsNullOrEmpty(redis))
|
||||
{
|
||||
return redis;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,13 @@ namespace cartservice.cartstore
|
|||
// Maps between user and their cart
|
||||
private ConcurrentDictionary<string, Hipstershop.Cart> userCartItems = new ConcurrentDictionary<string, Hipstershop.Cart>();
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
Console.WriteLine("Local Cart Store was initialized");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task AddItemAsync(string userId, string productId, int quantity)
|
||||
{
|
||||
Console.WriteLine($"AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity}");
|
||||
|
|
|
@ -13,9 +13,10 @@ namespace cartservice.cartstore
|
|||
{
|
||||
private const string CART_FIELD_NAME = "cart";
|
||||
|
||||
private readonly ConnectionMultiplexer redis;
|
||||
private static ConnectionMultiplexer redis;
|
||||
|
||||
private readonly byte[] emptyCartBytes;
|
||||
private readonly string connectionString;
|
||||
|
||||
public RedisCartStore(string redisAddress)
|
||||
{
|
||||
|
@ -23,9 +24,15 @@ namespace cartservice.cartstore
|
|||
var cart = new Hipstershop.Cart();
|
||||
emptyCartBytes = cart.ToByteArray();
|
||||
|
||||
string connectionString = $"{redisAddress},ssl=false,allowAdmin=true";
|
||||
connectionString = $"{redisAddress},ssl=false,allowAdmin=true";
|
||||
Console.WriteLine($"Going to use Redis cache at this address: {connectionString}");
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
Console.WriteLine("Connecting to Redis: " + connectionString);
|
||||
redis = ConnectionMultiplexer.Connect(connectionString);
|
||||
redis = await ConnectionMultiplexer.ConnectAsync(connectionString, Console.Out);
|
||||
Console.WriteLine("Connected successfully to Redis");
|
||||
}
|
||||
|
||||
public async Task AddItemAsync(string userId, string productId, int quantity)
|
||||
|
|
|
@ -4,6 +4,8 @@ namespace cartservice.interfaces
|
|||
{
|
||||
internal interface ICartStore
|
||||
{
|
||||
Task InitializeAsync();
|
||||
|
||||
Task AddItemAsync(string userId, string productId, int quantity);
|
||||
Task EmptyCartAsync(string userId);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ GOTO End1
|
|||
:local
|
||||
set REDIS_PORT=6379
|
||||
set REDIS_ADDR=localhost:%REDIS_PORT%
|
||||
set LISTEN_ADDR=127.0.0.1
|
||||
set LISTEN_ADDR=0.0.0.0
|
||||
set PORT=7070
|
||||
|
||||
echo running redis emulator locally on a separate window
|
||||
|
@ -23,12 +23,12 @@ GOTO End1
|
|||
|
||||
:docker_local
|
||||
set REDIS_PORT=6379
|
||||
set REDIS_ADDR=redis:%REDIS_PORT%
|
||||
set LISTEN_ADDR=127.0.0.1
|
||||
set REDIS_ADDR=0.0.0.0:%REDIS_PORT%
|
||||
set LISTEN_ADDR=0.0.0.0
|
||||
set PORT=7070
|
||||
|
||||
echo run docker container with redis
|
||||
docker run -d --name=redis -p %REDIS_PORT%:%REDIS_PORT% redis
|
||||
start docker run -d --name=redis -p %REDIS_PORT%:%REDIS_PORT% redis
|
||||
|
||||
echo building container image for cart service
|
||||
docker build -t cartservice ..\.
|
||||
|
|
Loading…
Reference in a new issue