| rsf-server/pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisConstants.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisKeys.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WmsRedisLuaService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/resources/wms-lua/inventory-reserve.lua | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-server/src/main/resources/wms-lua/location-claim.lua | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
rsf-server/pom.xml
@@ -46,6 +46,10 @@ </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisConstants.java
New file @@ -0,0 +1,12 @@ package com.vincent.rsf.server.common.redis; public final class RedisConstants { private RedisConstants() { } public static final String LUA_MODE_PUTAWAY = "PUTAWAY"; public static final String LUA_MODE_PICK = "PICK"; } rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisKeys.java
New file @@ -0,0 +1,23 @@ package com.vincent.rsf.server.common.redis; public final class RedisKeys { private RedisKeys() { } public static String locationOccupy(Long locationId) { return "wms:location:occupy:" + locationId; } public static String locationTaskOccupy(Long locationId) { return "wms:task:occupy:location:" + locationId; } public static String stockAvailable(Long inventoryId) { return "wms:stock:available:" + inventoryId; } public static String stockReserve(String orderNo) { return "wms:stock:reserve:" + orderNo; } } rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WmsRedisLuaService.java
New file @@ -0,0 +1,68 @@ 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; @Slf4j @Service @RequiredArgsConstructor public class WmsRedisLuaService { private static final DefaultRedisScript<Long> LOCATION_CLAIM_SCRIPT = createScript("wms-lua/location-claim.lua"); private static final DefaultRedisScript<Long> INVENTORY_RESERVE_SCRIPT = createScript("wms-lua/inventory-reserve.lua"); private final StringRedisTemplate redisTemplate; public boolean claimLocation(String occupyKey, String taskKey, String mode, String occupyValue, String taskValue, Duration ttl) { Long result = redisTemplate.execute( LOCATION_CLAIM_SCRIPT, Arrays.asList(occupyKey, taskKey), mode, occupyValue, 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, Arrays.asList(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<Long> createScript(String path) { DefaultRedisScript<Long> script = new DefaultRedisScript<>(); script.setLocation(new ClassPathResource(path)); script.setResultType(Long.class); return script; } } rsf-server/src/main/resources/wms-lua/inventory-reserve.lua
New file @@ -0,0 +1,20 @@ local current = redis.call('get', KEYS[1]) local initial = tonumber(ARGV[1]) local reserve = tonumber(ARGV[2]) local ttl = tonumber(ARGV[3]) if current == false then current = initial else current = tonumber(current) end if current < reserve then return 0 end local nextValue = current - reserve redis.call('psetex', KEYS[1], ttl, tostring(nextValue)) redis.call('incrbyfloat', KEYS[2], reserve) redis.call('pexpire', KEYS[2], ttl) return 1 rsf-server/src/main/resources/wms-lua/location-claim.lua
New file @@ -0,0 +1,19 @@ local mode = ARGV[1] local occupyValue = ARGV[2] local taskValue = ARGV[3] local ttl = tonumber(ARGV[4]) if mode == 'PUTAWAY' then if redis.call('exists', KEYS[1]) == 1 or redis.call('exists', KEYS[2]) == 1 then return 0 end redis.call('psetex', KEYS[1], ttl, occupyValue) redis.call('psetex', KEYS[2], ttl, taskValue) return 1 end if redis.call('exists', KEYS[2]) == 1 then return 0 end redis.call('psetex', KEYS[2], ttl, taskValue) return 1