添加Redis工具类,配置读取放到配置类中

master
youys 3 years ago
parent 81f5f1efa4
commit d557a4954e

@ -2,8 +2,6 @@ package net.educoder.common;
import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

@ -4,7 +4,9 @@ import net.educoder.common.DingTalk;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@ -20,13 +22,19 @@ public class AppConfig {
@Autowired
private PropertiesConfig propertiesConfig;
/**
* bean.
*
* @return
*/
@Bean("dingTalkEvaluation")
public DingTalk dingTalkEvaluation() {
return new DingTalk(propertiesConfig.getToken(), propertiesConfig.getSecret());
}
/**
* 线
* 线.
*
* @return
*/
@Bean("taskExecutor")
@ -50,4 +58,27 @@ public class AppConfig {
}
/**
* redisTemplate.
*
* @param factory
* @return redisTemplate.
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置key的序列化方式
template.setKeySerializer(RedisSerializer.string());
// 设置value的序列化方式
template.setValueSerializer(RedisSerializer.json());
// 设置hash的key的序列化方式
template.setHashKeySerializer(RedisSerializer.string());
// 设置hash的value的序列化方式
template.setHashValueSerializer(RedisSerializer.json());
template.afterPropertiesSet();
return template;
}
}

@ -2,22 +2,52 @@ package net.educoder.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @Author: youys
* @Date: 2022/4/2
* @Description:
* @Description: .
*/
@Configuration
public class PropertiesConfig {
/**
* token.
*/
@Value("${evaluation.token}")
private String token;
/**
* secret.
*/
@Value("${evaluation.secret}")
private String secret;
/**
* .
*/
@Value("${bridge.errorOutPuts}")
private String errorOutPuts;
/**
* .
*/
@Value("${bridge.evaluation}")
private String gameEvaluationUrl;
/**
* oj.
*/
@Value("${bridge.ojEvaluation}")
private String ojEvaluationUrl;
/**
* .
*/
@Value("${bridge.callbackUrl}")
private String callbackUrl;
public String getToken() {
return token;
@ -26,4 +56,20 @@ public class PropertiesConfig {
public String getSecret() {
return secret;
}
public String getErrorOutPuts() {
return errorOutPuts;
}
public String getGameEvaluationUrl() {
return gameEvaluationUrl;
}
public String getOjEvaluationUrl() {
return ojEvaluationUrl;
}
public String getCallbackUrl() {
return callbackUrl;
}
}

@ -4,6 +4,8 @@ import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.educoder.common.DingTalk;
import net.educoder.config.PropertiesConfig;
import net.educoder.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -24,19 +26,17 @@ public class CallbackController {
@Autowired
private DingTalk dingTalk;
private static final String RESULT = "success";
@Autowired
private PropertiesConfig propertiesConfig;
@Autowired
private RedisUtil redisUtil;
private static final String RESULT = "success";
private final List<String> ERROR_MSG_LIST = Arrays.asList("系统繁忙,请稍后重试",
"程序执行失败导致评测提前终止,请稍后重试或联系系统管理员",
"本次评测网络延迟较高资源无法正常加载请10s后重试。",
"实验环境存在问题或已被回收,请保存数据再重置实训重新评测。",
"当前实验环境正在更新中,请稍后重试或联系系统管理员!",
"当前网络较差,代码下载超时,请稍后重试!",
"评测脚本设置异常,建议您在实训的配置页面重新选择或修改评测脚本"
);
private static List<String> ERROR_MSG_LIST = null;
@PostMapping("/evaluationReuslt")
@PostMapping("/evaluationResult")
public String evaluation(@RequestBody Map<String, Object> params) {
log.info("回调请求参数:{}", params);
@ -50,13 +50,21 @@ public class CallbackController {
String decodeOutPut = Base64.decodeStr(outPut);
log.info("tpiID:{}, decodeOutPut:{}", tpiID, decodeOutPut);
if (match(decodeOutPut)) {
long incr;
String incrKey = String.format("evaluationResult:%s", tpiID);
boolean flag = (incr = redisUtil.increment(incrKey)) > 3;
log.info("evaluationResult, tpiID:{},第{}次评测失败", tpiID, incr);
if (matchOutPut(decodeOutPut) && flag) {
log.info("tpiID:{},需要发送钉钉通知", tpiID);
// 钉钉通知
StringBuilder sb = new StringBuilder();
sb.append("【自动化评测】tpiID:").append(tpiID).append(" 错误:消息").append(decodeOutPut);
String result = dingTalk.sendMessage(sb.toString());
log.info("发送钉钉通知结果:{}", result);
// 通知之后清空
redisUtil.remove(incrKey);
}
return RESULT;
@ -68,7 +76,10 @@ public class CallbackController {
* @param output
* @return
*/
private boolean match(String output) {
private boolean matchOutPut(String output) {
if (ERROR_MSG_LIST == null) {
ERROR_MSG_LIST = Arrays.asList(propertiesConfig.getErrorOutPuts().split("\n"));
}
for (String s : ERROR_MSG_LIST) {
if (output.contains(s)) {
return true;

@ -1,8 +1,6 @@
package net.educoder.model;
import org.hibernate.annotations.Table;
import javax.annotation.Generated;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;

@ -1,8 +1,9 @@
package net.educoder.shedule;
package net.educoder.schedule;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.educoder.config.PropertiesConfig;
import net.educoder.model.AutoEvaParamConfig;
import net.educoder.service.AutoEvaParamConfigService;
import org.springframework.beans.factory.annotation.Autowired;
@ -20,43 +21,39 @@ import java.util.UUID;
/**
* @Author: youys
* @Date: 2022/4/2
* @Description:
* @Description: .
*/
@Slf4j
@Component
public class EvaCheckWarningTask {
@Value("${bridge.evaluation}")
private String gameEvaluationUrl;
@Value("${bridge.ojEvaluation}")
private String ojEvaluationUrl;
@Value("${bridge.callbackUrl}")
private String callbackUrl;
@Autowired
private PropertiesConfig propertiesConfig;
@Autowired
private AutoEvaParamConfigService autoEvaParamConfigService;
@Async
@Scheduled(initialDelay = 5 * 1000, fixedRate = 30 * 1000)
@Scheduled(cron = "${task.cron.evalCheck}")
public void check() {
log.info("自动化评测接口告警检查---------start ");
long startTime = System.currentTimeMillis();
List<AutoEvaParamConfig> autoEvaParamConfigList = autoEvaParamConfigService.findAll();
log.info(JSONObject.toJSONString(autoEvaParamConfigList));
for (AutoEvaParamConfig autoEvaParamConfig : autoEvaParamConfigList) {
try {
if (autoEvaParamConfig.getType() == 0) {
if (autoEvaParamConfig.getType().equals(AutoEvaParamConfig.SX_EVA)) {
String extras = autoEvaParamConfig.getExtras();
if (!StringUtils.hasLength(extras)) {
continue;
}
postEvaluation(autoEvaParamConfig);
} else if (autoEvaParamConfig.getType() == 1) {
} else if (autoEvaParamConfig.getType().equals(AutoEvaParamConfig.OJ_EVA)) {
if (!StringUtils.hasLength(autoEvaParamConfig.getCodeFileContent())) {
continue;
@ -67,10 +64,15 @@ public class EvaCheckWarningTask {
log.error("自动化评测接口告警检查任务异常", e);
}
}
log.info("自动化评测接口告警检查 ---------end ");
log.info("自动化评测接口告警检查 ---------end ,总耗时:{}ms", (System.currentTimeMillis() - startTime));
}
/**
* .
*
* @param autoEvaParamConfig
*/
private void postEvaluation(AutoEvaParamConfig autoEvaParamConfig) {
JSONObject extrasObject = JSONObject.parseObject(autoEvaParamConfig.getExtras());
@ -90,20 +92,25 @@ public class EvaCheckWarningTask {
param.put("tpiGitURL", autoEvaParamConfig.getTpiGitUrl());
param.put("buildID", autoEvaParamConfig.getBuildId());
param.put("sec_key", UUID.randomUUID().toString());
param.put("callBackUrl", callbackUrl);
String result = HttpUtil.post(gameEvaluationUrl, param);
param.put("callBackUrl", propertiesConfig.getCallbackUrl());
String result = HttpUtil.post(propertiesConfig.getGameEvaluationUrl(), param);
JSONObject jsonResult = JSONObject.parseObject(result);
log.info("实训评测接口返回:{},tpiId:{}", jsonResult, autoEvaParamConfig.getTpiId());
}
/**
* oj.
*
* @param autoEvaParamConfig
*/
private void postOjEvaluation(AutoEvaParamConfig autoEvaParamConfig) {
Map<String, Object> param = new HashMap<>(8);
param.put("tpiID", autoEvaParamConfig.getTpiId());
param.put("testCases", autoEvaParamConfig.getTestCases());
param.put("codeFileContent", autoEvaParamConfig.getCodeFileContent());
param.put("sec_key", UUID.randomUUID().toString());
param.put("callBackUrl", callbackUrl);
String result = HttpUtil.post(ojEvaluationUrl, param);
param.put("callBackUrl", propertiesConfig.getCallbackUrl());
String result = HttpUtil.post(propertiesConfig.getOjEvaluationUrl(), param);
JSONObject jsonResult = JSONObject.parseObject(result);
log.info("Oj评测接口返回:{},tpiId:{}", jsonResult, autoEvaParamConfig.getTpiId());
}

@ -0,0 +1,346 @@
package net.educoder.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @Author: youys
* @Date: 2022/4/6
* @Description: redis.
*/
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
*
*
* @param key
* @param offset 8Bit=1Byte
* @return
*/
public boolean setBit(String key, long offset, boolean isShow) {
boolean result = false;
try {
ValueOperations<String, Object> operations = redisTemplate.opsForValue();
operations.setBit(key, offset, isShow);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
*
*
* @param key
* @param offset
* @return
*/
public boolean getBit(String key, long offset) {
boolean result = false;
try {
ValueOperations<String, Object> operations = redisTemplate.opsForValue();
result = operations.getBit(key, offset);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* .
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations<String, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* ().
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations<String, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* (1).
*
* @param key
* @return
*/
public Long increment(String key) {
return redisTemplate.opsForValue().increment(key);
}
/**
* (), .
*
* @param key
* @param value
* @return
*/
public Long increment(String key, long value) {
return redisTemplate.opsForValue().increment(key, value);
}
/**
* (1).
*
* @param key
* @return
*/
public Long decrement(String key) {
return redisTemplate.opsForValue().decrement(key);
}
/**
* value
*
* @param keys
*/
public void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
}
/**
* value
*
* @param key
*/
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* value
*
* @param key
* @return
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/**
*
*
* @param key
* @return
*/
public Object get(final String key) {
Object result = null;
ValueOperations<String, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
/**
*
*
* @param key
* @param hashKey
* @param value
*/
public void hmSet(String key, Object hashKey, Object value) {
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
hash.put(key, hashKey, value);
}
/**
*
*
* @param key
* @param hashKey
* @return
*/
public Object hmGet(String key, Object hashKey) {
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
return hash.get(key, hashKey);
}
/**
*
*
* @param k
* @param v
*/
public void lPush(String k, Object v) {
ListOperations<String, Object> list = redisTemplate.opsForList();
list.rightPush(k, v);
}
/**
*
*
* @param k
* @param l
* @param l1
* @return
*/
public List<Object> lRange(String k, long l, long l1) {
ListOperations<String, Object> list = redisTemplate.opsForList();
return list.range(k, l, l1);
}
/**
*
*
* @param key
* @param value
*/
public void add(String key, Object value) {
SetOperations<String, Object> set = redisTemplate.opsForSet();
set.add(key, value);
}
/**
*
*
* @param key
* @return
*/
public Set<Object> setMembers(String key) {
SetOperations<String, Object> set = redisTemplate.opsForSet();
return set.members(key);
}
/**
*
*
* @param key
* @param value
* @param scoure
*/
public void zAdd(String key, Object value, double scoure) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.add(key, value, scoure);
}
/**
*
*
* @param key
* @param scoure
* @param scoure1
* @return
*/
public Set<Object> rangeByScore(String key, double scoure, double scoure1) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
redisTemplate.opsForValue();
return zset.rangeByScore(key, scoure, scoure1);
}
/**
*
*
* @param key
* @param value
*/
public Long zRank(String key, Object value) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
return zset.rank(key, value);
}
/**
*
*
* @param key
*/
public Set<ZSetOperations.TypedTuple<Object>> zRankWithScore(String key, long start, long end) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
Set<ZSetOperations.TypedTuple<Object>> ret = zset.rangeWithScores(key, start, end);
return ret;
}
/**
*
*
* @param key
* @param value
*/
public Double zSetScore(String key, Object value) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
return zset.score(key, value);
}
/**
*
*
* @param key
* @param value
* @param scoure
*/
public void incrementScore(String key, Object value, double scoure) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.incrementScore(key, value, scoure);
}
/**
*
*
* @param key
*/
public Set<ZSetOperations.TypedTuple<Object>> reverseZRankWithScore(String key, long start, long end) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
Set<ZSetOperations.TypedTuple<Object>> ret = zset.reverseRangeByScoreWithScores(key, start, end);
return ret;
}
/**
*
*
* @param key
*/
public Set<ZSetOperations.TypedTuple<Object>> reverseZRankWithRank(String key, long start, long end) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
Set<ZSetOperations.TypedTuple<Object>> ret = zset.reverseRangeWithScores(key, start, end);
return ret;
}
}

@ -2,8 +2,19 @@
evaluation:
token: 1069c45d4dfab187bb95599faeaf3687b630f79eda0d6fff914a18ee9e25db6f
secret: SEC7431097248ee9c19b9d7a2c61883e29082bea79c88c3e8f02e5fa121c2837dbc
# b端相关配置
bridge:
evaluation: http://pre-bridge.educoder.net/bridge/game/gameEvaluate
ojEvaluation: http://pre-bridge.educoder.net/bridge/ojs/evaluate
callbackUrl: http://1c32-120-228-142-52.ngrok.io/callback/evaluationReuslt
callbackUrl: http://a176-120-228-142-52.ngrok.io/callback/evaluationResult
errorOutPuts: |
系统繁忙,请稍后重试
程序执行失败导致评测提前终止,请稍后重试或联系系统管理员
本次评测网络延迟较高资源无法正常加载请10s后重试
当前实验环境正在更新中,请稍后重试或联系系统管理员!
当前网络较差,代码下载超时,请稍后重试!
评测脚本设置异常,建议您在实训的配置页面重新选择或修改评测脚本
# 定时任务cron表达式
task:
cron:
evalCheck: 0/30 * * * * ?

@ -1,9 +1,20 @@
## 评测钉钉机器人配置
evaluation:
token: 1069c45d4dfab187bb95599faeaf3687b630f79eda0d6fff914a18ee9e25db6f
secret: SEC7431097248ee9c19b9d7a2c61883e29082bea79c88c3e8f02e5fa121c2837dbc
token: a28abafca1eda791b2b09bf8a7f37d877cc27da986b92c8e1bd1157535d76fdc
secret: SEC09fedac8a866be75685ab14a5a5b80b00f48ba3da953b6af71596a4a225b9b1b
bridge:
evaluation: https://www.educoder.net/bridge/game/gameEvaluate
ojEvaluation: https://www.educoder.net/bridge/ojs/evaluate
callbackUrl: https://1c32-120-228-142-52.ngrok.io/callback/evaluation
callbackUrl: https://1c32-120-228-142-52.ngrok.io/callback/evaluationResult
errorOutPuts: |
系统繁忙,请稍后重试
程序执行失败导致评测提前终止,请稍后重试或联系系统管理员
本次评测网络延迟较高资源无法正常加载请10s后重试
当前实验环境正在更新中,请稍后重试或联系系统管理员!
当前网络较差,代码下载超时,请稍后重试!
评测脚本设置异常,建议您在实训的配置页面重新选择或修改评测脚本
# 定时任务cron表达式
task:
cron:
evalCheck: 0/30 * * * * ?

@ -0,0 +1,54 @@
package net.educoder;
import com.alibaba.fastjson.JSONObject;
import net.educoder.util.RedisUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @Author: youys
* @Date: 2022/4/6
* @Description: redisUtil.
*/
@SpringBootTest
public class RedisUtilTest {
@Autowired
private RedisUtil redisUtil;
@Test
public void testSet() {
redisUtil.set("aaaaaa", "123", 30L);
String str = (String) redisUtil.get("aaaaaa");
System.out.println(str);
JSONObject obj = new JSONObject();
obj.put("123", "123");
obj.put("456", "456");
redisUtil.set("aaaaaa2", obj, 30L);
JSONObject des = (JSONObject) redisUtil.get("aaaaaa2");
System.out.println(des);
}
@Test
public void testIncrement() {
String key = "count";
// for (int i = 0; i < 5; i++) {
// Long increment = redisUtil.increment(key);
// System.out.println(increment);
// }
redisUtil.decrement(key);
redisUtil.decrement(key);
}
}
Loading…
Cancel
Save