From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master
---
jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/impl/LimsMessageServiceImpl.java | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 204 insertions(+), 0 deletions(-)
diff --git a/jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/impl/LimsMessageServiceImpl.java b/jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/impl/LimsMessageServiceImpl.java
new file mode 100644
index 0000000..c00d48c
--- /dev/null
+++ b/jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/impl/LimsMessageServiceImpl.java
@@ -0,0 +1,204 @@
+package jnpf.limsService.impl;
+
+import jnpf.base.UserInfo;
+import jnpf.limsEntity.LimsMessageDeliveryEntity;
+import jnpf.limsEntity.LimsMessageDeliveryStatus;
+import jnpf.limsEntity.LimsMessageEventEntity;
+import jnpf.limsEntity.LimsMessageEventStatus;
+import jnpf.limsEntity.LimsMessageLedger;
+import jnpf.limsEntity.LimsMessageRequest;
+import jnpf.limsEntity.LimsMessageSendResult;
+import jnpf.limsMapper.LimsMessageDeliveryMapper;
+import jnpf.limsMapper.LimsMessageEventMapper;
+import jnpf.limsService.LimsMessageService;
+import jnpf.limsService.LimsRecipientResolver;
+import jnpf.limsService.client.LimsMessageClient;
+import jnpf.message.model.SentMessageForm;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class LimsMessageServiceImpl implements LimsMessageService {
+ private static final int MAX_ERROR_LENGTH = 1000;
+
+ private final LimsMessageEventMapper eventMapper;
+ private final LimsMessageDeliveryMapper deliveryMapper;
+ private final LimsRecipientResolver recipientResolver;
+ private final LimsMessageClient messageClient;
+ private final LimsMessageLedgerService ledgerService;
+ private final LimsMessageConfigValidator configValidator;
+
+ @Override
+ public LimsMessageSendResult send(LimsMessageRequest request) {
+ validate(request);
+ request.setTenantId(normalizeTenant(request.getTenantId()));
+ List<String> recipients = recipientResolver.resolve(request.getTenantId(), request.getRecipients());
+ LimsMessageConfigValidator.ValidationResult config = validateConfig(request);
+ if (request.isDryRun()) {
+ log.info("[lims-message][dry] event={}, bizId={}, occurrence={}, configValid={}, configError={}, " +
+ "recipients={}, parameters={}",
+ request.getEvent().getCode(), request.getBizId(), request.getOccurrenceKey(),
+ config.isValid(), config.getError(), recipients, request.getParameters());
+ int sendable = config.isValid() ? recipients.size() : 0;
+ return new LimsMessageSendResult(true, false, recipients.size(), sendable, 0);
+ }
+
+ boolean ready = config.isValid() && !recipients.isEmpty();
+ LimsMessageLedger ledger = ledgerService.initialize(request,
+ ready ? recipients : Collections.emptyList());
+ if (!ledger.isAcquired()) {
+ return LimsMessageSendResult.duplicate();
+ }
+ LimsMessageEventEntity event = ledger.getEvent();
+ if (!config.isValid()) {
+ event.setRecipientCount(recipients.size());
+ failEvent(event, config.getError());
+ log.error("[lims-message] configuration rejected event={}, bizId={}, occurrence={}, reason={}",
+ request.getEvent().getCode(), request.getBizId(), request.getOccurrenceKey(), config.getError());
+ return new LimsMessageSendResult(true, false, recipients.size(), 0, 0);
+ }
+ if (recipients.isEmpty()) {
+ failEvent(event, "RECIPIENT_NOT_FOUND: no active user resolved");
+ log.error("[lims-message] no recipient event={}, bizId={}, occurrence={}, refs={}, tenant={}",
+ request.getEvent().getCode(), request.getBizId(), request.getOccurrenceKey(),
+ request.getRecipients(), request.getTenantId());
+ return new LimsMessageSendResult(true, false, 0, 0, 0);
+ }
+
+ List<LimsMessageDeliveryEntity> deliveries = ledger.getDeliveries();
+ event.setStatus(LimsMessageEventStatus.PROCESSING);
+ event.setLastModifyTime(new Date());
+ eventMapper.updateById(event);
+
+ int sent = 0;
+ int failed = 0;
+ for (LimsMessageDeliveryEntity delivery : deliveries) {
+ if (deliveryMapper.claim(delivery.getId()) == 0) {
+ failed++;
+ log.warn("[lims-message] delivery claim lost, event={}, delivery={}",
+ request.getEvent().getCode(), delivery.getId());
+ continue;
+ }
+ try {
+ List<String> errors = messageClient.sendScheduleMessage(
+ buildMessageForm(request, delivery));
+ if (errors != null && !errors.isEmpty()) {
+ markFailed(delivery, String.join("; ", errors));
+ failed++;
+ } else {
+ markSent(delivery);
+ sent++;
+ }
+ } catch (Exception e) {
+ markFailed(delivery, e.getMessage());
+ failed++;
+ log.error("[lims-message] send failed event={}, bizId={}, recipient={}",
+ request.getEvent().getCode(), request.getBizId(), delivery.getRecipientUserId(), e);
+ }
+ }
+ aggregate(event, recipients.size(), sent, failed);
+ return new LimsMessageSendResult(true, false, recipients.size(), sent, failed);
+ }
+
+ private SentMessageForm buildMessageForm(LimsMessageRequest request, LimsMessageDeliveryEntity delivery) {
+ UserInfo userInfo = new UserInfo();
+ userInfo.setUserId("system");
+ userInfo.setUserName("LIMS");
+ userInfo.setTenantId(normalizeTenant(request.getTenantId()));
+
+ Map<String, Object> parameters = request.getParameters() == null
+ ? new HashMap<>() : new HashMap<>(request.getParameters());
+ parameters.put("deliveryKey", delivery.getDeliveryKey());
+
+ SentMessageForm form = new SentMessageForm();
+ form.setToUserIds(Collections.singletonList(delivery.getRecipientUserId()));
+ form.setTemplateId(request.getEvent().getCode());
+ form.setParameterMap(parameters);
+ form.setContentMsg(new HashMap<>());
+ form.setUserInfo(userInfo);
+ return form;
+ }
+
+ private void markSent(LimsMessageDeliveryEntity delivery) {
+ Date now = new Date();
+ delivery.setStatus(LimsMessageDeliveryStatus.SENT);
+ delivery.setSentTime(now);
+ delivery.setLastModifyTime(now);
+ delivery.setErrorCode(null);
+ delivery.setErrorMessage(null);
+ deliveryMapper.updateById(delivery);
+ }
+
+ private void markFailed(LimsMessageDeliveryEntity delivery, String error) {
+ delivery.setStatus(LimsMessageDeliveryStatus.FAILED);
+ delivery.setRetryCount(delivery.getRetryCount() == null ? 1 : delivery.getRetryCount() + 1);
+ delivery.setErrorCode("SEND_FAILED");
+ delivery.setErrorMessage(limit(error));
+ delivery.setNextRetryTime(new Date(System.currentTimeMillis() + 2 * 60_000L));
+ delivery.setLastModifyTime(new Date());
+ deliveryMapper.updateById(delivery);
+ }
+
+ private void aggregate(LimsMessageEventEntity event, int recipients, int sent, int failed) {
+ Date now = new Date();
+ event.setRecipientCount(recipients);
+ event.setSentCount(sent);
+ event.setFailedCount(failed);
+ event.setStatus(failed == 0 ? LimsMessageEventStatus.COMPLETED
+ : sent == 0 ? LimsMessageEventStatus.FAILED : LimsMessageEventStatus.PARTIAL_FAILED);
+ event.setLastModifyTime(now);
+ if (failed == 0) {
+ event.setCompletedTime(now);
+ }
+ eventMapper.updateById(event);
+ }
+
+ private void failEvent(LimsMessageEventEntity event, String error) {
+ event.setStatus(LimsMessageEventStatus.FAILED);
+ event.setErrorMessage(limit(error));
+ event.setLastModifyTime(new Date());
+ eventMapper.updateById(event);
+ }
+
+ private void validate(LimsMessageRequest request) {
+ if (request == null || request.getEvent() == null) {
+ throw new IllegalArgumentException("message event is required");
+ }
+ if (!StringUtils.hasText(request.getBizId()) || !StringUtils.hasText(request.getOccurrenceKey())) {
+ throw new IllegalArgumentException("bizId and occurrenceKey are required");
+ }
+ }
+
+ private LimsMessageConfigValidator.ValidationResult validateConfig(LimsMessageRequest request) {
+ try {
+ return configValidator.validate(request.getEvent().getCode());
+ } catch (Exception e) {
+ log.error("[lims-message] configuration check failed event={}, bizId={}",
+ request.getEvent().getCode(), request.getBizId(), e);
+ return new LimsMessageConfigValidator.ValidationResult(false,
+ "CONFIG_INVALID: configuration check failed: " + limit(e.getMessage()));
+ }
+ }
+
+ private String normalizeTenant(String tenantId) {
+ return StringUtils.hasText(tenantId) ? tenantId : "0";
+ }
+
+ private String limit(String value) {
+ if (!StringUtils.hasText(value)) {
+ return "Unknown send error";
+ }
+ return value.length() <= MAX_ERROR_LENGTH ? value : value.substring(0, MAX_ERROR_LENGTH);
+ }
+
+}
--
Gitblit v1.8.0