feat: 3.2.0

1. 添加token
This commit is contained in:
byteblogs168 2024-03-29 23:38:48 +08:00
parent 36551e14bd
commit aa0ad7737c
13 changed files with 124 additions and 7 deletions

View File

@ -29,6 +29,7 @@ CREATE TABLE `group_config`
`namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
`group_name` varchar(64) NOT NULL DEFAULT '' COMMENT '组名称',
`description` varchar(256) NOT NULL DEFAULT '' COMMENT '组描述',
`token` varchar(256) NOT NULL DEFAULT 'ER_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT' COMMENT 'token',
`group_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '组状态 0、未启用 1、启用',
`version` int(11) NOT NULL COMMENT '版本号',
`group_partition` int(11) NOT NULL COMMENT '分区',

View File

@ -34,6 +34,12 @@ public class EasyRetryProperties {
*/
private String group;
/**
* 令牌
* 若不填则默认为 SystemConstants::DEFAULT_TOKEN
*/
private String token;
/**
* 指定客户端IP默认取本地IP
*/

View File

@ -182,6 +182,8 @@ public class NettyChannel {
.set(HeadersEnum.HOST.getKey(), serverConfig.getHost())
.set(HeadersEnum.NAMESPACE.getKey(), Optional.ofNullable(easyRetryProperties.getNamespace()).orElse(
SystemConstants.DEFAULT_NAMESPACE))
.set(HeadersEnum.TOKEN.getKey(), Optional.ofNullable(easyRetryProperties.getNamespace()).orElse(
SystemConstants.DEFAULT_TOKEN))
;
//发送数据

View File

@ -98,6 +98,11 @@ public interface SystemConstants {
*/
String DEFAULT_NAMESPACE = "764d604ec6fc45f68cd92514c40e9e1a";
/**
* 默认Token
*/
String DEFAULT_TOKEN = "ER_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT";
/**
* AT 所有人
*/

View File

@ -18,6 +18,7 @@ public enum HeadersEnum {
VERSION("version"),
HOST("Host"),
NAMESPACE("namespace"),
TOKEN("token"),
;
private final String key;

View File

@ -33,6 +33,8 @@ public class GroupConfig implements Serializable {
private Integer bucketIndex;
private String token;
private String description;
private LocalDateTime createDt;

View File

@ -39,12 +39,11 @@ public class CacheConsumerGroup implements Lifecycle {
* @return 缓存对象
*/
public static synchronized void addOrUpdate(String groupName, String namespaceId) {
// EasyRetryLog.LOCAL.info("add consumer cache. groupName:[{}]", groupName);
CACHE.put(groupName, namespaceId);
}
public static void remove(String groupName) {
EasyRetryLog.LOCAL.info("Remove consumer cache. groupName:[{}]", groupName);
EasyRetryLog.LOCAL.debug("Remove consumer cache. groupName:[{}]", groupName);
CACHE.invalidate(groupName);
}
@ -54,7 +53,7 @@ public class CacheConsumerGroup implements Lifecycle {
@Override
public void start() {
EasyRetryLog.LOCAL.info("CacheRegisterTable start");
EasyRetryLog.LOCAL.info("CacheRegisterTable start");
CACHE = CacheBuilder.newBuilder()
// 设置并发级别为cpu核心数
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
@ -65,7 +64,7 @@ public class CacheConsumerGroup implements Lifecycle {
@Override
public void close() {
EasyRetryLog.LOCAL.info("CacheRegisterTable stop");
EasyRetryLog.LOCAL.info("CacheRegisterTable stop");
CACHE.invalidateAll();
}
}

View File

@ -0,0 +1,61 @@
package com.aizuda.easy.retry.server.common.cache;
import cn.hutool.core.lang.Pair;
import com.aizuda.easy.retry.common.core.constant.SystemConstants;
import com.aizuda.easy.retry.common.core.context.SpringContext;
import com.aizuda.easy.retry.common.log.EasyRetryLog;
import com.aizuda.easy.retry.server.common.Lifecycle;
import com.aizuda.easy.retry.template.datasource.access.AccessTemplate;
import com.aizuda.easy.retry.template.datasource.persistence.po.GroupConfig;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* @author xiaowoniu
* @date 2024-03-29 23:15:26
* @since 3.2.0
*/
public class CacheToken implements Lifecycle {
private static Cache<Pair<String/*groupName*/, String/*namespaceId*/> , String/*Token*/> CACHE;
public static void add(String groupName, String namespaceId, String token) {
CACHE.put(Pair.of(groupName, namespaceId), token);
}
public static String get(String groupName, String namespaceId) throws ExecutionException {
return CACHE.get(Pair.of(groupName, namespaceId), () -> {
AccessTemplate template = SpringContext.getBean(AccessTemplate.class);
GroupConfig config = template.getGroupConfigAccess().getGroupConfigByGroupName(groupName, namespaceId);
if (Objects.isNull(config)) {
return SystemConstants.DEFAULT_TOKEN;
}
String token = config.getToken();
add(groupName, namespaceId, token);
return token;
});
}
@Override
public void start() {
EasyRetryLog.LOCAL.info("CacheToken start");
CACHE = CacheBuilder.newBuilder()
// 设置并发级别为cpu核心数
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
// 若当前节点不在消费次组则自动到期删除
.expireAfterWrite(60, TimeUnit.SECONDS)
.build();
}
@Override
public void close() {
EasyRetryLog.LOCAL.info("CacheToken stop");
CACHE.invalidateAll();
}
}

View File

@ -23,6 +23,11 @@ public class GroupConfigRequestVO {
@NotNull(message = "组状态不能为空")
private Integer groupStatus;
/**
* 令牌
*/
private String token;
/**
* 描述
*/

View File

@ -36,6 +36,8 @@ public class GroupConfigResponseVO {
private List<String> onlinePodList;
private String token;
private LocalDateTime createDt;
private LocalDateTime updateDt;

View File

@ -78,8 +78,6 @@ public class GroupConfigServiceImpl implements GroupConfigService {
private JdbcTemplate jdbcTemplate;
@Autowired
private MybatisPlusProperties mybatisPlusProperties;
@Autowired
private RetryTaskMapper retryTaskMapper;
@Override
@Transactional
@ -137,6 +135,7 @@ public class GroupConfigServiceImpl implements GroupConfigService {
groupConfig.setDescription(Optional.ofNullable(groupConfigRequestVO.getDescription()).orElse(StrUtil.EMPTY));
// 使用@TableField(value = "version", update= "%s+1") 进行更新version, 这里必须初始化一个值
groupConfig.setVersion(1);
groupConfig.setToken(null);
Assert.isTrue(systemProperties.getTotalPartition() > groupConfigRequestVO.getGroupPartition(),
() -> new EasyRetryServerException("分区超过最大分区. [{}]", systemProperties.getTotalPartition() - 1));
Assert.isTrue(groupConfigRequestVO.getGroupPartition() >= 0,
@ -226,6 +225,7 @@ public class GroupConfigServiceImpl implements GroupConfigService {
groupConfig.setVersion(1);
groupConfig.setNamespaceId(systemUser.getNamespaceId());
groupConfig.setGroupName(groupConfigRequestVO.getGroupName());
groupConfig.setToken(groupConfigRequestVO.getToken());
groupConfig.setDescription(Optional.ofNullable(groupConfigRequestVO.getDescription()).orElse(StrUtil.EMPTY));
if (Objects.isNull(groupConfigRequestVO.getGroupPartition())) {
groupConfig.setGroupPartition(

View File

@ -19,6 +19,9 @@
<a-descriptions-item label="描述" span="3">
{{ groupInfo.description }}
</a-descriptions-item>
<a-descriptions-item label="Token" span="3">
{{ groupInfo.token }}
</a-descriptions-item>
<a-descriptions-item label="OnLine机器" span="3">
<a-tag color="blue" v-for="item in podInfo" :key="item">
{{ item }}

View File

@ -56,6 +56,22 @@
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="16">
<a-col :lg="24" :md="24" :sm="24">
<a-form-item label="Token">
<a-input
placeholder="请输入Token"
:maxLength="64"
:disabled="this.id > 0"
v-decorator="[
'token',
{rules: [{ required: true, message: '请输入Token', whitespace: true}]}
]" >
<a-icon slot="addonAfter" type="sync" @click="getToken()" v-if="!this.id"/>
</a-input>
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="16">
<a-col :lg="24" :md="24" :sm="24">
<a-form-item label="描述">
@ -224,7 +240,7 @@ export default {
new Promise((resolve) => {
setTimeout(resolve, 100)
}).then(() => {
const formData = pick(data, ['id', 'groupName', 'groupStatus', 'description', 'groupPartition', 'idGeneratorMode', 'initScene'])
const formData = pick(data, ['id', 'groupName', 'groupStatus', 'description', 'groupPartition', 'idGeneratorMode', 'initScene', 'token'])
formData.groupStatus = formData.groupStatus.toString()
formData.idGeneratorMode = formData.idGeneratorMode.toString()
formData.initScene = formData.initScene.toString()
@ -232,6 +248,20 @@ export default {
form.setFieldsValue(formData)
})
},
getToken () {
const { form } = this
const token = this.generatePassword(32)
form.setFieldsValue({ token: token })
},
generatePassword (length) {
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
let password = 'ER_'
for (let i = 0; i < length; i++) {
const randomNumber = Math.floor(Math.random() * chars.length)
password += chars.substring(randomNumber, randomNumber + 1)
}
return password
}
}
}