fix: make tenant provisioning truly async via self-proxy
Some checks failed
CI / build (push) Failing after 41s
CI / docker (push) Has been skipped

@Async on provisionAsync() was bypassed because all call sites were
internal (this.provisionAsync), skipping the Spring proxy. Inject self
via @Lazy to route through the proxy so provisioning runs in a
background thread and the API returns immediately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-15 22:32:05 +02:00
parent 0dd52624b7
commit fd50a147a2

View File

@@ -22,6 +22,7 @@ import net.siegeln.cameleer.saas.tenant.TenantStatus;
import net.siegeln.cameleer.saas.tenant.dto.CreateTenantRequest; import net.siegeln.cameleer.saas.tenant.dto.CreateTenantRequest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -49,6 +50,7 @@ public class VendorTenantService {
private final ProvisioningProperties provisioningProps; private final ProvisioningProperties provisioningProps;
private final TenantDataCleanupService dataCleanupService; private final TenantDataCleanupService dataCleanupService;
private final TenantDatabaseService tenantDatabaseService; private final TenantDatabaseService tenantDatabaseService;
private final VendorTenantService self;
public VendorTenantService(TenantService tenantService, public VendorTenantService(TenantService tenantService,
TenantRepository tenantRepository, TenantRepository tenantRepository,
@@ -60,7 +62,8 @@ public class VendorTenantService {
AuditService auditService, AuditService auditService,
ProvisioningProperties provisioningProps, ProvisioningProperties provisioningProps,
TenantDataCleanupService dataCleanupService, TenantDataCleanupService dataCleanupService,
TenantDatabaseService tenantDatabaseService) { TenantDatabaseService tenantDatabaseService,
@Lazy VendorTenantService self) {
this.tenantService = tenantService; this.tenantService = tenantService;
this.tenantRepository = tenantRepository; this.tenantRepository = tenantRepository;
this.licenseService = licenseService; this.licenseService = licenseService;
@@ -72,6 +75,7 @@ public class VendorTenantService {
this.provisioningProps = provisioningProps; this.provisioningProps = provisioningProps;
this.dataCleanupService = dataCleanupService; this.dataCleanupService = dataCleanupService;
this.tenantDatabaseService = tenantDatabaseService; this.tenantDatabaseService = tenantDatabaseService;
this.self = self;
} }
@Transactional @Transactional
@@ -114,7 +118,7 @@ public class VendorTenantService {
// 4. Provision server asynchronously (Docker containers, health check, config push) // 4. Provision server asynchronously (Docker containers, health check, config push)
if (tenantProvisioner.isAvailable()) { if (tenantProvisioner.isAvailable()) {
provisionAsync(tenant.getId(), tenant.getSlug(), tenant.getTier().name(), license.getToken(), actorId); self.provisionAsync(tenant.getId(), tenant.getSlug(), tenant.getTier().name(), license.getToken(), actorId);
} }
return tenant; return tenant;
@@ -251,7 +255,7 @@ public class VendorTenantService {
tenantProvisioner.remove(tenant.getSlug()); tenantProvisioner.remove(tenant.getSlug());
var license = licenseService.getActiveLicense(tenantId).orElse(null); var license = licenseService.getActiveLicense(tenantId).orElse(null);
String token = license != null ? license.getToken() : ""; String token = license != null ? license.getToken() : "";
provisionAsync(tenantId, tenant.getSlug(), tenant.getTier().name(), token, null); self.provisionAsync(tenantId, tenant.getSlug(), tenant.getTier().name(), token, null);
return; return;
} }
throw e; throw e;
@@ -268,7 +272,7 @@ public class VendorTenantService {
// Re-provision with freshly pulled images // Re-provision with freshly pulled images
var license = licenseService.getActiveLicense(tenantId).orElse(null); var license = licenseService.getActiveLicense(tenantId).orElse(null);
String token = license != null ? license.getToken() : ""; String token = license != null ? license.getToken() : "";
provisionAsync(tenantId, tenant.getSlug(), tenant.getTier().name(), token, null); self.provisionAsync(tenantId, tenant.getSlug(), tenant.getTier().name(), token, null);
} }
@Transactional @Transactional