🐛 修复发送消息报错.
This commit is contained in:
@@ -14,6 +14,14 @@
|
|||||||
* 执行 升级的 `bash` 脚本
|
* 执行 升级的 `bash` 脚本
|
||||||
* 进入 代码目录执行 `sh docker-upgrade.sh` 进行容器升级 `down` > `pull` > `up -d`
|
* 进入 代码目录执行 `sh docker-upgrade.sh` 进行容器升级 `down` > `pull` > `up -d`
|
||||||
|
|
||||||
|
### v2.0.1
|
||||||
|
|
||||||
|
`2024-05-2` `release`
|
||||||
|
|
||||||
|
* 🩰 修改 logo
|
||||||
|
* 🐞 修复 批量执行后日志偶尔不展示的问题
|
||||||
|
* 🐞 修复 批量上传进度条显示异常的问题
|
||||||
|
|
||||||
### v2.0.0
|
### v2.0.0
|
||||||
|
|
||||||
`2024-05-17` `release`
|
`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.alibaba.fastjson.JSON;
|
||||||
import com.orion.lang.utils.Exceptions;
|
import com.orion.lang.utils.Exceptions;
|
||||||
import com.orion.lang.utils.Threads;
|
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.constant.WsCloseCode;
|
||||||
|
import com.orion.visor.framework.websocket.core.session.WebSocketSyncSession;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.TextMessage;
|
import org.springframework.web.socket.TextMessage;
|
||||||
@@ -24,6 +26,16 @@ public class WebSockets {
|
|||||||
private 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;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// 发重消息
|
// 发送消息
|
||||||
session.sendMessage(new TextMessage(message));
|
session.sendMessage(new TextMessage(message));
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
// 并发异常
|
// 并发异常
|
||||||
log.error("发送消息失败, 准备进行重试 {}", Exceptions.getDigest(e));
|
log.error("发送消息失败, 准备进行重试 {}", Exceptions.getDigest(e));
|
||||||
// 并发重试
|
// 并发重试
|
||||||
retrySendText(session, message, 50);
|
retrySendText(session, message, Const.MS_100);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw Exceptions.ioRuntime(e);
|
throw Exceptions.ioRuntime(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,10 @@ public class ExecLogTailHandler extends AbstractWebSocketHandler {
|
|||||||
String trackerId = this.getTrackerId(id, info, host);
|
String trackerId = this.getTrackerId(id, info, host);
|
||||||
String absolutePath = logsFileClient.getAbsolutePath(host.getPath());
|
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);
|
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.FileNotFoundMode;
|
||||||
import com.orion.ext.tail.mode.FileOffsetMode;
|
import com.orion.ext.tail.mode.FileOffsetMode;
|
||||||
import com.orion.spring.SpringHolder;
|
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.framework.websocket.core.utils.WebSockets;
|
||||||
import com.orion.visor.module.asset.define.config.AppTrackerConfig;
|
import com.orion.visor.module.asset.define.config.AppTrackerConfig;
|
||||||
import com.orion.visor.module.asset.entity.dto.ExecHostLogTailDTO;
|
import com.orion.visor.module.asset.entity.dto.ExecHostLogTailDTO;
|
||||||
@@ -79,7 +80,20 @@ public class ExecLogTracker implements IExecLogTracker {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(byte[] bytes, int len, Tracker tracker) {
|
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
|
@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://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://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/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>
|
</a-space>
|
||||||
<span class="copyright">
|
<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>
|
</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-layout-footer>
|
</a-layout-footer>
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ export default {
|
|||||||
'login.form.userName.placeholder': '用户名',
|
'login.form.userName.placeholder': '用户名',
|
||||||
'login.form.password.placeholder': '密码',
|
'login.form.password.placeholder': '密码',
|
||||||
'login.form.login': '登录',
|
'login.form.login': '登录',
|
||||||
'login.banner.slogan1': '开箱即用的一站式智能运维平台',
|
'login.banner.slogan1': '现代化的智能运维平台',
|
||||||
'login.banner.subSlogan1': '一站式操作 智能运维 让运维变得更简单',
|
'login.banner.subSlogan1': '一站式操作 让运维变得更简单',
|
||||||
'login.banner.slogan2': '内置权限角色管理',
|
'login.banner.slogan2': '高颜值的轻量堡垒机平台',
|
||||||
'login.banner.subSlogan2': '让每一次操作都安全可控可追溯',
|
'login.banner.subSlogan2': '内置批量处理模块 让工作更高效',
|
||||||
'login.banner.slogan3': '终端操作无障碍',
|
'login.banner.slogan3': '动态权限角色管理',
|
||||||
'login.banner.subSlogan3': '高效稳定 远程操作 让工作更高效',
|
'login.banner.subSlogan3': '让每一次操作都可追溯',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
await cancelUploadTask(taskId.value, false);
|
await cancelUploadTask(taskId.value, false);
|
||||||
taskStatus.value = UploadTaskStepStatus.WAITING;
|
taskStatus.value = UploadTaskStepStatus.WAITING;
|
||||||
Message.success('已取消');
|
Message.success('已取消');
|
||||||
|
taskId.value = undefined;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@@ -171,6 +172,8 @@
|
|||||||
|
|
||||||
// 上传请求结束
|
// 上传请求结束
|
||||||
const uploadRequestEnd = async () => {
|
const uploadRequestEnd = async () => {
|
||||||
|
// 上传请求结束后重置文件进度
|
||||||
|
resetSelectedFileProgress();
|
||||||
if (taskStatus.value.value === UploadTaskStepStatus.REQUESTING.value) {
|
if (taskStatus.value.value === UploadTaskStepStatus.REQUESTING.value) {
|
||||||
// 如果结束后还是请求中则代表请求完毕
|
// 如果结束后还是请求中则代表请求完毕
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -196,6 +199,8 @@
|
|||||||
|
|
||||||
// 上传请求失败
|
// 上传请求失败
|
||||||
const uploadRequestError = async () => {
|
const uploadRequestError = async () => {
|
||||||
|
// 上传请求结束后重置文件进度
|
||||||
|
resetSelectedFileProgress();
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
// 开始上传
|
// 开始上传
|
||||||
@@ -264,6 +269,11 @@
|
|||||||
fileList.value = [];
|
fileList.value = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 重置选择的文件进度
|
||||||
|
const resetSelectedFileProgress = () => {
|
||||||
|
fileList.value.forEach(s => s.percent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
// 设置轮询状态
|
// 设置轮询状态
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
pullIntervalId.value = setInterval(pullTaskStatus, 5000);
|
pullIntervalId.value = setInterval(pullTaskStatus, 5000);
|
||||||
|
|||||||
Reference in New Issue
Block a user