|
@@ -0,0 +1,104 @@
|
|
|
|
+package com.backendsys.modules.queue.service;
|
|
|
|
+
|
|
|
|
+import cn.hutool.core.convert.Convert;
|
|
|
|
+import com.backendsys.modules.queue.entity.QueuePosition;
|
|
|
|
+import com.backendsys.modules.queue.entity.QueueRequest;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+
|
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
+
|
|
|
|
+@Service
|
|
|
|
+public class QueueService {
|
|
|
|
+ private final StringRedisTemplate redisTemplate;
|
|
|
|
+ private final AtomicInteger counter = new AtomicInteger(0);
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ public QueueService(StringRedisTemplate redisTemplate) {
|
|
|
|
+ this.redisTemplate = redisTemplate;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 分配排队编号
|
|
|
|
+ */
|
|
|
|
+ public int enqueue(String queueKey, QueueRequest queueRequest) {
|
|
|
|
+ // 为每个请求分配一个排队编号
|
|
|
|
+ Long size = redisTemplate.opsForZSet().size(queueKey);
|
|
|
|
+ int position = (size == null) ? 1 : size.intValue() + 1;
|
|
|
|
+ //int position = counter.incrementAndGet();
|
|
|
|
+ System.out.println("排号: " + position + ", request_id: " + queueRequest.getId());
|
|
|
|
+
|
|
|
|
+ queueRequest.setPosition(position);
|
|
|
|
+ redisTemplate.opsForZSet().add(queueKey, queueRequest.getId(), position);
|
|
|
|
+
|
|
|
|
+ return position;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 开始排队
|
|
|
|
+ */
|
|
|
|
+ public void startProcessing(String queueKey) {
|
|
|
|
+ new Thread(() -> {
|
|
|
|
+ while (true) {
|
|
|
|
+ // 从有序集合中取出第一个请求
|
|
|
|
+ String requestId = Convert.toStr(redisTemplate.opsForZSet().popMin(queueKey));
|
|
|
|
+ if (requestId != null) {
|
|
|
|
+ QueueRequest queueRequest = getRequestById(requestId);
|
|
|
|
+ int position = queueRequest.getPosition();
|
|
|
|
+ // 处理请求
|
|
|
|
+ processRequest(queueRequest);
|
|
|
|
+ // 可以通知用户处理完成
|
|
|
|
+ notifyUser(queueRequest, position);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }).start();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void processRequest(QueueRequest queueRequest) {
|
|
|
|
+ // 模拟耗时操作
|
|
|
|
+ try {
|
|
|
|
+ Thread.sleep(10 * 1000);
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 通知
|
|
|
|
+ */
|
|
|
|
+ private void notifyUser(QueueRequest queueRequest, int position) {
|
|
|
|
+ // 通知用户处理完成
|
|
|
|
+ System.out.println("Request " + position + " processed.");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private QueueRequest getRequestById(String requestId) {
|
|
|
|
+ // 根据请求ID获取请求对象
|
|
|
|
+ return new QueueRequest();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取请求的排队位置和队列总数
|
|
|
|
+ * @param requestId 请求ID
|
|
|
|
+ * @return 一个包含排队位置和队列总数的对象
|
|
|
|
+ */
|
|
|
|
+ public QueuePosition getPosition(String queueKey, String requestId) {
|
|
|
|
+ // 获取请求的排队位置
|
|
|
|
+ Long rank = redisTemplate.opsForZSet().rank(queueKey, requestId);
|
|
|
|
+ if (rank == null) {
|
|
|
|
+ return new QueuePosition(-1, 0); // 请求不存在
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取队列的总大小(未处理的请求数量)
|
|
|
|
+ Long size = redisTemplate.opsForZSet().size(queueKey);
|
|
|
|
+ int total = (size == null) ? 0 : size.intValue();
|
|
|
|
+
|
|
|
|
+ // 当前排队位置从0开始,加1表示实际排队位置
|
|
|
|
+ int position = rank.intValue() + 1;
|
|
|
|
+
|
|
|
|
+ return new QueuePosition(position, total);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|