🐛 修复发送消息报错.
This commit is contained in:
@@ -14,6 +14,14 @@
|
||||
* 执行 升级的 `bash` 脚本
|
||||
* 进入 代码目录执行 `sh docker-upgrade.sh` 进行容器升级 `down` > `pull` > `up -d`
|
||||
|
||||
### v2.0.1
|
||||
|
||||
`2024-05-2` `release`
|
||||
|
||||
* 🩰 修改 logo
|
||||
* 🐞 修复 批量执行后日志偶尔不展示的问题
|
||||
* 🐞 修复 批量上传进度条显示异常的问题
|
||||
|
||||
### v2.0.0
|
||||
|
||||
`2024-05-17` `release`
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.orion.visor.framework.websocket.core.session;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
import org.springframework.web.socket.WebSocketExtension;
|
||||
import org.springframework.web.socket.WebSocketMessage;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* web socket 同步会话
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/5/20 10:12
|
||||
*/
|
||||
public class WebSocketSyncSession implements WebSocketSession {
|
||||
|
||||
private final WebSocketSession delegate;
|
||||
|
||||
public WebSocketSyncSession(WebSocketSession delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.delegate.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return this.delegate.getUri();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHandshakeHeaders() {
|
||||
return this.delegate.getHandshakeHeaders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAttributes() {
|
||||
return this.delegate.getAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getPrincipal() {
|
||||
return this.delegate.getPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress() {
|
||||
return this.delegate.getLocalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
return this.delegate.getRemoteAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAcceptedProtocol() {
|
||||
return this.delegate.getAcceptedProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextMessageSizeLimit(int messageSizeLimit) {
|
||||
this.delegate.setTextMessageSizeLimit(messageSizeLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextMessageSizeLimit() {
|
||||
return this.delegate.getTextMessageSizeLimit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBinaryMessageSizeLimit(int messageSizeLimit) {
|
||||
this.delegate.setBinaryMessageSizeLimit(messageSizeLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBinaryMessageSizeLimit() {
|
||||
return this.delegate.getBinaryMessageSizeLimit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WebSocketExtension> getExtensions() {
|
||||
return this.delegate.getExtensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void sendMessage(WebSocketMessage<?> message) throws IOException {
|
||||
this.delegate.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return this.delegate.isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.delegate.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(CloseStatus status) throws IOException {
|
||||
this.delegate.close(status);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,9 @@ package com.orion.visor.framework.websocket.core.utils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.orion.lang.utils.Exceptions;
|
||||
import com.orion.lang.utils.Threads;
|
||||
import com.orion.visor.framework.common.constant.Const;
|
||||
import com.orion.visor.framework.websocket.core.constant.WsCloseCode;
|
||||
import com.orion.visor.framework.websocket.core.session.WebSocketSyncSession;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
import org.springframework.web.socket.TextMessage;
|
||||
@@ -24,6 +26,16 @@ public class WebSockets {
|
||||
private WebSockets() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建同步会话
|
||||
*
|
||||
* @param session session
|
||||
* @return session
|
||||
*/
|
||||
public static WebSocketSession createSyncSession(WebSocketSession session) {
|
||||
return new WebSocketSyncSession(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取属性
|
||||
*
|
||||
@@ -58,13 +70,13 @@ public class WebSockets {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 发重消息
|
||||
// 发送消息
|
||||
session.sendMessage(new TextMessage(message));
|
||||
} catch (IllegalStateException e) {
|
||||
// 并发异常
|
||||
log.error("发送消息失败, 准备进行重试 {}", Exceptions.getDigest(e));
|
||||
// 并发重试
|
||||
retrySendText(session, message, 50);
|
||||
retrySendText(session, message, Const.MS_100);
|
||||
} catch (IOException e) {
|
||||
throw Exceptions.ioRuntime(e);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,10 @@ public class ExecLogTailHandler extends AbstractWebSocketHandler {
|
||||
String trackerId = this.getTrackerId(id, info, host);
|
||||
String absolutePath = logsFileClient.getAbsolutePath(host.getPath());
|
||||
// 追踪器
|
||||
ExecLogTracker tracker = new ExecLogTracker(trackerId, absolutePath, session, host);
|
||||
ExecLogTracker tracker = new ExecLogTracker(trackerId,
|
||||
absolutePath,
|
||||
WebSockets.createSyncSession(session),
|
||||
host);
|
||||
// 执行
|
||||
AssetThreadPools.EXEC_LOG.execute(tracker);
|
||||
// 添加追踪器
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.orion.ext.tail.delay.DelayTrackerListener;
|
||||
import com.orion.ext.tail.mode.FileNotFoundMode;
|
||||
import com.orion.ext.tail.mode.FileOffsetMode;
|
||||
import com.orion.spring.SpringHolder;
|
||||
import com.orion.visor.framework.common.constant.Const;
|
||||
import com.orion.visor.framework.websocket.core.utils.WebSockets;
|
||||
import com.orion.visor.module.asset.define.config.AppTrackerConfig;
|
||||
import com.orion.visor.module.asset.entity.dto.ExecHostLogTailDTO;
|
||||
@@ -79,7 +80,20 @@ public class ExecLogTracker implements IExecLogTracker {
|
||||
|
||||
@Override
|
||||
public void read(byte[] bytes, int len, Tracker tracker) {
|
||||
WebSockets.sendText(session, config.getId() + LogConst.SEPARATOR + new String(bytes, 0, len));
|
||||
// 发送消息
|
||||
String message = config.getId() + LogConst.SEPARATOR + new String(bytes, 0, len);
|
||||
try {
|
||||
WebSockets.sendText(session, message);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
log.error("ExecLogTracker.send error", e);
|
||||
}
|
||||
// 重试
|
||||
try {
|
||||
WebSockets.retrySendText(session, message, Const.MS_100);
|
||||
} catch (Exception e) {
|
||||
log.error("ExecLogTracker.resend error fk", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
<a-link target="_blank" href="https://gitee.com/lijiahangmax/orion-visor">gitee</a-link>
|
||||
<a-link target="_blank" href="https://lijiahangmax.github.io/orion-visor">文档</a-link>
|
||||
<a-link target="_blank" href="https://github.com/lijiahangmax/orion-visor/blob/main/LICENSE">License</a-link>
|
||||
<a-link target="_blank" :href="`https://github.com/lijiahangmax/orion-visor/releases/tag/v${version}`">v{{ version }} Community</a-link>
|
||||
<a-link target="_blank" :href="`https://github.com/lijiahangmax/orion-visor/releases/tag/v${version}`">V{{ version }} 社区版</a-link>
|
||||
</a-space>
|
||||
<span class="copyright">
|
||||
Copyright<icon-copyright /> {{ new Date().getFullYear() }} Li Jiahang All rights reserved.
|
||||
Copyright<icon-copyright /> 2023 - {{ new Date().getFullYear() }} Li Jiahang, All rights reserved.
|
||||
</span>
|
||||
</a-space>
|
||||
</a-layout-footer>
|
||||
|
||||
@@ -7,10 +7,10 @@ export default {
|
||||
'login.form.userName.placeholder': '用户名',
|
||||
'login.form.password.placeholder': '密码',
|
||||
'login.form.login': '登录',
|
||||
'login.banner.slogan1': '开箱即用的一站式智能运维平台',
|
||||
'login.banner.subSlogan1': '一站式操作 智能运维 让运维变得更简单',
|
||||
'login.banner.slogan2': '内置权限角色管理',
|
||||
'login.banner.subSlogan2': '让每一次操作都安全可控可追溯',
|
||||
'login.banner.slogan3': '终端操作无障碍',
|
||||
'login.banner.subSlogan3': '高效稳定 远程操作 让工作更高效',
|
||||
'login.banner.slogan1': '现代化的智能运维平台',
|
||||
'login.banner.subSlogan1': '一站式操作 让运维变得更简单',
|
||||
'login.banner.slogan2': '高颜值的轻量堡垒机平台',
|
||||
'login.banner.subSlogan2': '内置批量处理模块 让工作更高效',
|
||||
'login.banner.slogan3': '动态权限角色管理',
|
||||
'login.banner.subSlogan3': '让每一次操作都可追溯',
|
||||
};
|
||||
|
||||
@@ -157,6 +157,7 @@
|
||||
await cancelUploadTask(taskId.value, false);
|
||||
taskStatus.value = UploadTaskStepStatus.WAITING;
|
||||
Message.success('已取消');
|
||||
taskId.value = undefined;
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
@@ -171,6 +172,8 @@
|
||||
|
||||
// 上传请求结束
|
||||
const uploadRequestEnd = async () => {
|
||||
// 上传请求结束后重置文件进度
|
||||
resetSelectedFileProgress();
|
||||
if (taskStatus.value.value === UploadTaskStepStatus.REQUESTING.value) {
|
||||
// 如果结束后还是请求中则代表请求完毕
|
||||
setLoading(true);
|
||||
@@ -196,6 +199,8 @@
|
||||
|
||||
// 上传请求失败
|
||||
const uploadRequestError = async () => {
|
||||
// 上传请求结束后重置文件进度
|
||||
resetSelectedFileProgress();
|
||||
setLoading(true);
|
||||
try {
|
||||
// 开始上传
|
||||
@@ -264,6 +269,11 @@
|
||||
fileList.value = [];
|
||||
};
|
||||
|
||||
// 重置选择的文件进度
|
||||
const resetSelectedFileProgress = () => {
|
||||
fileList.value.forEach(s => s.percent = 0);
|
||||
};
|
||||
|
||||
// 设置轮询状态
|
||||
onMounted(() => {
|
||||
pullIntervalId.value = setInterval(pullTaskStatus, 5000);
|
||||
|
||||
Reference in New Issue
Block a user