From c1c045cad0f39a38409de117e9ddf470804b0d81 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期二, 07 四月 2026 10:22:00 +0800
Subject: [PATCH] #

---
 rsf-server/pom.xml                                                                           |    4 +
 rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisKeys.java                  |   23 +++++++
 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WmsRedisLuaService.java |   68 ++++++++++++++++++++++
 rsf-server/src/main/resources/wms-lua/inventory-reserve.lua                                  |   20 ++++++
 rsf-server/src/main/resources/wms-lua/location-claim.lua                                     |   19 ++++++
 rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisConstants.java             |   12 ++++
 6 files changed, 146 insertions(+), 0 deletions(-)

diff --git a/rsf-server/pom.xml b/rsf-server/pom.xml
index d7b7edb..454c873 100644
--- a/rsf-server/pom.xml
+++ b/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>
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisConstants.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisConstants.java
new file mode 100644
index 0000000..a06854d
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisConstants.java
@@ -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";
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisKeys.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisKeys.java
new file mode 100644
index 0000000..28d6979
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/redis/RedisKeys.java
@@ -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;
+    }
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WmsRedisLuaService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WmsRedisLuaService.java
new file mode 100644
index 0000000..9b01001
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/WmsRedisLuaService.java
@@ -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;
+    }
+}
diff --git a/rsf-server/src/main/resources/wms-lua/inventory-reserve.lua b/rsf-server/src/main/resources/wms-lua/inventory-reserve.lua
new file mode 100644
index 0000000..3ccd793
--- /dev/null
+++ b/rsf-server/src/main/resources/wms-lua/inventory-reserve.lua
@@ -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
diff --git a/rsf-server/src/main/resources/wms-lua/location-claim.lua b/rsf-server/src/main/resources/wms-lua/location-claim.lua
new file mode 100644
index 0000000..b6e6896
--- /dev/null
+++ b/rsf-server/src/main/resources/wms-lua/location-claim.lua
@@ -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

--
Gitblit v1.9.1