Fixing cache implementation
This commit is contained in:
parent
3262ff82b0
commit
c3c76effea
8 changed files with 99 additions and 86 deletions
|
@ -32,54 +32,9 @@ namespace cartservice
|
|||
return Empty;
|
||||
}
|
||||
|
||||
public async override Task<Hipstershop.Cart> GetCart(GetCartRequest request, ServerCallContext context)
|
||||
public override Task<Hipstershop.Cart> GetCart(GetCartRequest request, ServerCallContext context)
|
||||
{
|
||||
return await cartStore.GetCartAsync(request.UserId);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class CartUtils
|
||||
{
|
||||
public static Hipstershop.Cart ToHipsterCart(this Cart cart)
|
||||
{
|
||||
var hipsterCart = new Hipstershop.Cart
|
||||
{
|
||||
UserId = cart.UserId,
|
||||
Items = { cart.Items.Select(i => new CartItem { ProductId = i.Key, Quantity = i.Value }) }
|
||||
};
|
||||
return hipsterCart;
|
||||
}
|
||||
}
|
||||
|
||||
// Actual implementation of the cart
|
||||
internal class Cart
|
||||
{
|
||||
// Maps between productId and its quantity
|
||||
private Dictionary<string, int> cart = new Dictionary<string, int>();
|
||||
|
||||
public Cart(string userId)
|
||||
{
|
||||
UserId = userId;
|
||||
}
|
||||
|
||||
public string UserId { get; set; }
|
||||
|
||||
public void AddItem(string productId, int quantity)
|
||||
{
|
||||
cart.Add(productId, quantity);
|
||||
}
|
||||
|
||||
public void EmptyCart()
|
||||
{
|
||||
cart.Clear();
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, int> Items
|
||||
{
|
||||
get
|
||||
{
|
||||
return cart;
|
||||
}
|
||||
return cartStore.GetCartAsync(request.UserId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ namespace cartservice
|
|||
// 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(() =>
|
||||
{
|
||||
//var store = new LocalCartStore();
|
||||
var store = new RedisCartStore(redisAddress);
|
||||
Server server = new Server
|
||||
{
|
||||
|
@ -50,8 +51,6 @@ namespace cartservice
|
|||
{
|
||||
Thread.Sleep(TimeSpan.FromMinutes(10));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
|
|
|
@ -1,41 +1,52 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks;
|
||||
using cartservice.interfaces;
|
||||
using Hipstershop;
|
||||
|
||||
namespace cartservice.cartstore
|
||||
{
|
||||
internal class LocalCartStore
|
||||
internal class LocalCartStore : ICartStore
|
||||
{
|
||||
// Maps between user and their cart
|
||||
private ConcurrentDictionary<string, Cart> userCartItems = new ConcurrentDictionary<string, Cart>();
|
||||
private ConcurrentDictionary<string, Hipstershop.Cart> userCartItems = new ConcurrentDictionary<string, Hipstershop.Cart>();
|
||||
|
||||
public void AddItem(string userId, string productId, int quantity)
|
||||
public Task AddItemAsync(string userId, string productId, int quantity)
|
||||
{
|
||||
Cart cart;
|
||||
Console.WriteLine($"AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity}");
|
||||
var newCart = new Hipstershop.Cart
|
||||
{
|
||||
UserId = userId,
|
||||
Items = { new Hipstershop.CartItem { ProductId = productId, Quantity = quantity } }
|
||||
};
|
||||
userCartItems.AddOrUpdate(userId, newCart,
|
||||
(k, exVal) =>
|
||||
{
|
||||
// Currently we assume that we only add to the cart
|
||||
exVal.Items.Add(new Hipstershop.CartItem { ProductId = productId, Quantity = quantity });
|
||||
return exVal;
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task EmptyCartAsync(string userId)
|
||||
{
|
||||
Console.WriteLine($"EmptyCartAsync called with userId={userId}");
|
||||
userCartItems[userId] = new Hipstershop.Cart();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<Hipstershop.Cart> GetCartAsync(string userId)
|
||||
{
|
||||
Console.WriteLine($"GetCartAsync called with userId={userId}");
|
||||
Hipstershop.Cart cart = null;
|
||||
if (!userCartItems.TryGetValue(userId, out cart))
|
||||
{
|
||||
cart = new Cart(userId);
|
||||
Console.WriteLine($"No carts for user {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;
|
||||
return Task.FromResult(cart);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,6 +29,8 @@ namespace cartservice.cartstore
|
|||
|
||||
public async Task AddItemAsync(string userId, string productId, int quantity)
|
||||
{
|
||||
Console.WriteLine($"AddItemAsync called with userId={userId}, productId={productId}, quantity={quantity}");
|
||||
|
||||
var db = redis.GetDatabase();
|
||||
|
||||
// Access the cart from the cache
|
||||
|
@ -44,11 +46,15 @@ namespace cartservice.cartstore
|
|||
cart = Hipstershop.Cart.Parser.ParseFrom(value);
|
||||
}
|
||||
|
||||
cart.UserId = userId;
|
||||
cart.Items.Add(new Hipstershop.CartItem { ProductId = productId, Quantity = quantity });
|
||||
await db.HashSetAsync(userId, new[]{ new HashEntry(CART_FIELD_NAME, cart.ToByteArray()) });
|
||||
}
|
||||
|
||||
public async Task EmptyCartAsync(string userId)
|
||||
{
|
||||
Console.WriteLine($"EmptyCartAsync called with userId={userId}");
|
||||
|
||||
var db = redis.GetDatabase();
|
||||
|
||||
// Update the cache with empty cart for given user
|
||||
|
@ -57,6 +63,7 @@ namespace cartservice.cartstore
|
|||
|
||||
public async Task<Hipstershop.Cart> GetCartAsync(string userId)
|
||||
{
|
||||
Console.WriteLine($"GetCartAsync called with userId={userId}");
|
||||
var db = redis.GetDatabase();
|
||||
|
||||
// Access the cart from the cache
|
||||
|
|
|
@ -8,6 +8,9 @@ set CART_SERVICE_PORT=7070
|
|||
rem run docker container with redis
|
||||
rem docker run -d --name=redis -p %REDIS_PORT%:%REDIS_PORT% redis:alpine
|
||||
|
||||
rem running locally
|
||||
dotnet build ..\.
|
||||
dotnet run --project ../cartservice.csproj start
|
||||
rem run docker container with cart service
|
||||
docker run -it --rm -e REDIS_ADDR=%REDIS_ADDR%:%REDIS_PORT% -e CART_SERVICE_ADDR=%CART_SERVICE_ADDR% -e CART_SERVICE_PORT=%CART_SERVICE_PORT% -p %CART_SERVICE_PORT%:%CART_SERVICE_PORT% cartservice
|
||||
rem -e GRPC_TRACE=all -e GRPC_VERBOSITY=debug
|
||||
rem docker run -it --rm -e REDIS_ADDR=%REDIS_ADDR%:%REDIS_PORT% -e CART_SERVICE_ADDR=%CART_SERVICE_ADDR% -e CART_SERVICE_PORT=%CART_SERVICE_PORT% -p %CART_SERVICE_PORT%:%CART_SERVICE_PORT% cartservice
|
||||
rem -e GRPC_TRACE=all -e GRPC_VERBOSITY=debug
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue