package jnpf.dmsService.recordprint;
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import jnpf.exception.DataException;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
import org.springframework.stereotype.Component;
|
|
import java.util.Arrays;
|
|
/**
|
* 使用 Redis 保存短期打印预占,避免预览阶段写入业务表。
|
*/
|
@Component
|
@RequiredArgsConstructor
|
public class RedisDmsRecordPrintReservationStore
|
implements DmsRecordPrintReservationStore {
|
|
private static final String KEY_PREFIX = "dms:record-print:reservation:";
|
|
private static final DefaultRedisScript<Long> CREATE_SCRIPT =
|
new DefaultRedisScript<>(
|
"if redis.call('exists', KEYS[1]) == 1 then return 0 end "
|
+ "redis.call('psetex', KEYS[1], ARGV[1], ARGV[2]) "
|
+ "redis.call('psetex', KEYS[2], ARGV[1], ARGV[3]) "
|
+ "return 1",
|
Long.class);
|
|
private static final DefaultRedisScript<Long> CONFIRM_SCRIPT =
|
new DefaultRedisScript<>(
|
"redis.call('psetex', KEYS[1], ARGV[1], ARGV[2]) "
|
+ "redis.call('psetex', KEYS[2], ARGV[1], ARGV[3]) "
|
+ "return 1",
|
Long.class);
|
|
private final StringRedisTemplate redisTemplate;
|
private final ObjectMapper objectMapper;
|
|
@Override
|
public DmsRecordPrintReservation findByPrintItem(String tenantId, String printItemId)
|
throws DataException {
|
try {
|
String itemKey = itemKey(tenantId, printItemId);
|
String reservationId = redisTemplate.opsForValue().get(itemKey);
|
if (reservationId == null || reservationId.trim().isEmpty()) {
|
return null;
|
}
|
DmsRecordPrintReservation reservation = read(
|
redisTemplate.opsForValue().get(idKey(tenantId, reservationId)));
|
if (reservation == null) {
|
redisTemplate.delete(itemKey);
|
}
|
return reservation;
|
} catch (RuntimeException exception) {
|
throw new DataException("读取打印流水号预占失败");
|
}
|
}
|
|
@Override
|
public DmsRecordPrintReservation findById(String tenantId, String reservationId)
|
throws DataException {
|
try {
|
return read(redisTemplate.opsForValue().get(idKey(tenantId, reservationId)));
|
} catch (RuntimeException exception) {
|
throw new DataException("读取打印流水号预占失败");
|
}
|
}
|
|
@Override
|
public void create(DmsRecordPrintReservation reservation, long ttlMillis)
|
throws DataException {
|
try {
|
String json = objectMapper.writeValueAsString(reservation);
|
Long created = redisTemplate.execute(CREATE_SCRIPT,
|
Arrays.asList(itemKey(reservation.getTenantId(), reservation.getPrintItemId()),
|
idKey(reservation.getTenantId(), reservation.getReservationId())),
|
String.valueOf(ttlMillis), reservation.getReservationId(), json);
|
if (!Long.valueOf(1L).equals(created)) {
|
throw new DataException("该打印申请已经存在有效预占,请刷新后重试");
|
}
|
} catch (JsonProcessingException exception) {
|
throw new DataException("保存打印流水号预占失败");
|
} catch (RuntimeException exception) {
|
if (exception instanceof DataException) {
|
throw exception;
|
}
|
throw new DataException("保存打印流水号预占失败");
|
}
|
}
|
|
@Override
|
public void markConfirmed(DmsRecordPrintReservation reservation, long ttlMillis)
|
throws DataException {
|
try {
|
String json = objectMapper.writeValueAsString(reservation);
|
redisTemplate.execute(CONFIRM_SCRIPT,
|
Arrays.asList(itemKey(reservation.getTenantId(), reservation.getPrintItemId()),
|
idKey(reservation.getTenantId(), reservation.getReservationId())),
|
String.valueOf(ttlMillis), reservation.getReservationId(), json);
|
} catch (JsonProcessingException | RuntimeException exception) {
|
throw new DataException("更新打印流水号预占状态失败");
|
}
|
}
|
|
private DmsRecordPrintReservation read(String json) throws DataException {
|
if (json == null || json.trim().isEmpty()) {
|
return null;
|
}
|
try {
|
return objectMapper.readValue(json, DmsRecordPrintReservation.class);
|
} catch (JsonProcessingException exception) {
|
throw new DataException("打印流水号预占数据格式无效");
|
}
|
}
|
|
private String itemKey(String tenantId, String printItemId) {
|
return KEY_PREFIX + "item:{" + tenantId + "}:" + printItemId;
|
}
|
|
private String idKey(String tenantId, String reservationId) {
|
return KEY_PREFIX + "id:{" + tenantId + "}:" + reservationId;
|
}
|
}
|