package com.vincent.rsf.server.manager.service.impl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.ClassPathResource; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.Duration; import java.util.Arrays; import java.util.List; @Slf4j @Service @RequiredArgsConstructor public class WmsRedisLuaService { private static final DefaultRedisScript LOCATION_CLAIM_SCRIPT = createScript("wms-lua/location-claim.lua"); private static final DefaultRedisScript STATION_CLAIM_SCRIPT = createScript("wms-lua/station-claim.lua"); private static final DefaultRedisScript INVENTORY_RESERVE_SCRIPT = createScript("wms-lua/inventory-reserve.lua"); private final StringRedisTemplate redisTemplate; public boolean claimLocation(String occupyKey, String occupyValue, Duration ttl) { Long result = redisTemplate.execute( LOCATION_CLAIM_SCRIPT, List.of(occupyKey), occupyValue, String.valueOf(ttl.toMillis()) ); return result != null && result > 0; } public boolean claimStation(String stationKey, String taskValue, Duration ttl) { Long result = redisTemplate.execute( STATION_CLAIM_SCRIPT, List.of(stationKey), taskValue, String.valueOf(ttl.toMillis()) ); return result != null && result > 0; } public boolean reserveInventory(String inventoryKey, String orderKey, BigDecimal initialAvailable, BigDecimal reserveQuantity, Duration ttl) { Long result = redisTemplate.execute( INVENTORY_RESERVE_SCRIPT, List.of(inventoryKey, orderKey), initialAvailable.toPlainString(), reserveQuantity.toPlainString(), String.valueOf(ttl.toMillis()) ); return result != null && result > 0; } public void releaseKeys(String... keys) { if (keys == null || keys.length == 0) { return; } try { redisTemplate.delete(Arrays.asList(keys)); } catch (Exception ex) { log.warn("Release redis keys failed", ex); } } public void resetInventoryCache(String inventoryKey, BigDecimal availableQuantity, Duration ttl) { redisTemplate.opsForValue().set(inventoryKey, availableQuantity.toPlainString(), ttl); } private static DefaultRedisScript createScript(String path) { DefaultRedisScript script = new DefaultRedisScript<>(); script.setLocation(new ClassPathResource(path)); script.setResultType(Long.class); return script; } }