fix: app_key backfill on re-registration + notify after tx commit

- LicenseDeviceService: update app_key on re-registration if blank,
  fixing devices that registered before the app_key column was added
- FeatureServiceManager: send activation IM notification in afterCommit()
  hook so the frontend refresh sees the committed DB state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
XuqmGroup 2026-05-16 15:04:57 +08:00
父节点 8443af4818
当前提交 57ad8f7f25
共有 2 个文件被更改,包括 42 次插入2 次删除

查看文件

@ -56,6 +56,9 @@ public class DeviceService {
// Re-issue token
String token = licenseAuthService.generateToken(appKey, deviceId, existing.getId());
String tokenHash = hashToken(token);
if (existing.getAppKey() == null || existing.getAppKey().isBlank()) {
existing.setAppKey(appKey);
}
existing.setDeviceName(firstNonBlank(deviceName, existing.getDeviceName()));
existing.setDeviceModel(firstNonBlank(deviceModel, existing.getDeviceModel()));
existing.setDeviceVendor(firstNonBlank(deviceVendor, existing.getDeviceVendor()));

查看文件

@ -11,8 +11,12 @@ import com.xuqm.tenant.entity.ServiceActivationRequestEntity.Status;
import com.xuqm.tenant.repository.AppRepository;
import com.xuqm.tenant.repository.FeatureServiceRepository;
import com.xuqm.tenant.repository.ServiceActivationRequestRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.time.LocalDateTime;
import java.util.ArrayList;
@ -22,22 +26,27 @@ import java.util.UUID;
@Service
public class FeatureServiceManager {
private static final Logger log = LoggerFactory.getLogger(FeatureServiceManager.class);
private final FeatureServiceRepository repository;
private final ServiceActivationRequestRepository requestRepository;
private final AppRepository appRepository;
private final ObjectMapper objectMapper;
private final LicenseServiceClient licenseServiceClient;
private final ImPlatformEventService imPlatformEventService;
public FeatureServiceManager(FeatureServiceRepository repository,
ServiceActivationRequestRepository requestRepository,
AppRepository appRepository,
ObjectMapper objectMapper,
LicenseServiceClient licenseServiceClient) {
LicenseServiceClient licenseServiceClient,
ImPlatformEventService imPlatformEventService) {
this.repository = repository;
this.requestRepository = requestRepository;
this.appRepository = appRepository;
this.objectMapper = objectMapper;
this.licenseServiceClient = licenseServiceClient;
this.imPlatformEventService = imPlatformEventService;
}
public List<FeatureServiceEntity> listByApp(String appKey) {
@ -173,6 +182,7 @@ public class FeatureServiceManager {
appRepository.findByAppKey(normalizedAppId).ifPresent(app ->
licenseServiceClient.syncAppLicense(app.getAppKey(), app.getName(), 1, expiresAt));
}
sendActivationImNotification(req.getAppKey(), req.getServiceType().name(), "APPROVED", reviewNote);
return req;
}
@ -189,6 +199,7 @@ public class FeatureServiceManager {
});
entity.setEnabled(true);
repository.save(entity);
sendActivationImNotification(req.getAppKey(), req.getServiceType().name(), "APPROVED", reviewNote);
return req;
}
@ -205,7 +216,9 @@ public class FeatureServiceManager {
req.setStatus(Status.REJECTED);
req.setReviewNote(reviewNote);
req.setReviewedAt(LocalDateTime.now());
return requestRepository.save(req);
requestRepository.save(req);
sendActivationImNotification(req.getAppKey(), req.getServiceType().name(), "REJECTED", reviewNote);
return req;
}
public List<ServiceActivationRequestEntity> listRequestsByApp(String appKey) {
@ -619,4 +632,28 @@ public class FeatureServiceManager {
node.put(field, value.trim());
}
}
private void sendActivationImNotification(String appKey, String serviceType, String status, String reviewNote) {
// Send after transaction commits so the frontend refresh sees the updated DB state.
if (TransactionSynchronizationManager.isActualTransactionActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
doSendActivationImNotification(appKey, serviceType, status, reviewNote);
}
});
} else {
doSendActivationImNotification(appKey, serviceType, status, reviewNote);
}
}
private void doSendActivationImNotification(String appKey, String serviceType, String status, String reviewNote) {
try {
imPlatformEventService.notifyServiceActivationChange(
new ImPlatformEventService.ServiceActivationEventRequest(appKey, serviceType, status, reviewNote));
} catch (Exception e) {
log.warn("Failed to send service activation IM notification appKey={} serviceType={} status={}: {}",
appKey, serviceType, status, e.getMessage());
}
}
}