Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions wgx-delayqueue-util/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# DelayQueue - Util 延迟队列服务

## 概述
`DelayQueue - Util` 是一个基于 Java 延迟队列 `DelayQueue` 类实现的服务,用于管理延迟任务。它提供了一系列对延迟任务的操作接口,包括添加、查询、删除等功能,同时通过日志记录操作过程,方便监控和排查问题。该服务依赖于 `DelayedTask` 实体类来表示具体的任务。

## 服务接口

##### 添加元素到延迟队列
##### 方法: `addTask`
- **入参**:
- **task**: 任务对象 `DelayedTask`,包含任务的各种属性,如延迟时间、开始时间、任务 ID、状态、参数、结果和名称等信息。
- **出参**: 添加成功返回 `true`,失败返回 `false`
- **描述**: 将任务添加到延迟队列中。首先会检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常;接着检查任务是否为 `null`,若是则记录错误日志并返回 `false`。若任务不为 `null` 且队列已初始化,则尝试将任务放入队列,若放入过程中出现异常,则记录异常日志,中断当前线程,并返回 `false`;若成功放入队列,则记录添加成功的日志并返回 `true`。

##### 添加元素到延迟队列(队列满时返回 `false`)
##### 方法: `offer`
- **入参**:
- **task**: 任务对象 `DelayedTask`。
- **出参**: 添加成功返回 `true`,队列满返回 `false`
- **描述**: 此方法用于尝试将任务添加到延迟队列。先检查延迟队列是否已初始化以及任务是否为 `null`,若队列未初始化则抛出 `IllegalStateException` 异常,若任务为 `null` 则记录错误日志并返回 `false`。若队列已初始化且任务不为 `null`,则调用 `delayQueue.offer` 方法尝试添加任务,根据该方法的返回值判断添加是否成功,成功则记录日志,失败则记录相应的日志并返回 `false`。

##### 获取并移除最早过期的元素
##### 方法: `take`
- **出参**: 返回最早过期的任务对象 `DelayedTask`,如果队列为空则阻塞等待
- **描述**: 用于获取并移除延迟队列中最早过期的任务。首先检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常。若队列已初始化,则调用 `delayQueue.take` 方法获取任务,若在获取过程中线程被中断,则记录异常日志,恢复线程中断状态,并返回 `null`;若成功获取任务,则记录获取成功的日志并返回该任务。

##### 立即获取最早过期的元素(不阻塞)
##### 方法: `pollNow`
- **出参**: 返回最早过期的任务对象 `DelayedTask`,如果队列为空或所有元素都未到期则返回 `null`
- **描述**: 立即获取并移除最早过期的任务。先检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常。若队列已初始化,则直接调用 `delayQueue.poll` 方法获取任务,若获取到任务则记录日志,若队列为空则直接返回 `null`。

##### 尝试在指定时间内获取队列头部元素
##### 方法: `pollWithTimeout`
- **入参**:
- **timeout**: 等待时间(毫秒)。
- **出参**: 在指定时间内获取到的任务对象 `DelayedTask`,超时或队列为空则返回 `null`
- **描述**: 在指定时间内尝试获取并移除最早过期的任务。首先检查延迟队列是否已初始化,若未初始化则抛出 `RuntimeException` 异常。若队列已初始化,则根据传入的 `timeout` 值(若为 `null` 则设为 0)调用 `delayQueue.poll` 方法获取任务,若在获取过程中线程被中断,则记录异常日志,恢复线程中断状态,并返回 `null`;若成功获取任务,则记录获取成功的日志并返回该任务。

##### 查看但不删除队列头部元素
##### 方法: `peek`
- **出参**: 返回队列头部的任务对象 `DelayedTask`,如果头部元素未到期则返回 `null`
- **描述**: 查看延迟队列头部的任务,但不移除。先检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常。若队列已初始化,则调用 `delayQueue.peek` 方法获取头部任务,若获取到任务则记录日志,若头部元素不存在或未到期则返回 `null`。

##### 查询并返回延迟队列中的所有任务
##### 方法: `findAllTasks`
- **出参**: 返回包含所有任务的列表 `List<DelayedTask>`
- **描述**: 查询并返回延迟队列中的所有任务。首先检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常。若队列已初始化,则创建一个 `ArrayList`,将延迟队列中的所有任务添加到该列表中,并将其转换为不可变列表后返回。

##### 根据任务标题模糊匹配延迟队列中的所有任务
##### 方法: `searchTasksByTaskName`
- **入参**:
- **query**: 用于匹配任务标题的查询字符串。
- **出参**: 返回匹配查询字符串的任务列表 `List<DelayedTask>`
- **描述**: 根据任务标题进行模糊匹配,返回匹配的任务列表。先检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常。若队列已初始化,则判断查询字符串是否为 `null` 或空,若是则直接返回一个空的不可变列表;接着判断队列是否为空,若是则也返回空列表。若队列不为空且查询字符串有效,则遍历队列中的任务,将任务标题包含查询字符串的任务添加到一个新的列表中,并将该列表转换为不可变列表后返回。

##### 根据任务 ID 查询延迟队列中的特定任务
##### 方法: `getTaskByTaskId`
- **入参**:
- **taskId**: 要查询的任务 ID。
- **出参**: 返回匹配任务 ID 的任务对象 `DelayedTask`,如果未找到则返回 `null`
- **描述**: 根据任务 ID 查询延迟队列中的特定任务。先检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常。若队列已初始化,则检查任务 ID 是否为 `null` 或空,若是则直接返回 `null`;接着检查队列是否为空,若是则返回 `null`。若队列不为空且任务 ID 有效,则使用迭代器遍历队列中的任务,找到任务 ID 匹配的任务并返回,若遍历完队列仍未找到匹配的任务则返回 `null`。

##### 清除延迟队列中的所有任务
##### 方法: `clearAllTasks`
- **出参**: 清除操作成功返回 `true`,失败返回 `false`
- **描述**: 清除延迟队列中的所有任务。首先检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常。若队列已初始化,则调用 `delayQueue.clear` 方法清除所有任务,若清除过程中出现异常,则记录异常日志并返回 `false`;若清除成功则记录日志并返回 `true`。

##### 从延迟队列中删除指定的任务
##### 方法: `remove`
- **入参**:
- **o**: 要删除的任务对象 `DelayedTask`。
- **出参**: 删除操作成功返回 `true`,失败返回 `false`
- **描述**: 从延迟队列中删除指定的任务。先检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常。若队列已初始化,则检查要删除的任务对象是否为 `null`,若是则记录警告日志并返回 `false`;若任务对象不为 `null`,则调用 `delayQueue.remove` 方法删除任务,根据该方法的返回值判断删除是否成功,成功则记录删除成功的日志并返回 `true`,失败则返回 `false`。

##### 返回延迟队列中所有元素的数量
##### 方法: `size`
- **出参**: 返回队列中的元素数量 `Integer`
- **描述**: 返回延迟队列中所有元素的数量。先检查延迟队列是否已初始化,若未初始化则抛出 `IllegalStateException` 异常。若队列已初始化,则直接调用 `delayQueue.size` 方法获取队列元素数量并返回。

## 日志记录
所有操作都会记录日志,包括成功添加、失败添加、
### 任务实体介绍

#### 概述

任务实体 `DelayedTask` 是一个用于表示延迟任务的 Java 类。它实现了 `java.util.concurrent.Delayed` 接口,使得其实例可以被放入延迟队列中,以便在指定的延迟时间后执行。

#### 属性

##### 延迟时间(Delay)
- **名称**: `delay`
- **类型**: `Long`
- **描述**: 表示任务需要延迟多长时间后执行,单位为毫秒。

##### 任务开始时间(Start Time)
- **名称**: `startTime`
- **类型**: `Long`
- **描述**: 表示任务计划开始执行的时间戳,单位为毫秒。

##### 任务ID(Task ID)
- **名称**: `taskId`
- **类型**: `String`
- **描述**: 任务的唯一标识符,用于区分不同的任务。

##### 任务状态(Status)
- **名称**: `status`
- **类型**: `String`
- **描述**: 表示任务的当前状态,例如 "pending", "running", "completed", "failed" 等。

##### 任务参数(Parameters)
- **名称**: `parameters`
- **类型**: `String`
- **描述**: 任务执行时需要的参数,可以是 JSON 字符串或其他格式。

##### 任务结果(Result)
- **名称**: `result`
- **类型**: `String`
- **描述**: 任务执行后的结果,可以是返回值、状态信息或其他相关数据。

##### 任务名称(Task Name)
- **名称**: `taskName`
- **类型**: `String`
- **描述**: 任务的名称,用于描述任务的用途或类型。

需要描述清楚 实体描述保留
Binary file not shown.
93 changes: 93 additions & 0 deletions wgx-delayqueue-util/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.wgx</groupId>
<artifactId>wgx-delayqueue-util</artifactId>
<version>1.1.2</version>
<name>延迟队列依赖库</name>
<description>延迟队列依赖库</description>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.9.RELEASE</version><!--与当前制品应用默认版本统一-->
<relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
<!--本案例是本地系统引入nasl-metadata-collector-0.10.1.jar的方式。
若把nasl-metadata-collector-0.10.1.jar安装到自己的maven仓库,
注意修改artifactId和groupId的情况下,不要使用<scope>system</scope>,会在发布时造成依赖中断。
不修改artifactId和groupId的情况下,nasl-metadata-maven-plugin会做特殊处理-->

<!--Nasl核心依赖-->
<dependency>
<artifactId>nasl-metadata-collector</artifactId>
<groupId>com.netease.lowcode</groupId>
<version>0.8.0</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/jar/nasl-metadata-collector-0.8.0.jar</systemPath>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<!--Jackson JSON-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>

<!-- &lt;!&ndash;SLF4J API&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-api</artifactId>-->
<!-- <scope>provided</scope>-->
<!-- </dependency>-->

<!--制品应用使用Springboot框架,父应用引用了的包,为了防止版本冲突,scope可设置为provided-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>

<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.netease.lowcode</groupId>
<artifactId>nasl-metadata-maven-plugin</artifactId>
<version>1.3.0</version>
<executions>
<execution>
<goals>
<goal>archive</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
85 changes: 85 additions & 0 deletions wgx-delayqueue-util/src/main/java/com/wgx/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.wgx;/*
package com.wgx;

import com.wgx.lib.delayqueue.modal.DelayedTask;
import com.wgx.lib.delayqueue.service.DelayQueueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.List;

@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
private DelayQueueService delayedTaskService;

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Override
public void run(String... args) throws Exception {
// 创建任务
DelayedTask task1 = new DelayedTask("task-001", 1000L, System.currentTimeMillis() + 1000L, "PENDING", "", "", "Sample Task 1");
DelayedTask task2 = new DelayedTask("task-002", 2000L, System.currentTimeMillis() + 2000L, "PENDING", "", "", "Sample Task 2");
DelayedTask task3 = new DelayedTask("task-003", 5000L, System.currentTimeMillis() + 5000L, "PENDING", "", "", "Sample Task 3");

// 添加任务到延迟队列
boolean added1 = delayedTaskService.addTask(task1);
boolean added2 = delayedTaskService.addTask(task2);
boolean added3 = delayedTaskService.addTask(task3);

// 检查任务是否添加成功
if (added1) {
System.out.println("Task 1 added successfully");
}
if (added2) {
System.out.println("Task 2 added successfully");
}
if (added3) {
System.out.println("Task 3 added successfully");
}

// 尝试获取任务
DelayedTask task = delayedTaskService.pollNow();
if (task != null) {
System.out.println("Polled task: " + task.getTaskName());
}

// 等待一段时间,然后尝试获取下一个任务
Thread.sleep(1100); // 等待1100毫秒,足以让第一个任务到期
task = delayedTaskService.take();
if (task != null) {
System.out.println("Took task1: " + task.getTaskName());
}

// 搜索任务
List<DelayedTask> tasks = delayedTaskService.searchTasksByTaskName("Sample");
for (DelayedTask t : tasks) {
System.out.println("Found task: " + t);
}

// 获取队列大小
int size = delayedTaskService.size();
System.out.println("Queue size: " + size);

task = delayedTaskService.take();
if (task != null) {
System.out.println("Took task2: " + task.getTaskName());
}
task = delayedTaskService.take();
if (task != null) {
System.out.println("Took task3: " + task.getTaskName());
}

// 清除所有任务
boolean cleared = delayedTaskService.clearAllTasks();
if (cleared) {
System.out.println("All tasks cleared successfully");
}

//}
}
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.wgx.lib.delayqueue;

/**
* 依赖库自动扫描类
* @author system
*/
public class LibraryAutoScan {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.wgx.lib.delayqueue.config;

import com.wgx.lib.delayqueue.modal.DelayedTask;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.DelayQueue;

@Configuration
public class DelayQueueConfig {
@Bean
public DelayQueue<DelayedTask> delayQueue() {
return new DelayQueue<>();
}
}
Loading