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:
Simon Zeltser 2018-06-28 17:12:33 -07:00
parent 07bb077c10
commit ca6e6647ef
5 changed files with 63 additions and 24 deletions

View file

@ -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;
}
}
}

View file

@ -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}");

View file

@ -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)

View file

@ -4,6 +4,8 @@ namespace cartservice.interfaces
{
internal interface ICartStore
{
Task InitializeAsync();
Task AddItemAsync(string userId, string productId, int quantity);
Task EmptyCartAsync(string userId);

View file

@ -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 ..\.