69 lines
2.3 KiB
C#
69 lines
2.3 KiB
C#
using DysonNetwork.Shared.Auth;
|
|
using DysonNetwork.Shared.Cache;
|
|
using DysonNetwork.Shared.Proto;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using NodaTime;
|
|
|
|
namespace DysonNetwork.Drive.Billing;
|
|
|
|
public class QuotaService(
|
|
AppDatabase db,
|
|
UsageService usage,
|
|
AccountService.AccountServiceClient accounts,
|
|
ICacheService cache
|
|
)
|
|
{
|
|
public async Task<(bool ok, long billable, long quota)> IsFileAcceptable(Guid accountId, double costMultiplier, long newFileSize)
|
|
{
|
|
// The billable unit is MiB
|
|
var billableUnit = (long)Math.Ceiling(newFileSize / 1024.0 / 1024.0 * costMultiplier);
|
|
var totalBillableUsage = await usage.GetTotalBillableUsage();
|
|
var quota = await GetQuota(accountId);
|
|
return (totalBillableUsage + billableUnit <= quota, billableUnit, quota);
|
|
}
|
|
|
|
public async Task<long> GetQuota(Guid accountId)
|
|
{
|
|
var cacheKey = $"file:quota:{accountId}";
|
|
var cachedResult = await cache.GetAsync<long?>(cacheKey);
|
|
if (cachedResult.HasValue) return cachedResult.Value;
|
|
|
|
var (based, extra) = await GetQuotaVerbose(accountId);
|
|
var quota = based + extra;
|
|
await cache.SetAsync(cacheKey, quota);
|
|
return quota;
|
|
}
|
|
|
|
public async Task<(long based, long extra)> GetQuotaVerbose(Guid accountId)
|
|
{
|
|
|
|
|
|
var response = await accounts.GetAccountAsync(new GetAccountRequest { Id = accountId.ToString() });
|
|
var perkSubscription = response.PerkSubscription;
|
|
|
|
// The base quota is 1GiB, T1 is 5GiB, T2 is 10GiB, T3 is 15GiB
|
|
var basedQuota = 1L;
|
|
if (perkSubscription != null)
|
|
{
|
|
var privilege = PerkSubscriptionPrivilege.GetPrivilegeFromIdentifier(perkSubscription.Identifier);
|
|
basedQuota = privilege switch
|
|
{
|
|
1 => 5L,
|
|
2 => 10L,
|
|
3 => 15L,
|
|
_ => basedQuota
|
|
};
|
|
}
|
|
|
|
// The based quota is in GiB, we need to convert it to MiB
|
|
basedQuota *= 1024L;
|
|
|
|
var now = SystemClock.Instance.GetCurrentInstant();
|
|
var extraQuota = await db.QuotaRecords
|
|
.Where(e => e.AccountId == accountId)
|
|
.Where(e => !e.ExpiredAt.HasValue || e.ExpiredAt > now)
|
|
.SumAsync(e => e.Quota);
|
|
|
|
return (basedQuota, extraQuota);
|
|
}
|
|
} |