Merge branch 'master' of sso://user/ahmetb/microservices-demo
This commit is contained in:
commit
91663aa541
18 changed files with 2750 additions and 55 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,3 +1,6 @@
|
||||||
|
bin/
|
||||||
|
pkg/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
*.pyc
|
||||||
*.swp
|
*.swp
|
||||||
*~
|
*~
|
||||||
|
|
28
.vscode/launch.json
vendored
Normal file
28
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||||
|
// Use hover for the description of the existing attributes
|
||||||
|
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": ".NET Core Launch (console)",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build",
|
||||||
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
|
"program": "${workspaceFolder}/src/cartservice/bin/Debug/netcoreapp2.0/cartservice.dll",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}/src/cartservice",
|
||||||
|
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
|
||||||
|
"console": "internalConsole",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"internalConsoleOptions": "openOnSessionStart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ".NET Core Attach",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach",
|
||||||
|
"processId": "${command:pickProcess}"
|
||||||
|
}
|
||||||
|
,]
|
||||||
|
}
|
15
.vscode/tasks.json
vendored
Normal file
15
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "build",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"${workspaceFolder}/src/cartservice/cartservice.csproj"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
3
src/cartservice/.gitignore
vendored
Normal file
3
src/cartservice/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/bin/*
|
||||||
|
/obj/*
|
||||||
|
.vs/*.*
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
41
src/cartservice/cartstore/LocalCartStore.cs
Normal file
41
src/cartservice/cartstore/LocalCartStore.cs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using cartservice.interfaces;
|
||||||
|
|
||||||
|
namespace cartservice.cartstore
|
||||||
|
{
|
||||||
|
internal class LocalCartStore
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
src/cartservice/cartstore/RedisCartStore.cs
Normal file
74
src/cartservice/cartstore/RedisCartStore.cs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using cartservice.interfaces;
|
||||||
|
using Google.Protobuf;
|
||||||
|
using Hipstershop;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
|
||||||
|
namespace cartservice.cartstore
|
||||||
|
{
|
||||||
|
public class RedisCartStore : ICartStore
|
||||||
|
{
|
||||||
|
private const string CART_FIELD_NAME = "cart";
|
||||||
|
|
||||||
|
private readonly ConnectionMultiplexer redis;
|
||||||
|
|
||||||
|
private readonly byte[] emptyCartBytes;
|
||||||
|
|
||||||
|
public RedisCartStore(string redisAddress)
|
||||||
|
{
|
||||||
|
// Serialize empty cart into byte array.
|
||||||
|
var cart = new Hipstershop.Cart();
|
||||||
|
emptyCartBytes = cart.ToByteArray();
|
||||||
|
|
||||||
|
string connectionString = $"{redisAddress},ssl=false,allowAdmin=true";
|
||||||
|
Console.WriteLine("Connecting to Redis: " + connectionString);
|
||||||
|
redis = ConnectionMultiplexer.Connect(connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddItemAsync(string userId, string productId, int quantity)
|
||||||
|
{
|
||||||
|
var db = redis.GetDatabase();
|
||||||
|
|
||||||
|
// Access the cart from the cache
|
||||||
|
var value = await db.HashGetAsync(userId, CART_FIELD_NAME);
|
||||||
|
|
||||||
|
Hipstershop.Cart cart;
|
||||||
|
if (value.IsNull)
|
||||||
|
{
|
||||||
|
cart = new Hipstershop.Cart();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cart = Hipstershop.Cart.Parser.ParseFrom(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
cart.Items.Add(new Hipstershop.CartItem { ProductId = productId, Quantity = quantity });
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task EmptyCartAsync(string userId)
|
||||||
|
{
|
||||||
|
var db = redis.GetDatabase();
|
||||||
|
|
||||||
|
// Update the cache with empty cart for given user
|
||||||
|
await db.HashSetAsync(userId, new[] { new HashEntry(CART_FIELD_NAME, emptyCartBytes) });
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Hipstershop.Cart> GetCartAsync(string userId)
|
||||||
|
{
|
||||||
|
var db = redis.GetDatabase();
|
||||||
|
|
||||||
|
// Access the cart from the cache
|
||||||
|
var value = await db.HashGetAsync(userId, CART_FIELD_NAME);
|
||||||
|
|
||||||
|
Hipstershop.Cart cart = null;
|
||||||
|
if (!value.IsNull)
|
||||||
|
{
|
||||||
|
cart = Hipstershop.Cart.Parser.ParseFrom(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
src/cartservice/interfaces/ICartStore.cs
Normal file
12
src/cartservice/interfaces/ICartStore.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace cartservice.interfaces
|
||||||
|
{
|
||||||
|
internal interface ICartStore
|
||||||
|
{
|
||||||
|
Task AddItemAsync(string userId, string productId, int quantity);
|
||||||
|
Task EmptyCartAsync(string userId);
|
||||||
|
|
||||||
|
Task<Hipstershop.Cart> GetCartAsync(string userId);
|
||||||
|
}
|
||||||
|
}
|
11
src/cartservice/run_redis_emulator_windows.bat
Normal file
11
src/cartservice/run_redis_emulator_windows.bat
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
@echo off
|
||||||
|
rem install redis on windows using choco
|
||||||
|
rem choco install redis-64
|
||||||
|
|
||||||
|
rem run redis
|
||||||
|
redis-server --daemonize yes
|
||||||
|
|
||||||
|
rem testing locally
|
||||||
|
rem redis-cli
|
||||||
|
rem SET foo bar
|
||||||
|
rem GET foo
|
13
src/checkoutservice/Dockerfile
Normal file
13
src/checkoutservice/Dockerfile
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
FROM golang:1.10-alpine as builder
|
||||||
|
RUN apk add --no-cache ca-certificates git
|
||||||
|
WORKDIR /src/microservices-demo/catalogservice
|
||||||
|
COPY . .
|
||||||
|
RUN go get -d ./...
|
||||||
|
RUN go build -o /catalogservice .
|
||||||
|
|
||||||
|
FROM alpine as release
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
ca-certificates
|
||||||
|
COPY --from=builder /catalogservice /catalogservice
|
||||||
|
EXPOSE 5000
|
||||||
|
ENTRYPOINT /catalogservice
|
6
src/checkoutservice/genproto.sh
Executable file
6
src/checkoutservice/genproto.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
PATH=$PATH:$GOPATH/bin
|
||||||
|
protodir=../../pb
|
||||||
|
|
||||||
|
protoc --go_out=plugins=grpc:genproto -I $protodir $protodir/demo.proto
|
2393
src/checkoutservice/genproto/demo.pb.go
Normal file
2393
src/checkoutservice/genproto/demo.pb.go
Normal file
File diff suppressed because it is too large
Load diff
93
src/checkoutservice/main.go
Normal file
93
src/checkoutservice/main.go
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
|
pb "./genproto"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
listenPort = "5000"
|
||||||
|
)
|
||||||
|
|
||||||
|
type checkoutService struct {
|
||||||
|
productCatalogSvcAddr string
|
||||||
|
cartSvcAddr string
|
||||||
|
currencySvcAddr string
|
||||||
|
shippingSvcAddr string
|
||||||
|
emailSvcAddr string
|
||||||
|
paymentSvcAddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
port := listenPort
|
||||||
|
if os.Getenv("PORT") != "" {
|
||||||
|
port = os.Getenv("PORT")
|
||||||
|
}
|
||||||
|
|
||||||
|
svc := new(checkoutService)
|
||||||
|
mustMapEnv(&svc.shippingSvcAddr, "SHIPPING_SERVICE_ADDR")
|
||||||
|
// mustMapEnv(&svc.productCatalogSvcAddr, "PRODUCT_CATALOG_SERVICE_ADDR")
|
||||||
|
// mustMapEnv(&svc.cartSvcAddr, "CART_SERVICE_ADDR")
|
||||||
|
// mustMapEnv(&svc.currencySvcAddr, "CURRENCY_SERVICE_ADDR")
|
||||||
|
// mustMapEnv(&svc.emailSvcAddr, "EMAIL_SERVICE_ADDR")
|
||||||
|
// mustMapEnv(&svc.paymentSvcAddr, "PAYMENT_SERVICE_ADDR")
|
||||||
|
|
||||||
|
log.Printf("service config: %+v", svc)
|
||||||
|
|
||||||
|
lis, err := net.Listen("tcp", fmt.Sprintf(":%s", port))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
srv := grpc.NewServer()
|
||||||
|
pb.RegisterCheckoutServiceServer(srv, svc)
|
||||||
|
log.Printf("starting to listen on tcp: %q", lis.Addr().String())
|
||||||
|
log.Fatal(srv.Serve(lis))
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustMapEnv(target *string, envKey string) {
|
||||||
|
v := os.Getenv(envKey)
|
||||||
|
if v == "" {
|
||||||
|
panic(fmt.Sprintf("environment variable %q not set", envKey))
|
||||||
|
}
|
||||||
|
*target = v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *checkoutService) CreateOrder(ctx context.Context, req *pb.CreateOrderRequest) (*pb.CreateOrderResponse, error) {
|
||||||
|
log.Printf("[CreateOrder] user_id=%q user_currency=%q", req.UserId, req.UserCurrency)
|
||||||
|
resp := new(pb.CreateOrderResponse)
|
||||||
|
conn, err := grpc.Dial(cs.shippingSvcAddr, grpc.WithInsecure())
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Unavailable, "could not connect shippping service: %+v", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
shippingQuote, err := pb.NewShippingServiceClient(conn).
|
||||||
|
GetQuote(ctx, &pb.GetQuoteRequest{
|
||||||
|
Address: req.Address,
|
||||||
|
Items: nil}) // TODO(ahmetb): query CartService for items
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Unavailable, "failed to get shipping quote: %+v", err)
|
||||||
|
}
|
||||||
|
resp.ShippingCost = &pb.Money{
|
||||||
|
Amount: shippingQuote.GetCostUsd(),
|
||||||
|
CurrencyCode: "USD", // TOD(ahmetb) convert to req.UserCurrency
|
||||||
|
}
|
||||||
|
// TODO(ahmetb) calculate resp.OrderItem with req.UserCurrency
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderRequest) (*pb.PlaceOrderResponse, error) {
|
||||||
|
log.Printf("[PlaceOrder] user_id=%q user_currency=%q", req.UserId, req.UserCurrency)
|
||||||
|
resp := new(pb.PlaceOrderResponse)
|
||||||
|
return resp, nil
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ RUN apk add --no-cache \
|
||||||
WORKDIR /src/microservices-demo/productcatalogservice
|
WORKDIR /src/microservices-demo/productcatalogservice
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN go get -d ./...
|
RUN go get -d ./...
|
||||||
RUN go build -v -o /productcatalogservice .
|
RUN go build -o /productcatalogservice .
|
||||||
|
|
||||||
FROM alpine as release
|
FROM alpine as release
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
# script to compile python protos
|
# script to compile python protos
|
||||||
#
|
#
|
||||||
# requires gRPC tools:
|
# requires gRPC tools:
|
|
@ -5,7 +5,7 @@ RUN apk add --no-cache \
|
||||||
WORKDIR /src/microservices-demo/shippingservice
|
WORKDIR /src/microservices-demo/shippingservice
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN go get -d ./...
|
RUN go get -d ./...
|
||||||
RUN go build -v -o /shippingservice .
|
RUN go build -o /shippingservice .
|
||||||
|
|
||||||
FROM alpine as release
|
FROM alpine as release
|
||||||
COPY --from=builder /shippingservice /shippingservice
|
COPY --from=builder /shippingservice /shippingservice
|
||||||
|
|
Loading…
Reference in a new issue