Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class AeFinderApplicationConsts
public const int DefaultAssetExpiration = 100; // 100 years
public const string RegisterEmailTemplate = "Register";
public const string AdminRoleName = "admin";
public const string AppStorageResourceName = "Storage";

public static readonly HashSet<string> AppInterestedExtraPropertiesKey = new HashSet<string>
{ "RefBlockNumber", "RefBlockPrefix", "ReturnValue", "Error", "TransactionFee", "ResourceFee" };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ public class AppFullPodResourceUsageDto
{
public string AppId { get; set; }
public string AppVersion { get; set; }
public string ContainerName { get; set; }
// public string ContainerName { get; set; }
public string CurrentState { get; set; }
public string RequestCpu { get; set; }
public string RequestMemory { get; set; }
// public string RequestCpu { get; set; }
// public string RequestMemory { get; set; }
public string LimitCpu { get; set; }
public string LimitMemory { get; set; }
public long UsageTimestamp { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using AeFinder.Apps;

namespace AeFinder.AppResources.Dto;

public class AppResourceUsageDto
{
public AppInfoImmutable AppInfo { get; set; }
public Guid OrganizationId { get; set; }
public Dictionary<string, List<ResourceUsageDto>> ResourceUsages { get; set; } = new();
}

public class ResourceUsageDto
{
public string Name { get; set; }
public string Limit { get; set; }
public string Usage { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Volo.Abp.Application.Dtos;

namespace AeFinder.AppResources.Dto;

public class GetAppResourceUsageInput: PagedResultRequestDto
{
public string AppId { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AeFinder.AppResources.Dto;
using Volo.Abp.Application.Dtos;

namespace AeFinder.AppResources;

public interface IAppResourceUsageService
{
Task AddOrUpdateAsync(List<AppResourceUsageDto> input);
Task DeleteAsync(string appId);
Task<AppResourceUsageDto> GetAsync(Guid? organizationId, string appId);
Task<PagedResultDto<AppResourceUsageDto>> GetListAsync(Guid? organizationId, GetAppResourceUsageInput input);
}
Original file line number Diff line number Diff line change
Expand Up @@ -250,5 +250,11 @@ public AeFinderApplicationAutoMapperProfile()
CreateMap<BillingDetailIndex, BillingDetailDto>();

CreateMap<UserRegisterState, UserRegisterInfo>();

// AppResourceUsage
CreateMap<AppResourceUsageIndex, AppResourceUsageDto>();
CreateMap<ResourceUsageIndex, ResourceUsageDto>();
CreateMap<AppResourceUsageDto, AppResourceUsageIndex>();
CreateMap<ResourceUsageDto, ResourceUsageIndex>();
}
}
70 changes: 70 additions & 0 deletions src/AeFinder.Application/AppResources/AppResourceUsageService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AeFinder.App.Es;
using AeFinder.AppResources.Dto;
using AElf.EntityMapping.Repositories;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Auditing;
using System.Linq;

namespace AeFinder.AppResources;

[RemoteService(IsEnabled = false)]
[DisableAuditing]
public class AppResourceUsageService : AeFinderAppService, IAppResourceUsageService
{
private readonly IEntityMappingRepository<AppResourceUsageIndex, string> _entityMappingRepository;

public AppResourceUsageService(IEntityMappingRepository<AppResourceUsageIndex, string> entityMappingRepository)
{
_entityMappingRepository = entityMappingRepository;
}

public async Task AddOrUpdateAsync(List<AppResourceUsageDto> input)
{
var index = ObjectMapper.Map<List<AppResourceUsageDto>, List<AppResourceUsageIndex>>(input);
await _entityMappingRepository.AddOrUpdateManyAsync(index);
}

public async Task DeleteAsync(string appId)
{
await _entityMappingRepository.DeleteAsync(appId);
}

public async Task<PagedResultDto<AppResourceUsageDto>> GetListAsync(Guid? organizationId,
GetAppResourceUsageInput input)
{
var queryable = await _entityMappingRepository.GetQueryableAsync();
if (organizationId.HasValue)
{
queryable = queryable.Where(o => o.OrganizationId == organizationId.Value);
}

if (!input.AppId.IsNullOrWhiteSpace())
{
queryable = queryable.Where(o => o.AppInfo.AppId == input.AppId);
}

var count = queryable.Count();
var list = queryable.OrderBy(o => o.AppInfo.AppId).Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

return new PagedResultDto<AppResourceUsageDto>
{
TotalCount = count,
Items = ObjectMapper.Map<List<AppResourceUsageIndex>, List<AppResourceUsageDto>>(list)
};
}

public async Task<AppResourceUsageDto> GetAsync(Guid? organizationId, string appId)
{
var index = await _entityMappingRepository.GetAsync(appId);
if (index != null && organizationId.HasValue && index.OrganizationId != organizationId.Value)
{
throw new UserFriendlyException("No permission.");
}

return ObjectMapper.Map<AppResourceUsageIndex, AppResourceUsageDto>(index);
}
}
23 changes: 22 additions & 1 deletion src/AeFinder.Application/Apps/AppDeployService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.Threading.Tasks;
using AeFinder.ApiKeys;
using AeFinder.App.Deploy;
using AeFinder.AppResources;
using AeFinder.AppResources.Dto;
using AeFinder.Apps.Dto;
using AeFinder.Assets;
using AeFinder.BlockScan;
Expand Down Expand Up @@ -40,6 +42,7 @@
private readonly IAppEmailSender _appEmailSender;
private readonly IApiKeyService _apiKeyService;
private readonly PodResourceOptions _podResourceOptions;
private readonly IAppResourceUsageService _appResourceUsageService;

public AppDeployService(IClusterClient clusterClient,
IBlockScanAppService blockScanAppService, IAppDeployManager appDeployManager,
Expand All @@ -50,12 +53,13 @@
IAssetService assetService,
IApiKeyService apiKeyService,
IUserAppService userAppService, IAppEmailSender appEmailSender,
IAppResourceLimitProvider appResourceLimitProvider)
IAppResourceLimitProvider appResourceLimitProvider, IAppResourceUsageService appResourceUsageService)
{
_clusterClient = clusterClient;
_blockScanAppService = blockScanAppService;
_appDeployManager = appDeployManager;
_appResourceLimitProvider = appResourceLimitProvider;
_appResourceUsageService = appResourceUsageService;
_organizationAppService = organizationAppService;
_appDeployOptions = appDeployOptions.Value;
_customOrganizationOptions = customOrganizationOptions.Value;
Expand Down Expand Up @@ -388,6 +392,23 @@
throw new UserFriendlyException("Please purchase storage capacity before proceeding with deployment.");
}
}
else
{
var appResourceUsage = await _appResourceUsageService.GetAsync(null, appId);

Check warning on line 397 in src/AeFinder.Application/Apps/AppDeployService.cs

View check run for this annotation

Codecov / codecov/patch

src/AeFinder.Application/Apps/AppDeployService.cs#L396-L397

Added lines #L396 - L397 were not covered by tests

if (appResourceUsage != null)
{

Check warning on line 400 in src/AeFinder.Application/Apps/AppDeployService.cs

View check run for this annotation

Codecov / codecov/patch

src/AeFinder.Application/Apps/AppDeployService.cs#L400

Added line #L400 was not covered by tests
foreach (var resourceUsage in appResourceUsage.ResourceUsages.Values
.SelectMany(resourceUsages => resourceUsages.Where(resourceUsage =>
resourceUsage.Name == AeFinderApplicationConsts.AppStorageResourceName)))
{

Check warning on line 404 in src/AeFinder.Application/Apps/AppDeployService.cs

View check run for this annotation

Codecov / codecov/patch

src/AeFinder.Application/Apps/AppDeployService.cs#L402-L404

Added lines #L402 - L404 were not covered by tests
if (Convert.ToDecimal(resourceUsage.Usage) > storageAsset.Replicas)
{
throw new UserFriendlyException("Storage is insufficient. Please purchase more storage.");

Check warning on line 407 in src/AeFinder.Application/Apps/AppDeployService.cs

View check run for this annotation

Codecov / codecov/patch

src/AeFinder.Application/Apps/AppDeployService.cs#L406-L407

Added lines #L406 - L407 were not covered by tests
}
}
}
}

Check warning on line 411 in src/AeFinder.Application/Apps/AppDeployService.cs

View check run for this annotation

Codecov / codecov/patch

src/AeFinder.Application/Apps/AppDeployService.cs#L409-L411

Added lines #L409 - L411 were not covered by tests
}

private async Task SetFirstDeployTimeAsync(string appId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,23 @@
private readonly IBlockScanAppService _blockScanAppService;
private readonly IEntityMappingRepository<AppInfoIndex, string> _appInfoEntityMappingRepository;
private readonly IAssetService _assetService;
private readonly IEntityMappingRepository<OrganizationIndex, string> _organizationEntityMappingRepository;

public AppDeleteHandler(ILogger<AppDeleteHandler> logger,
IClusterClient clusterClient,
IBlockScanAppService blockScanAppService,
IAssetService assetService,
IEntityMappingRepository<AppInfoIndex, string> appInfoEntityMappingRepository)
IEntityMappingRepository<AppInfoIndex, string> appInfoEntityMappingRepository,
IEntityMappingRepository<OrganizationIndex, string> organizationEntityMappingRepository)

Check warning on line 34 in src/AeFinder.BackgroundWorker.Core/EventHandler/AppDeleteHandler.cs

View check run for this annotation

Codecov / codecov/patch

src/AeFinder.BackgroundWorker.Core/EventHandler/AppDeleteHandler.cs#L33-L34

Added lines #L33 - L34 were not covered by tests
{
_logger = logger;
_clusterClient = clusterClient;
_blockScanAppService = blockScanAppService;
_assetService = assetService;
_appInfoEntityMappingRepository = appInfoEntityMappingRepository;
_organizationEntityMappingRepository = organizationEntityMappingRepository;

Check warning on line 41 in src/AeFinder.BackgroundWorker.Core/EventHandler/AppDeleteHandler.cs

View check run for this annotation

Codecov / codecov/patch

src/AeFinder.BackgroundWorker.Core/EventHandler/AppDeleteHandler.cs#L41

Added line #L41 was not covered by tests
}

public async Task HandleEventAsync(AppDeleteEto eventData)
{
var appId = eventData.AppId;
Expand Down Expand Up @@ -82,6 +85,11 @@
appInfoIndex.Status = eventData.Status;
appInfoIndex.DeleteTime = eventData.DeleteTime;
await _appInfoEntityMappingRepository.AddOrUpdateAsync(appInfoIndex);

var organizationIndex = await _organizationEntityMappingRepository.GetAsync(organizationGuid.ToString());
organizationIndex.AppIds.Remove(eventData.AppId);
await _organizationEntityMappingRepository.UpdateAsync(organizationIndex);

Check warning on line 91 in src/AeFinder.BackgroundWorker.Core/EventHandler/AppDeleteHandler.cs

View check run for this annotation

Codecov / codecov/patch

src/AeFinder.BackgroundWorker.Core/EventHandler/AppDeleteHandler.cs#L89-L91

Added lines #L89 - L91 were not covered by tests

_logger.LogInformation($"[AppDeleteHandler] App {eventData.AppId} is deleted.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ public class ScheduledTaskOptions
public int PayFailedOrderTimeoutHours { get; set; } = 48;
public int ConfirmingOrderTimeoutMinutes { get; set; } = 60;
public int BillingPaymentTaskPeriodMilliSeconds { get; set; } = 300000;
public int AppResourceUsageTaskPeriodMilliSeconds { get; set; } = 600000;
}
Loading
Loading