command line arguments handling

This commit is contained in:
Simon Zeltser 2018-06-21 11:10:13 -07:00
parent 8860d8bfdd
commit 0ce195bb80
3 changed files with 53 additions and 53 deletions

View file

@ -2,6 +2,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using cartservice.interfaces;
using Grpc.Core; using Grpc.Core;
using Hipstershop; using Hipstershop;
using static Hipstershop.CartService; using static Hipstershop.CartService;
@ -11,65 +12,29 @@ namespace cartservice
// Cart wrapper to deal with grpc communication // Cart wrapper to deal with grpc communication
internal class CartServiceImpl : CartServiceBase internal class CartServiceImpl : CartServiceBase
{ {
private CartStore cartStore; private ICartStore cartStore;
private readonly static Empty Empty = new Empty();
public CartServiceImpl(CartStore cartStore) public CartServiceImpl(ICartStore cartStore)
{ {
this.cartStore = cartStore; this.cartStore = cartStore;
} }
public override Task<Empty> AddItem(AddItemRequest request, Grpc.Core.ServerCallContext context) public async override Task<Empty> AddItem(AddItemRequest request, Grpc.Core.ServerCallContext context)
{ {
cartStore.AddItem(request.UserId, request.Item.ProductId, request.Item.Quantity); await cartStore.AddItemAsync(request.UserId, request.Item.ProductId, request.Item.Quantity);
return Task.FromResult(new Empty()); return Empty;
} }
public override Task<Empty> EmptyCart(EmptyCartRequest request, ServerCallContext context) public async override Task<Empty> EmptyCart(EmptyCartRequest request, ServerCallContext context)
{ {
cartStore.EmptyCart(request.UserId); await cartStore.EmptyCartAsync(request.UserId);
return Task.FromResult(new Empty()); return Empty;
} }
public override Task<Hipstershop.Cart> GetCart(GetCartRequest request, ServerCallContext context) public async override Task<Hipstershop.Cart> GetCart(GetCartRequest request, ServerCallContext context)
{ {
var cart = cartStore.GetCart(request.UserId); return await cartStore.GetCartAsync(request.UserId);
return Task.FromResult(cart.ToHipsterCart());
}
}
internal class CartStore
{
// Maps between user and their cart
private ConcurrentDictionary<string, Cart> userCartItems = new ConcurrentDictionary<string, Cart>();
public void AddItem(string userId, string productId, int quantity)
{
Cart cart;
if (!userCartItems.TryGetValue(userId, out cart))
{
cart = new Cart(userId);
}
else
{
cart = userCartItems[userId];
}
cart.AddItem(productId, quantity);
}
public void EmptyCart(string userId)
{
Cart cart;
if (userCartItems.TryGetValue(userId, out cart))
{
cart.EmptyCart();
}
}
public Cart GetCart(string userId)
{
Cart cart = null;
userCartItems.TryGetValue(userId, out cart);
return cart;
} }
} }

View file

@ -1,29 +1,41 @@
using System; using System;
using System.IO;
using cartservice.cartstore;
using CommandLine; using CommandLine;
using Grpc.Core; using Grpc.Core;
using Microsoft.Extensions.Configuration;
namespace cartservice namespace cartservice
{ {
class Program class Program
{ {
const string CART_SERVICE_ADDRESS = "CART_SERVICE_ADDR";
const string REDIS_ADDRESS = "REDIS_ADDR";
[Verb("start", HelpText = "Starts the server listening on provided port")] [Verb("start", HelpText = "Starts the server listening on provided port")]
class ServerOptions class ServerOptions
{ {
[Option('h', "hostname", HelpText = "The ip on which the server is running. If not provided, CART_SERVICE_ADDR environment variable value will be used. If not defined, localhost is used")]
public string Host { get; set; }
[Option('p', "port", HelpText = "The port on for running the server", Required = true)] [Option('p', "port", HelpText = "The port on for running the server", Required = true)]
public int Port { get; set; } public int Port { get; set; }
[Option('r', "redis", HelpText = "The ip of redis cache")]
public string Redis { get; set; }
} }
static object StartServer(string host, int port) static object StartServer(string host, int port, string redisAddress)
{ {
var store = new CartStore(); var store = new RedisCartStore(redisAddress);
Server server = new Server Server server = new Server
{ {
Services = { Hipstershop.CartService.BindService(new CartServiceImpl(store)) }, Services = { Hipstershop.CartService.BindService(new CartServiceImpl(store)) },
Ports = { new ServerPort(host, port, ServerCredentials.Insecure) } Ports = { new ServerPort(host, port, ServerCredentials.Insecure) }
}; };
Console.WriteLine("Cart server is listening on port " + port); Console.WriteLine($"Cart server is listening at {host}:{port}");
Console.WriteLine("Press any key to stop the server..."); Console.WriteLine("Press any key to stop the server...");
server.Start(); server.Start();
@ -33,6 +45,7 @@ namespace cartservice
return null; return null;
} }
static void Main(string[] args) static void Main(string[] args)
{ {
if (args.Length == 0) if (args.Length == 0)
@ -45,15 +58,34 @@ namespace cartservice
{ {
case "start": case "start":
Parser.Default.ParseArguments<ServerOptions>(args).MapResult( Parser.Default.ParseArguments<ServerOptions>(args).MapResult(
(ServerOptions options) => StartServer("localhost", options.Port), (ServerOptions options) =>
{
string host = options.Host;
if (string.IsNullOrEmpty(host))
{
Console.WriteLine($"Reading host address from {CART_SERVICE_ADDRESS} environment variable...");
host = Environment.GetEnvironmentVariable(CART_SERVICE_ADDRESS);
if (string.IsNullOrEmpty(host))
{
Console.WriteLine("Setting the host to 127.0.0.1");
host = "127.0.0.1";
}
}
string redis = options.Redis;
if (string.IsNullOrEmpty(redis))
{
Console.WriteLine("Reading redis cache address from environment variable");
redis = Environment.GetEnvironmentVariable(REDIS_ADDRESS);
}
return StartServer(host, options.Port, redis);
},
errs => 1); errs => 1);
break; break;
default: default:
Console.WriteLine("Invalid command"); Console.WriteLine("Invalid command");
break; break;
} }
Console.WriteLine("Hello World!");
} }
} }
} }

View file

@ -11,6 +11,9 @@
<PackageReference Include="Google.Protobuf.Tools" Version="3.5.1" /> <PackageReference Include="Google.Protobuf.Tools" Version="3.5.1" />
<PackageReference Include="grpc" Version="1.12.0" /> <PackageReference Include="grpc" Version="1.12.0" />
<PackageReference Include="grpc.tools" Version="1.12.0" /> <PackageReference Include="grpc.tools" Version="1.12.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
<PackageReference Include="StackExchange.Redis" Version="1.2.6" />
</ItemGroup> </ItemGroup>
</Project> </Project>