feat: add agent/env counts to vendor tenant list endpoint

Extend VendorTenantSummary with agentCount, environmentCount, and
agentLimit fields. Fetch counts in parallel using CompletableFuture
per tenant, only calling server API for ACTIVE tenants with RUNNING
servers. Agent limit extracted from license limits JSONB.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-10 22:01:02 +02:00
parent a0c12b8ee6
commit d7ce0aaf8c
2 changed files with 41 additions and 14 deletions

View File

@@ -44,7 +44,10 @@ public class VendorTenantController {
String status,
String serverState,
String licenseExpiry,
String provisionError
String provisionError,
int agentCount,
int environmentCount,
int agentLimit
) {}
public record VendorTenantDetail(
@@ -59,19 +62,39 @@ public class VendorTenantController {
@GetMapping
public ResponseEntity<List<VendorTenantSummary>> listAll() {
List<VendorTenantSummary> summaries = vendorTenantService.listAll().stream()
.map(tenant -> {
ServerStatus status = vendorTenantService.getServerStatus(tenant);
String licenseExpiry = vendorTenantService
.getLicenseForTenant(tenant.getId())
.map(l -> l.getExpiresAt() != null ? l.getExpiresAt().toString() : null)
.orElse(null);
return new VendorTenantSummary(
tenant.getId(), tenant.getName(), tenant.getSlug(),
tenant.getTier().name(), tenant.getStatus().name(),
status.state().name(), licenseExpiry, tenant.getProvisionError()
);
})
var tenants = vendorTenantService.listAll();
var futures = tenants.stream().map(tenant -> java.util.concurrent.CompletableFuture.supplyAsync(() -> {
ServerStatus status = vendorTenantService.getServerStatus(tenant);
String licenseExpiry = vendorTenantService
.getLicenseForTenant(tenant.getId())
.map(l -> l.getExpiresAt() != null ? l.getExpiresAt().toString() : null)
.orElse(null);
int agentCount = 0;
int environmentCount = 0;
int agentLimit = -1;
String endpoint = tenant.getServerEndpoint();
boolean isActive = "ACTIVE".equals(tenant.getStatus().name());
if (isActive && endpoint != null && !endpoint.isBlank() && "RUNNING".equals(status.state().name())) {
var serverApi = vendorTenantService.getServerApiClient();
agentCount = serverApi.getAgentCount(endpoint);
environmentCount = serverApi.getEnvironmentCount(endpoint);
}
var license = vendorTenantService.getLicenseForTenant(tenant.getId());
if (license.isPresent() && license.get().getLimits() != null) {
var limits = license.get().getLimits();
if (limits.containsKey("agents")) {
agentLimit = ((Number) limits.get("agents")).intValue();
}
}
return new VendorTenantSummary(
tenant.getId(), tenant.getName(), tenant.getSlug(),
tenant.getTier().name(), tenant.getStatus().name(),
status.state().name(), licenseExpiry, tenant.getProvisionError(),
agentCount, environmentCount, agentLimit
);
})).toList();
List<VendorTenantSummary> summaries = futures.stream()
.map(java.util.concurrent.CompletableFuture::join)
.toList();
return ResponseEntity.ok(summaries);
}

View File

@@ -184,6 +184,10 @@ public class VendorTenantService {
}
}
public ServerApiClient getServerApiClient() {
return serverApiClient;
}
public List<TenantEntity> listAll() {
return tenantService.findAll().stream()
.filter(t -> t.getStatus() != TenantStatus.DELETED)