Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ScalarDB .NET Client] Add microservice transactions sample with Shared-cluster pattern with LINQ #72

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
406 changes: 403 additions & 3 deletions .gitignore

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**/bin/
**/obj/
**/.DS_Store
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<RootNamespace>MicroserviceTransactionsSample.Client</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Grpc.Net.Client" Version="2.66.0"/>
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.66.0"/>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1"/>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0"/>
</ItemGroup>
<ItemGroup>
<None Remove="Commands\"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Rpc\Rpc.csproj"/>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.CommandLine.Binding;
using Grpc.Net.Client;
using static MicroserviceTransactionsSample.Rpc.CustomerService;

namespace MicroserviceTransactionsSample.Client.Commands.Binders;

public class CustomerServiceClientBinder : BinderBase<CustomerServiceClient>
{
private const string CustomerServiceUrl = "http://localhost:10010";

protected override CustomerServiceClient GetBoundValue(BindingContext bindingContext)
{
var customerServiceUrl = Environment.GetEnvironmentVariable("CUSTOMER_SERVICE_URL");
if (String.IsNullOrEmpty(customerServiceUrl))
customerServiceUrl = CustomerServiceUrl;

var grpcOptions = new GrpcChannelOptions { LoggerFactory = Logging.GetLoggerFactory() };
var grpcChannel = GrpcChannel.ForAddress(customerServiceUrl, grpcOptions);

return new CustomerServiceClient(grpcChannel);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.CommandLine.Binding;
using Grpc.Net.Client;
using static MicroserviceTransactionsSample.Rpc.OrderService;

namespace MicroserviceTransactionsSample.Client.Commands.Binders;

public class OrderServiceClientBinder : BinderBase<OrderServiceClient>
{
private const string OrderServiceUrl = "http://localhost:10020";

protected override OrderServiceClient GetBoundValue(BindingContext bindingContext)
{
var orderServiceUrl = Environment.GetEnvironmentVariable("ORDER_SERVICE_URL");
if (String.IsNullOrEmpty(orderServiceUrl))
orderServiceUrl = OrderServiceUrl;

var grpcOptions = new GrpcChannelOptions { LoggerFactory = Logging.GetLoggerFactory() };
var grpcChannel = GrpcChannel.ForAddress(orderServiceUrl, grpcOptions);

return new OrderServiceClient(grpcChannel);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.CommandLine;
using MicroserviceTransactionsSample.Client.Commands.Binders;
using MicroserviceTransactionsSample.Rpc;
using static MicroserviceTransactionsSample.Rpc.CustomerService;

namespace MicroserviceTransactionsSample.Client.Commands;

public static class GetCustomerInfoCommand
{
private const string Name = "GetCustomerInfo";
private const string Description = "Get customer information";

private const string ArgName = "id";
private const string ArgDescription = "customer ID";

public static Command Create()
{
var customerIdArg = new Argument<int>(ArgName, ArgDescription);
var getCustomerInfoCommand = new Command(Name, Description)
{
customerIdArg
};

getCustomerInfoCommand.SetHandler(getCustomerInfo,
customerIdArg,
new CustomerServiceClientBinder());
return getCustomerInfoCommand;
}

private static async Task getCustomerInfo(int customerId, CustomerServiceClient client)
{
var request = new GetCustomerInfoRequest { CustomerId = customerId };
var response = await client.GetCustomerInfoAsync(request);

Console.WriteLine(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.CommandLine;
using MicroserviceTransactionsSample.Client.Commands.Binders;
using MicroserviceTransactionsSample.Rpc;
using static MicroserviceTransactionsSample.Rpc.OrderService;

namespace MicroserviceTransactionsSample.Client.Commands;

public static class GetOrderCommand
{
private const string Name = "GetOrder";
private const string Description = "Get order information by order ID";

private const string ArgName = "id";
private const string ArgDescription = "order ID";

public static Command Create()
{
var orderIdArg = new Argument<string>(ArgName, ArgDescription);
var getOrderCommand = new Command(Name, Description)
{
orderIdArg
};

getOrderCommand.SetHandler(getOrder,
orderIdArg,
new OrderServiceClientBinder());
return getOrderCommand;
}

private static async Task getOrder(string orderId, OrderServiceClient client)
{
var request = new GetOrderRequest { OrderId = orderId };
var response = await client.GetOrderAsync(request);

Console.WriteLine(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.CommandLine;
using MicroserviceTransactionsSample.Client.Commands.Binders;
using MicroserviceTransactionsSample.Rpc;
using static MicroserviceTransactionsSample.Rpc.OrderService;

namespace MicroserviceTransactionsSample.Client.Commands;

public static class GetOrdersCommand
{
private const string Name = "GetOrders";
private const string Description = "Get orders information by customer ID";
Dima-X marked this conversation as resolved.
Show resolved Hide resolved

private const string ArgName = "customer_id";
private const string ArgDescription = "customer ID";

public static Command Create()
{
var customerIdArg = new Argument<int>(ArgName, ArgDescription);
var getOrdersCommand = new Command(Name, Description)
{
customerIdArg
};

getOrdersCommand.SetHandler(getOrders,
customerIdArg,
new OrderServiceClientBinder());
return getOrdersCommand;
}

private static async Task getOrders(int customerId, OrderServiceClient client)
{
var request = new GetOrdersRequest { CustomerId = customerId };
var response = await client.GetOrdersAsync(request);

Console.WriteLine(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.CommandLine;
using MicroserviceTransactionsSample.Client.Commands.Binders;
using MicroserviceTransactionsSample.Rpc;
using Microsoft.Extensions.DependencyInjection;
using static MicroserviceTransactionsSample.Rpc.OrderService;

namespace MicroserviceTransactionsSample.Client.Commands;

public static class PlaceOrderCommand
{
private const string Name = "PlaceOrder";
private const string Description = "Place an order";

private const string ArgName1 = "customer_id";
private const string ArgDescription1 = "customer ID";
private const string ArgName2 = "orders";
private const string ArgDescription2 = "orders. The format is \"<Item ID>:<Count>,<Item ID>:<Count>,...\"";

public static Command Create()
{
var customerIdArg = new Argument<int>(ArgName1, ArgDescription1);
var ordersArg = new Argument<Dictionary<int, int>>(
name: ArgName2,
parse: arg =>
{
var argStr = arg.Tokens.First().Value;
var orders = argStr
.Split(',')
.Select(s => s.Split(':'))
.ToDictionary(
s => Int32.Parse(s[0]),
s => Int32.Parse(s[1])
);

return orders;
},
description: ArgDescription2)
{
Arity = ArgumentArity.ExactlyOne
};

var placeOrderCommand = new Command(Name, Description)
{
customerIdArg,
ordersArg
};

placeOrderCommand.SetHandler(placeOrder,
customerIdArg,
ordersArg,
new OrderServiceClientBinder());
return placeOrderCommand;
}

private static async Task placeOrder(int customerId,
Dictionary<int, int> orders,
OrderServiceClient client)
{
var request = new PlaceOrderRequest { CustomerId = customerId };
foreach (var order in orders)
request.ItemOrder.Add(new ItemOrder { ItemId = order.Key, Count = order.Value });

var response = await client.PlaceOrderAsync(request);

Console.WriteLine(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.CommandLine;
using MicroserviceTransactionsSample.Client.Commands.Binders;
using MicroserviceTransactionsSample.Rpc;
using static MicroserviceTransactionsSample.Rpc.CustomerService;

namespace MicroserviceTransactionsSample.Client.Commands;

public static class RepaymentCommand
{
private const string Name = "Repayment";
private const string Description = "Make a repayment";

private const string ArgName1 = "customer_id";
private const string ArgDescription1 = "customer ID";
private const string ArgName2 = "amount";
private const string ArgDescription2 = "repayment amount";

public static Command Create()
{
var customerIdArg = new Argument<int>(ArgName1, ArgDescription1);
var amountArg = new Argument<int>(ArgName2, ArgDescription2);
var repaymentCommand = new Command(Name, Description)
{
customerIdArg,
amountArg
};

repaymentCommand.SetHandler(repay,
customerIdArg,
amountArg,
new CustomerServiceClientBinder());
return repaymentCommand;
}

private static async Task repay(int customerId, int amount, CustomerServiceClient client)
{
var request = new RepaymentRequest { CustomerId = customerId, Amount = amount };
var response = await client.RepaymentAsync(request);

Console.WriteLine(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Microsoft.Extensions.Logging;

namespace MicroserviceTransactionsSample.Client;

public static class Logging
{
public static ILoggerFactory GetLoggerFactory()
=> LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Warning);
builder.AddSimpleConsole(options => { options.TimestampFormat = "HH:mm:ss "; });
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.CommandLine;
using MicroserviceTransactionsSample.Client.Commands;

namespace MicroserviceTransactionsSample.Client;

class Program
{
static async Task Main(string[] args)
{
var rootCommand = new RootCommand("MicroserviceTransactionsSample.Client")
{
GetCustomerInfoCommand.Create(),
GetOrderCommand.Create(),
GetOrdersCommand.Create(),
PlaceOrderCommand.Create(),
RepaymentCommand.Create()
};

await rootCommand.InvokeAsync(args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>MicroserviceTransactionsSample.Common</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ScalarDB.Client" Version="3.13.0"/>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations.Schema;
using ScalarDB.Client.DataAnnotations;

namespace MicroserviceTransactionsSample.Common.CustomerService;

[Table("customer_service.customers")]
public class Customer
{
[PartitionKey]
[Column("customer_id", Order = 0)]
public int Id { get; set; }

[Column("name", Order = 1)]
public string Name { get; set; } = "";

[Column("credit_limit", Order = 2)]
public int CreditLimit { get; set; }

[Column("credit_total", Order = 3)]
public int CreditTotal { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Grpc.Core;

namespace MicroserviceTransactionsSample.Common;

public class FailedPreconditionException : RpcException
{
public FailedPreconditionException(string message)
: base(new Status(StatusCode.FailedPrecondition, message))
{ }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Grpc.Core;

namespace MicroserviceTransactionsSample.Common;

public class InternalException : RpcException
{
public InternalException(string message, Exception? innerEx)
: base(new Status(StatusCode.Internal, message, innerEx))
{ }
}
Loading