diff --git a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/security/SecurityScanService.java b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/security/SecurityScanService.java index 7a901f73..3549ec6a 100644 --- a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/security/SecurityScanService.java +++ b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/security/SecurityScanService.java @@ -12,6 +12,8 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; import java.io.IOException; import java.nio.file.Files; @@ -75,7 +77,7 @@ public class SecurityScanService { } // Always create a new audit record — supports multiple rounds per version auditRepository.save(new SecurityAudit(versionId, ScannerType.SKILL_SCANNER)); - scanTaskProducer.publishScanTask(new ScanTask( + final ScanTask scanTask = new ScanTask( UUID.randomUUID().toString(), versionId, packagePath, @@ -83,7 +85,22 @@ public class SecurityScanService { publisherId, System.currentTimeMillis(), Map.of("scannerType", ScannerType.SKILL_SCANNER.getValue()) - )); + ); + // Publish the scan task only after this transaction commits, so the + // stream consumer cannot observe the task before the skill_version / + // security_audit rows are visible (issue #612). On rollback the task + // is never published. Fall back to inline publish if somehow called + // outside a transaction. + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + scanTaskProducer.publishScanTask(scanTask); + } + }); + } else { + scanTaskProducer.publishScanTask(scanTask); + } // Only transition to SCANNING if the version is not already published (auto-publish flow) if (version.getStatus() != SkillVersionStatus.PUBLISHED) { version.setStatus(SkillVersionStatus.SCANNING);