fix: make tenant provisioning truly async via self-proxy
@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:
@@ -22,6 +22,7 @@ import net.siegeln.cameleer.saas.tenant.TenantStatus;
|
||||
import net.siegeln.cameleer.saas.tenant.dto.CreateTenantRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -49,6 +50,7 @@ public class VendorTenantService {
|
||||
private final ProvisioningProperties provisioningProps;
|
||||
private final TenantDataCleanupService dataCleanupService;
|
||||
private final TenantDatabaseService tenantDatabaseService;
|
||||
private final VendorTenantService self;
|
||||
|
||||
public VendorTenantService(TenantService tenantService,
|
||||
TenantRepository tenantRepository,
|
||||
@@ -60,7 +62,8 @@ public class VendorTenantService {
|
||||
AuditService auditService,
|
||||
ProvisioningProperties provisioningProps,
|
||||
TenantDataCleanupService dataCleanupService,
|
||||
TenantDatabaseService tenantDatabaseService) {
|
||||
TenantDatabaseService tenantDatabaseService,
|
||||
@Lazy VendorTenantService self) {
|
||||
this.tenantService = tenantService;
|
||||
this.tenantRepository = tenantRepository;
|
||||
this.licenseService = licenseService;
|
||||
@@ -72,6 +75,7 @@ public class VendorTenantService {
|
||||
this.provisioningProps = provisioningProps;
|
||||
this.dataCleanupService = dataCleanupService;
|
||||
this.tenantDatabaseService = tenantDatabaseService;
|
||||
this.self = self;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -114,7 +118,7 @@ public class VendorTenantService {
|
||||
|
||||
// 4. Provision server asynchronously (Docker containers, health check, config push)
|
||||
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;
|
||||
@@ -251,7 +255,7 @@ public class VendorTenantService {
|
||||
tenantProvisioner.remove(tenant.getSlug());
|
||||
var license = licenseService.getActiveLicense(tenantId).orElse(null);
|
||||
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;
|
||||
}
|
||||
throw e;
|
||||
@@ -268,7 +272,7 @@ public class VendorTenantService {
|
||||
// Re-provision with freshly pulled images
|
||||
var license = licenseService.getActiveLicense(tenantId).orElse(null);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user