Redis 模块重构与命令系统增强
本次更新对 Lettuce Redis 模块进行了全面重构,引入更清晰的接口设计和更完善的集群支持,同时为命令系统添加了枚举类型参数支持,提升了开发体验。
涉及的相关提交
主要功能更新
-
refactor(database): 重构 Redis 客户端实现并移除旧代码由 @zhibei 提交 - 全面重构 Lettuce Redis 模块,引入清晰的接口设计和完善的集群支持
-
feat(command): 添加枚举类型的命令参数支持和建议功能由 @zhibei 提交 - 为命令系统添加原生枚举类型参数支持,自动提供枚举值建议
-
feat(ui): 在 ClickEvent 中添加 view 属性以获取 InventoryView由 @zhibei 提交 - 在 ClickEvent 中新增 view 属性,方便获取完整的 InventoryView 对象
基础设施改进
-
feat(bukkit): 添加对 ItemName 的支持由 @嘿鹰 提交 - ItemBuilder 支持读取和设置 ItemName(Minecraft 1.20.5+)
-
fix(bukkit-util): 修复 PropertyMap 获取兼容性问题由 @Sting 提交 - 修复玩家头颅纹理属性获取的兼容性问题
-
fix(kether): 修正 RemoteQuestContext 中的方法返回类型由 @zhibei 提交 - 修正 RemoteQuestContext 部分方法的可空性标注
一句话简述更新
Lettuce Redis 模块迎来全面重构,引入更现代化的接口设计和完善的集群支持,同时命令系统新增枚举参数支持,让开发更加便捷。
本次更新的重点
1. Lettuce Redis 模块全面重构
背景问题
在之前的版本中,Lettuce Redis 模块存在以下问题:
- 接口设计不够清晰:客户端类混杂了过多职责,缺少清晰的接口抽象
- 集群支持不完善:集群模式的配置和功能支持较为有限
- 配置复杂度高:配置结构不够直观,缺少完整的配置示例
- 连接池管理混乱:同步和异步连接池的管理逻辑耦合度高
解决方案
本次更新对整个 Lettuce Redis 模块进行了全面重构,引入了清晰的接口分层设计:
新的接口体系:
核心改进
1. 新增接口定义
// 客户端接口
interface IRedisClient {
fun start(autoRelease: Boolean = true): CompletableFuture<Void>
}
// 命令操作接口
interface IRedisCommand {
fun <T> useCommands(block: (RedisCommands<String, String>) -> T): T?
fun <T> useAsyncCommands(block: (RedisAsyncCommands<String, String>) -> T): CompletableFuture<T?>
fun <T> useReactiveCommands(block: (RedisReactiveCommands<String, String>) -> T): CompletableFuture<T?>
}
// 发布订阅接口
interface IRedisPubSub {
fun <T> usePubSubCommands(block: (RedisPubSubCommands<String, String>) -> T): T?
fun <T> usePubSubAsyncCommands(block: (RedisPubSubAsyncCommands<String, String>) -> T): T?
fun <T> usePubSubReactiveCommands(block: (RedisPubSubReactiveCommands<String, String>) -> T): T?
}
// 连接通道接口
interface IRedisChannel {
fun <T> useConnection(
use: ((StatefulRedisConnection<String, String>) -> T)? = null,
useCluster: ((StatefulRedisClusterConnection<String, String>) -> T)? = null
): T?
fun <T> useAsyncConnection(
use: ((StatefulRedisConnection<String, String>) -> T)? = null,
useCluster: ((StatefulRedisClusterConnection<String, String>) -> T)? = null
): CompletableFuture<T?>
}
2. 统一的配置系统
引入了 LettuceRedisConfig 类来统一管理所有配置:
class LettuceRedisConfig(val configurationSection: ConfigurationSection) {
// 基础连接配置
val host: String
val port: Int
val password: String?
val ssl: Boolean
val timeout: Duration
val database: Int
// 线程池配置
val ioThreadPoolSize: Int
val computationThreadPoolSize: Int
// 连接池配置
val pool: Pool
val asyncPool: AsyncPool
// 哨兵模式配置
val enableSentinel: Boolean
val sentinel: Sentinel
// 主从模式配置
val enableSlaves: Boolean
val slaves: Slaves
// 集群模式配置
val cluster: Cluster
}
3. 完善的集群支持
新增 LettuceClusterRedisClient 类,提供完整的 Redis 集群功能支持:
- 集群拓扑自动发现和刷新
- 自适应刷新触发器
- 动态刷新源支持
- 过时连接自动清理
- 集群重定向支持
- 节点成员关系验证
4. 改进的连接池管理
分离了同步和异步连接池的管理逻辑,提供更清晰的资源管理:
class LettuceRedisClient(val redisConfig: LettuceRedisConfig) {
// 同步连接池
lateinit var pool: GenericObjectPool<StatefulRedisConnection<String, String>>
// 异步连接池
lateinit var asyncPool: BoundedAsyncPool<StatefulRedisConnection<String, String>>
// 主从同步连接池
lateinit var masterReplicaPool: GenericObjectPool<StatefulRedisMasterReplicaConnection<String, String>>
// 主从异步连接池
lateinit var masterAsyncReplicaPool: BoundedAsyncPool<StatefulRedisMasterReplicaConnection<String, String>>
}
使用示例
单机模式:
// 加载配置
val config = LettuceRedisConfig(configuration.getConfigurationSection("redis")!!)
// 创建客户端
val client = LettuceRedisClient(config)
client.start().join()
// 使用同步命令
client.useCommands { commands ->
commands.set("key", "value")
commands.get("key")
}
// 使用异步命令
client.useAsyncCommands { commands ->
commands.set("key", "value")
}.thenAccept { result ->
println("操作结果: $result")
}
// 使用发布订阅
client.usePubSubCommands { commands ->
commands.subscribe("channel")
}
集群模式:
// 加载配置
val config = LettuceRedisConfig(configuration.getConfigurationSection("redis")!!)
// 创建集群客户端
val client = LettuceClusterRedisClient(config)
client.start().join()
// 使用集群命令
client.useClusterCommands { commands ->
commands.set("key", "value")
commands.get("key")
}
配置文件示例
新增了完整的配置文件示例 example.yml,涵盖所有配置选项:
redis:
host: localhost
port: 6379
password: password
ssl: false
timeout: PT15S
database: 0
# 哨兵模式
sentinel:
enable: false
masterId: master
nodes:
- "127.0.0.1:26379"
# 主从模式
slaves:
enable: false
readFrom: nearest # master, masterPreferred, slave, slavePreferred, nearest, any
# 集群模式
cluster:
enablePeriodicRefresh: false
refreshPeriod: PT60S
enableAdaptiveRefreshTrigger: []
maxRedirects: 5
# 连接池配置
pool:
maxTotal: 8
maxIdle: 8
minIdle: 0
testOnBorrow: false
maxWaitDuration: PT15S
blockWhenExhausted: true
依赖升级
- Lettuce Core: 升级至 6.6.0(支持最新 Redis 特性)
- Apache Commons Pool2: 升级至 2.12.1(改进连接池性能)
2. 命令系统枚举参数支持
背景问题
在之前的版本中,命令系统虽然支持自定义参数类型,但对于枚举类型的处理不够便捷,开发者需要手动编写约束和建议逻辑。
解决方案
本次更新为命令系统新增了原生的枚举类型参数支持,提供自动约束和自动建议功能。
使用示例
enum class GameMode {
SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR
}
@CommandHeader("gamemode", ["gm"])
object GameModeCommand {
@CommandBody
val main = subCommand {
// 使用枚举参数节点
enum(GameMode.entries, "mode") {
execute<Player> { sender, context, _ ->
val mode = context["mode"]
// mode 类型已自动约束为 GameMode 枚举值之一
sender.gameMode = when (mode) {
"SURVIVAL" -> org.bukkit.GameMode.SURVIVAL
"CREATIVE" -> org.bukkit.GameMode.CREATIVE
"ADVENTURE" -> org.bukkit.GameMode.ADVENTURE
"SPECTATOR" -> org.bukkit.GameMode.SPECTATOR
else -> org.bukkit.GameMode.SURVIVAL
}
}
}
}
}
技术实现
新增 CommandComponent.enum() 扩展函数和相关建议提供器:
@OptIn(ExperimentalStdlibApi::class)
fun CommandComponent.enum(
enums: EnumEntries<*>,
comment: String = "enum",
suggest: List<String> = emptyList(),
optional: Boolean = false,
permission: String = "",
dynamic: CommandComponentDynamic.() -> Unit = {}
): CommandComponentDynamic
命令解析时会自动:
- 从枚举类获取所有可用值
- 生成自动补全建议
- 添加参数值约束验证
3. UI 系统 InventoryView 支持
改进说明
在 ClickEvent 中新增 view 属性,方便直接获取 InventoryView 对象:
class ClickEvent {
// 原有属性
val clicker: Player
val inventory: Inventory
// 新增属性
val view: InventoryView
}
使用场景
buildMenu<Chest> {
onClick { event ->
// 获取 InventoryView
val view = event.view
// 访问上下界面
val topInventory = view.topInventory
val bottomInventory = view.bottomInventory
// 获取标题
val title = view.title
}
}
4. ItemBuilder ItemName 支持
改进说明
ItemBuilder 现在支持 Minecraft 1.20.5+ 的 ItemName 特性:
buildItem(Material.DIAMOND_SWORD) {
// ItemName(原始 JSON 文本组件,不会被格式化)
itemName = "{\"text\":\"Epic Sword\",\"color\":\"gold\"}"
// DisplayName(传统显示名称,会被格式化)
name = "&6Epic Sword"
}
ItemName 与 DisplayName 的区别:
- ItemName: Minecraft 1.20.5+ 引入,原始 JSON 文本组件,不会应用物品名称的斜体格式
- DisplayName: 传统显示名称,会自动应用斜体等格式
5. 其他修复
PropertyMap 兼容性修复
修复了跨版本获取玩家头颅纹理属性时的兼容性问题,确保在不同 Minecraft 版本上都能正确读取头颅纹理。
Kether 类型标注修正
修正了 RemoteQuestContext 中部分方法的返回类型标注:
getExecutor(): 返回类型从QuestExecutor?改为QuestExecutorRemoteVarTable.get()和getFuture(): 返回类型改为可为空
迁移指南
Lettuce Redis 模块迁移
旧版用法
// 旧版:使用旧的客户端类
val redis = SingleClient(...)
redis.useCommands { commands ->
commands.set("key", "value")
}
新版用法
// 新版:使用新的接口和配置
val config = LettuceRedisConfig(configuration.getConfigurationSection("redis")!!)
val client = LettuceRedisClient(config)
client.start().join()
client.useCommands { commands ->
commands.set("key", "value")
}
本次重构移除了旧的客户端实现类:
SingleClient→ 使用LettuceRedisClientClusterClient→ 使用LettuceClusterRedisClientMasterSlaveClient→ 使用LettuceRedisClient并启用slaves配置
配置文件迁移
旧版配置需要根据新的配置结构进行调整,具体请参考 example.yml 和 clusters/cluster0.yml 示例文件。
主要变更:
- 连接池配置结构调整
- 新增异步连接池配置
- 集群配置项增加
- 超时时间使用 Duration 格式(如
PT15S)
文档更新
本次更新同步更新了以下文档:
- Lettuce Redis 模块文档:新增完整的接口说明和使用示例
- 命令系统文档:新增枚举参数节点的使用说明
- UI 系统文档:更新 ClickEvent 的属性说明
- ItemBuilder 文档:新增 ItemName 支持说明
致谢
感谢以下贡献者为本次更新做出的贡献:
- @zhibei - Redis 模块重构、命令系统枚举支持、UI 系统改进、Kether 类型修正
- @嘿鹰 - ItemBuilder ItemName 支持
- @Sting - PropertyMap 兼容性修复
如有问题或建议,欢迎在 GitHub Issues 反馈。