♻️ Splitted wallet service
This commit is contained in:
@@ -4,7 +4,6 @@ using DysonNetwork.Pass.Credit;
|
||||
using DysonNetwork.Pass.Leveling;
|
||||
using DysonNetwork.Pass.Permission;
|
||||
using DysonNetwork.Pass.Realm;
|
||||
using DysonNetwork.Pass.Wallet;
|
||||
using DysonNetwork.Shared.Networking;
|
||||
|
||||
namespace DysonNetwork.Pass.Startup;
|
||||
@@ -38,8 +37,6 @@ public static class ApplicationConfiguration
|
||||
app.MapGrpcService<SocialCreditServiceGrpc>();
|
||||
app.MapGrpcService<ExperienceServiceGrpc>();
|
||||
app.MapGrpcService<BotAccountReceiverGrpc>();
|
||||
app.MapGrpcService<WalletServiceGrpc>();
|
||||
app.MapGrpcService<PaymentServiceGrpc>();
|
||||
app.MapGrpcService<RealmServiceGrpc>();
|
||||
app.MapGrpcReflectionService();
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using System.Text.Json;
|
||||
using DysonNetwork.Pass.Account;
|
||||
using DysonNetwork.Pass.Wallet;
|
||||
using DysonNetwork.Shared.Cache;
|
||||
using DysonNetwork.Shared.Models;
|
||||
using DysonNetwork.Shared.Proto;
|
||||
using DysonNetwork.Shared.Queue;
|
||||
using Google.Protobuf;
|
||||
using NATS.Client.Core;
|
||||
using NATS.Client.JetStream.Models;
|
||||
using NATS.Net;
|
||||
using NodaTime;
|
||||
|
||||
@@ -31,127 +29,7 @@ public class BroadcastEventHandler(
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
var paymentTask = HandlePaymentEventsAsync(stoppingToken);
|
||||
var webSocketTask = HandleWebSocketEventsAsync(stoppingToken);
|
||||
|
||||
await Task.WhenAll(paymentTask, webSocketTask);
|
||||
}
|
||||
|
||||
private async Task HandlePaymentEventsAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
var js = nats.CreateJetStreamContext();
|
||||
|
||||
await js.EnsureStreamCreated("payment_events", [PaymentOrderEventBase.Type]);
|
||||
|
||||
var consumer = await js.CreateOrUpdateConsumerAsync("payment_events",
|
||||
new ConsumerConfig("pass_payment_handler"),
|
||||
cancellationToken: stoppingToken);
|
||||
|
||||
await foreach (var msg in consumer.ConsumeAsync<byte[]>(cancellationToken: stoppingToken))
|
||||
{
|
||||
PaymentOrderEvent? evt = null;
|
||||
try
|
||||
{
|
||||
evt = JsonSerializer.Deserialize<PaymentOrderEvent>(msg.Data, GrpcTypeHelper.SerializerOptions);
|
||||
|
||||
logger.LogInformation(
|
||||
"Received order event: {ProductIdentifier} {OrderId}",
|
||||
evt?.ProductIdentifier,
|
||||
evt?.OrderId
|
||||
);
|
||||
|
||||
if (evt?.ProductIdentifier is null)
|
||||
continue;
|
||||
|
||||
// Handle subscription orders
|
||||
if (
|
||||
evt.ProductIdentifier.StartsWith(SubscriptionType.StellarProgram) &&
|
||||
evt.Meta?.TryGetValue("gift_id", out var giftIdValue) == true
|
||||
)
|
||||
{
|
||||
logger.LogInformation("Handling gift order: {OrderId}", evt.OrderId);
|
||||
|
||||
await using var scope = serviceProvider.CreateAsyncScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDatabase>();
|
||||
var subscriptions = scope.ServiceProvider.GetRequiredService<SubscriptionService>();
|
||||
|
||||
var order = await db.PaymentOrders.FindAsync(
|
||||
[evt.OrderId],
|
||||
cancellationToken: stoppingToken
|
||||
);
|
||||
if (order is null)
|
||||
{
|
||||
logger.LogWarning("Order with ID {OrderId} not found. Redelivering.", evt.OrderId);
|
||||
await msg.NakAsync(cancellationToken: stoppingToken);
|
||||
continue;
|
||||
}
|
||||
|
||||
await subscriptions.HandleGiftOrder(order);
|
||||
|
||||
logger.LogInformation("Gift for order {OrderId} handled successfully.", evt.OrderId);
|
||||
await msg.AckAsync(cancellationToken: stoppingToken);
|
||||
}
|
||||
else if (evt.ProductIdentifier.StartsWith(SubscriptionType.StellarProgram))
|
||||
{
|
||||
logger.LogInformation("Handling stellar program order: {OrderId}", evt.OrderId);
|
||||
|
||||
await using var scope = serviceProvider.CreateAsyncScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDatabase>();
|
||||
var subscriptions = scope.ServiceProvider.GetRequiredService<SubscriptionService>();
|
||||
|
||||
var order = await db.PaymentOrders.FindAsync(
|
||||
[evt.OrderId],
|
||||
cancellationToken: stoppingToken
|
||||
);
|
||||
if (order is null)
|
||||
{
|
||||
logger.LogWarning("Order with ID {OrderId} not found. Redelivering.", evt.OrderId);
|
||||
await msg.NakAsync(cancellationToken: stoppingToken);
|
||||
continue;
|
||||
}
|
||||
|
||||
await subscriptions.HandleSubscriptionOrder(order);
|
||||
|
||||
logger.LogInformation("Subscription for order {OrderId} handled successfully.", evt.OrderId);
|
||||
await msg.AckAsync(cancellationToken: stoppingToken);
|
||||
}
|
||||
else if (evt.ProductIdentifier == "lottery")
|
||||
{
|
||||
logger.LogInformation("Handling lottery order: {OrderId}", evt.OrderId);
|
||||
|
||||
await using var scope = serviceProvider.CreateAsyncScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDatabase>();
|
||||
var lotteries = scope.ServiceProvider.GetRequiredService<Lotteries.LotteryService>();
|
||||
|
||||
var order = await db.PaymentOrders.FindAsync(
|
||||
[evt.OrderId],
|
||||
cancellationToken: stoppingToken
|
||||
);
|
||||
if (order == null)
|
||||
{
|
||||
logger.LogWarning("Order with ID {OrderId} not found. Redelivering.", evt.OrderId);
|
||||
await msg.NakAsync(cancellationToken: stoppingToken);
|
||||
continue;
|
||||
}
|
||||
|
||||
await lotteries.HandleLotteryOrder(order);
|
||||
|
||||
logger.LogInformation("Lottery ticket for order {OrderId} created successfully.", evt.OrderId);
|
||||
await msg.AckAsync(cancellationToken: stoppingToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a subscription, gift, or lottery order, skip
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Error processing payment order event for order {OrderId}. Redelivering.",
|
||||
evt?.OrderId);
|
||||
await msg.NakAsync(cancellationToken: stoppingToken);
|
||||
}
|
||||
}
|
||||
await HandleWebSocketEventsAsync(stoppingToken);
|
||||
}
|
||||
|
||||
private async Task HandleWebSocketEventsAsync(CancellationToken stoppingToken)
|
||||
|
||||
@@ -2,7 +2,6 @@ using DysonNetwork.Pass.Account;
|
||||
using DysonNetwork.Pass.Account.Presences;
|
||||
using DysonNetwork.Pass.Credit;
|
||||
using DysonNetwork.Pass.Handlers;
|
||||
using DysonNetwork.Pass.Wallet;
|
||||
using Quartz;
|
||||
|
||||
namespace DysonNetwork.Pass.Startup;
|
||||
@@ -37,33 +36,6 @@ public static class ScheduledJobsConfiguration
|
||||
.RepeatForever())
|
||||
);
|
||||
|
||||
q.AddJob<SubscriptionRenewalJob>(opts => opts.WithIdentity("SubscriptionRenewal"));
|
||||
q.AddTrigger(opts => opts
|
||||
.ForJob("SubscriptionRenewal")
|
||||
.WithIdentity("SubscriptionRenewalTrigger")
|
||||
.WithSimpleSchedule(o => o
|
||||
.WithIntervalInMinutes(30)
|
||||
.RepeatForever())
|
||||
);
|
||||
|
||||
q.AddJob<GiftCleanupJob>(opts => opts.WithIdentity("GiftCleanup"));
|
||||
q.AddTrigger(opts => opts
|
||||
.ForJob("GiftCleanup")
|
||||
.WithIdentity("GiftCleanupTrigger")
|
||||
.WithSimpleSchedule(o => o
|
||||
.WithIntervalInHours(1)
|
||||
.RepeatForever())
|
||||
);
|
||||
|
||||
q.AddJob<FundExpirationJob>(opts => opts.WithIdentity("FundExpiration"));
|
||||
q.AddTrigger(opts => opts
|
||||
.ForJob("FundExpiration")
|
||||
.WithIdentity("FundExpirationTrigger")
|
||||
.WithSimpleSchedule(o => o
|
||||
.WithIntervalInHours(1)
|
||||
.RepeatForever())
|
||||
);
|
||||
|
||||
q.AddJob<Lotteries.LotteryDrawJob>(opts => opts.WithIdentity("LotteryDraw"));
|
||||
q.AddTrigger(opts => opts
|
||||
.ForJob("LotteryDraw")
|
||||
|
||||
@@ -4,7 +4,6 @@ using DysonNetwork.Pass.Auth;
|
||||
using DysonNetwork.Pass.Auth.OpenId;
|
||||
using DysonNetwork.Pass.Localization;
|
||||
using DysonNetwork.Pass.Permission;
|
||||
using DysonNetwork.Pass.Wallet;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
using NodaTime;
|
||||
using NodaTime.Serialization.SystemTextJson;
|
||||
@@ -22,7 +21,6 @@ using DysonNetwork.Pass.Mailer;
|
||||
using DysonNetwork.Pass.Realm;
|
||||
using DysonNetwork.Pass.Rewind;
|
||||
using DysonNetwork.Pass.Safety;
|
||||
using DysonNetwork.Pass.Wallet.PaymentHandlers;
|
||||
using DysonNetwork.Shared.Cache;
|
||||
using DysonNetwork.Shared.Geometry;
|
||||
using DysonNetwork.Shared.Registry;
|
||||
@@ -150,10 +148,6 @@ public static class ServiceCollectionExtensions
|
||||
services.AddScoped<AuthService>();
|
||||
services.AddScoped<TokenAuthService>();
|
||||
services.AddScoped<AccountUsernameService>();
|
||||
services.AddScoped<WalletService>();
|
||||
services.AddScoped<SubscriptionService>();
|
||||
services.AddScoped<PaymentService>();
|
||||
services.AddScoped<AfdianPaymentHandler>();
|
||||
services.AddScoped<SafetyService>();
|
||||
services.AddScoped<SocialCreditService>();
|
||||
services.AddScoped<ExperienceService>();
|
||||
|
||||
Reference in New Issue
Block a user