Commit 2b9841c5 authored by wenmo's avatar wenmo

会话管理

parent 6961f0f3
......@@ -7,6 +7,7 @@ import com.dlink.explainer.ca.TableCANode;
import com.dlink.job.JobResult;
import com.dlink.result.IResult;
import com.dlink.result.SelectResult;
import com.dlink.session.ExecutorEntity;
import com.dlink.session.SessionInfo;
import java.util.List;
......@@ -25,7 +26,7 @@ public interface StudioService {
SelectResult getJobData(String jobId);
boolean createSession(SessionDTO sessionDTO,String createUser);
SessionInfo createSession(SessionDTO sessionDTO, String createUser);
boolean clearSession(String session);
......
......@@ -13,6 +13,7 @@ import com.dlink.result.IResult;
import com.dlink.result.SelectResult;
import com.dlink.service.ClusterService;
import com.dlink.service.StudioService;
import com.dlink.session.ExecutorEntity;
import com.dlink.session.SessionConfig;
import com.dlink.session.SessionInfo;
import com.dlink.session.SessionPool;
......@@ -59,7 +60,7 @@ public class StudioServiceImpl implements StudioService {
}
@Override
public boolean createSession(SessionDTO sessionDTO,String createUser) {
public SessionInfo createSession(SessionDTO sessionDTO, String createUser) {
if(sessionDTO.isUseRemote()) {
Cluster cluster = clusterService.getById(sessionDTO.getClusterId());
SessionConfig sessionConfig = SessionConfig.build(
......
......@@ -271,9 +271,9 @@ public class JobManager extends RunTime {
return ResultPool.get(jobId);
}
public static boolean createSession(String session, SessionConfig sessionConfig,String createUser){
public static SessionInfo createSession(String session, SessionConfig sessionConfig,String createUser){
if(SessionPool.exist(session)){
return false;
return SessionPool.getInfo(session);
}
Executor sessionExecutor = null;
if (sessionConfig.isUseRemote()) {
......@@ -281,8 +281,9 @@ public class JobManager extends RunTime {
} else {
sessionExecutor = Executor.buildLocalExecutor(sessionConfig.getExecutorSetting());
}
SessionPool.push(new ExecutorEntity(session,sessionConfig,createUser,LocalDateTime.now(), sessionExecutor));
return true;
ExecutorEntity executorEntity = new ExecutorEntity(session, sessionConfig, createUser, LocalDateTime.now(), sessionExecutor);
SessionPool.push(executorEntity);
return SessionInfo.build(executorEntity);
}
public static List<SessionInfo> listSession(String createUser){
......
......@@ -72,4 +72,13 @@ public class SessionPool {
}
return sessionInfos;
}
public static SessionInfo getInfo(String sessionId){
ExecutorEntity executorEntity = get(sessionId);
if(executorEntity!=null){
return SessionInfo.build(executorEntity);
}else {
return null;
}
}
}
......@@ -157,7 +157,7 @@ const StudioHistory = (props: any) => {
{(row.status==2) ?
(<><Badge status="success"/><Text type="success">SUCCESS</Text></>):
(row.status==1) ?
<><Badge status="error"/><Text type="secondary">RUNNING</Text></> :
<><Badge status="success"/><Text type="secondary">RUNNING</Text></> :
(row.status==3) ?
<><Badge status="error"/><Text type="danger">FAILED</Text></> :
(row.status==4) ?
......
import {executeDDL} from "@/pages/FlinkSqlStudio/service";
import FlinkSQL from "./FlinkSQL";
import {SessionType, TaskType} from "@/pages/FlinkSqlStudio/model";
import {Modal} from "antd";
import {getData, handleRemove} from "@/components/Common/crud";
import {SessionType} from "@/pages/FlinkSqlStudio/model";
import {Modal,message} from "antd";
import {addOrUpdateData, getData, handleRemove} from "@/components/Common/crud";
/*--- 创建会话 ---*/
export function createSession(session: SessionType,dispatch: any) {
const res = addOrUpdateData("api/studio/createSession",session)
res.then((result) => {
message.success(`创建会话【${session.session}】成功!`);
result.datas&&changeSession(result.datas,dispatch);
listSession(dispatch);
});
}
/*--- 查询会话列表 ---*/
export function listSession(dispatch: any) {
const res = getData("api/studio/listSession");
res.then((result)=>{
console.log(result.datas);
dispatch && dispatch({
type: "Studio/saveSession",
payload: result.datas,
});
});
}
/*--- 切换会话 ---*/
export function changeSession(session: SessionType, dispatch: any) {
dispatch && dispatch({
type: "Studio/refreshCurrentSession",
......@@ -13,13 +33,31 @@ export function changeSession(session: SessionType, dispatch: any) {
showTables(session.session,dispatch);
},200);
}
/*--- 退出会话 ---*/
export function quitSession( dispatch: any) {
dispatch && dispatch({
type: "Studio/quitCurrentSession",
});
}
/*--- 注销会话 ---*/
export function clearSession(session: string, dispatch: any) {
Modal.confirm({
title: '确认注销会话【' + session + '】?',
okText: '确认',
cancelText: '取消',
onOk: async () => {
let para = {
id: session,
};
const res = handleRemove('/api/studio/clearSession', [para]);
res.then((result) => {
quitSession(dispatch);
listSession(dispatch);
});
}
});
}
/*--- 刷新 Catalog Table ---*/
export function showTables(session: string, dispatch: any) {
if(session==null||session==''){
return;
......@@ -43,7 +81,7 @@ export function showTables(session: string, dispatch: any) {
});
});
}
/*--- 移除 Catalog Table ---*/
export function removeTable(tablename: string, session: string, dispatch: any) {
Modal.confirm({
title: '确定删除表【' + tablename + '】吗?',
......@@ -62,24 +100,7 @@ export function removeTable(tablename: string, session: string, dispatch: any) {
}
});
}
export function clearSession(session: string, dispatch: any) {
Modal.confirm({
title: '确认清空会话【' + session + '】?',
okText: '确认',
cancelText: '取消',
onOk: async () => {
let para = {
id: session,
};
const res = handleRemove('/api/studio/clearSession', [para]);
res.then((result) => {
quitSession(dispatch);
});
}
});
}
/*--- 刷新 集群 ---*/
export function showCluster(dispatch: any) {
const res = getData('api/cluster/listEnabledAll');
res.then((result) => {
......
......@@ -18,17 +18,17 @@ const StudioLeftTool = (props:any) => {
<TabPane tab={<span><BarsOutlined/> 目录</span>} key="StudioTree" >
<StudioTree/>
</TabPane>
<TabPane tab={<span><DatabaseOutlined /> 数据源</span>} key="DataSource" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
<TabPane tab={<span><MessageOutlined /> 会话</span>} key="Connectors" >
<StudioConnector />
</TabPane>
<TabPane tab={<span><AppstoreOutlined /> 元数据</span>} key="MetaData" >
<TabPane tab={<span><ClusterOutlined /> 集群</span>} key="Cluster" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</TabPane>
<TabPane tab={<span><ClusterOutlined /> 集群</span>} key="Cluster" >
<TabPane tab={<span><DatabaseOutlined /> 数据源</span>} key="DataSource" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</TabPane>
<TabPane tab={<span><MessageOutlined /> 会话</span>} key="Connectors" >
<StudioConnector />
<TabPane tab={<span><AppstoreOutlined /> 元数据</span>} key="MetaData" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</TabPane>
<TabPane tab={<span><FireOutlined /> 任务</span>} key="FlinkTask" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
......
import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {Form, InputNumber,Input,Switch,Select,Tag,Row,Col,Divider,Tooltip,Button} from "antd";
import {
Form, InputNumber, Input, Switch, Select, Tag, Row, Col, Divider, Tooltip, Button, Badge,
Typography
} from "antd";
import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined} from "@ant-design/icons";
import styles from "./index.less";
import {useEffect, useState} from "react";
import {showTables} from "@/components/Studio/StudioEvent/DDL";
const { Option } = Select;
const { Text } = Typography;
const StudioConfig = (props: any) => {
......@@ -75,8 +79,11 @@ const StudioConfig = (props: any) => {
label="远程执行" className={styles.form_item} name="useRemote" valuePropName="checked"
tooltip={{ title: '开启远程执行,将在远程集群进行任务执行', icon: <InfoCircleOutlined /> }}
>
<Switch checkedChildren="启用" unCheckedChildren="禁用"
/>
{
currentSession.session?
(currentSession.sessionConfig&&currentSession.sessionConfig.useRemote?(<><Badge status="success"/><Text type="success">已启用</Text></>):(<><Badge status="error"/><Text type="danger">已禁用</Text></>)
):(<Switch checkedChildren="启用" unCheckedChildren="禁用"/>)
}
</Form.Item>
</Form>
</>
......
import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {Form, InputNumber,Input,Switch,Select,Tag,Row,Col,Divider,Tooltip,Button} from "antd";
import {Form, InputNumber, Input, Switch, Select, Tag, Row, Col, Badge, Tooltip, Button, Typography} from "antd";
import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined} from "@ant-design/icons";
import styles from "./index.less";
import {useEffect, useState} from "react";
import {showCluster, showTables} from "@/components/Studio/StudioEvent/DDL";
const { Option } = Select;
const { Text } = Typography;
const StudioSetting = (props: any) => {
......@@ -111,7 +112,12 @@ const StudioSetting = (props: any) => {
<Col span={24}>
<Form.Item label="Flink集群" tooltip="选择Flink集群进行远程提交任务" name="clusterId"
className={styles.form_item}>
<Select
{
currentSession.session?
(currentSession.sessionConfig&&currentSession.sessionConfig.clusterId?
(<><Badge status="success"/><Text type="success">{currentSession.sessionConfig.clusterName}</Text></>)
:(<><Badge status="error"/><Text type="danger">本地模式</Text></>)
):(<Select
style={{ width: '100%' }}
placeholder="选择Flink集群"
defaultValue={0}
......@@ -119,7 +125,9 @@ const StudioSetting = (props: any) => {
onChange={onChangeClusterSession}
>
{getClusterOptions()}
</Select>
</Select>)
}
</Form.Item>
</Col>
</Row>
......
......@@ -11,7 +11,7 @@ import {StateType} from "@/pages/FlinkSqlStudio/model";
import StudioConsole from "./StudioConsole";
import StudioLeftTool from "./StudioLeftTool";
import StudioRightTool from "./StudioRightTool";
import {showCluster} from "@/components/Studio/StudioEvent/DDL";
import {listSession, showCluster} from "@/components/Studio/StudioEvent/DDL";
type StudioProps = {
rightClickMenu:StateType['rightClickMenu'];
......@@ -24,6 +24,7 @@ const Studio: React.FC<StudioProps> = (props) => {
const [form] = Form.useForm();
showCluster(dispatch);
listSession(dispatch);
const onClick=()=>{
if(rightClickMenu){
......
......@@ -17,10 +17,12 @@ import {
handleAddOrUpdate, handleOption, handleRemove, queryData,
updateEnabled
} from "@/components/Common/crud";
import {showCluster} from "@/components/Studio/StudioEvent/DDL";
const url = '/api/cluster';
const ClusterTableList: React.FC<{}> = () => {
const ClusterTableList: React.FC<{}> = (props: any) => {
const {dispatch} = props;
const [createModalVisible, handleModalVisible] = useState<boolean>(false);
const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
const [formValues, setFormValues] = useState({});
......@@ -38,16 +40,16 @@ const ClusterTableList: React.FC<{}> = () => {
content: '确定删除该集群吗?',
okText: '确认',
cancelText: '取消',
onOk:async () => {
await handleRemove(url,[currentItem]);
onOk: async () => {
await handleRemove(url, [currentItem]);
actionRef.current?.reloadAndRest?.();
}
});
}
};
const checkHeartBeats = async ()=>{
await handleOption(url+'/heartbeats','心跳检测',null);
const checkHeartBeats = async () => {
await handleOption(url + '/heartbeats', '心跳检测', null);
actionRef.current?.reloadAndRest?.();
};
......@@ -122,9 +124,9 @@ const ClusterTableList: React.FC<{}> = () => {
],
filterMultiple: false,
valueEnum: {
'Yarn': { text: 'Yarn'},
'Standalone': { text: 'Standalone'},
'Others': { text: 'Others' },
'Yarn': {text: 'Yarn'},
'Standalone': {text: 'Standalone'},
'Others': {text: 'Others'},
},
},
{
......@@ -162,8 +164,8 @@ const ClusterTableList: React.FC<{}> = () => {
],
filterMultiple: false,
valueEnum: {
1: { text: '正常', status: 'Success' },
0: { text: '异常', status: 'Error' },
1: {text: '正常', status: 'Success'},
0: {text: '异常', status: 'Error'},
},
},
{
......@@ -193,8 +195,8 @@ const ClusterTableList: React.FC<{}> = () => {
],
filterMultiple: false,
valueEnum: {
true: { text: '已启用', status: 'Success' },
false: { text: '已禁用', status: 'Error' },
true: {text: '已启用', status: 'Success'},
false: {text: '已禁用', status: 'Error'},
},
},
{
......@@ -203,14 +205,14 @@ const ClusterTableList: React.FC<{}> = () => {
sorter: true,
valueType: 'dateTime',
hideInForm: true,
hideInTable:true,
renderFormItem: (item, { defaultRender, ...rest }, form) => {
hideInTable: true,
renderFormItem: (item, {defaultRender, ...rest}, form) => {
const status = form.getFieldValue('status');
if (`${status}` === '0') {
return false;
}
if (`${status}` === '3') {
return <Input {...rest} placeholder="请输入异常原因!" />;
return <Input {...rest} placeholder="请输入异常原因!"/>;
}
return defaultRender(item);
},
......@@ -221,13 +223,13 @@ const ClusterTableList: React.FC<{}> = () => {
sorter: true,
valueType: 'dateTime',
hideInForm: true,
renderFormItem: (item, { defaultRender, ...rest }, form) => {
renderFormItem: (item, {defaultRender, ...rest}, form) => {
const status = form.getFieldValue('status');
if (`${status}` === '0') {
return false;
}
if (`${status}` === '3') {
return <Input {...rest} placeholder="请输入异常原因!" />;
return <Input {...rest} placeholder="请输入异常原因!"/>;
}
return defaultRender(item);
},
......@@ -264,10 +266,10 @@ const ClusterTableList: React.FC<{}> = () => {
<PlusOutlined/> 新建
</Button>,
<Button type="primary" onClick={() => checkHeartBeats()}>
<HeartOutlined /> 心跳
<HeartOutlined/> 心跳
</Button>,
]}
request={(params, sorter, filter) => queryData(url,{...params, sorter, filter})}
request={(params, sorter, filter) => queryData(url, {...params, sorter, filter})}
columns={columns}
rowSelection={{
onChange: (_, selectedRows) => setSelectedRows(selectedRows),
......@@ -285,14 +287,14 @@ const ClusterTableList: React.FC<{}> = () => {
}
>
<Button type="primary" danger
onClick ={()=>{
onClick={() => {
Modal.confirm({
title: '删除集群',
content: '确定删除选中的集群吗?',
okText: '确认',
cancelText: '取消',
onOk:async () => {
await handleRemove(url,selectedRowsState);
onOk: async () => {
await handleRemove(url, selectedRowsState);
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
}
......@@ -302,14 +304,14 @@ const ClusterTableList: React.FC<{}> = () => {
批量删除
</Button>
<Button type="primary"
onClick ={()=>{
onClick={() => {
Modal.confirm({
title: '启用集群',
content: '确定启用选中的集群吗?',
okText: '确认',
cancelText: '取消',
onOk:async () => {
await updateEnabled(url,selectedRowsState, true);
onOk: async () => {
await updateEnabled(url, selectedRowsState, true);
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
}
......@@ -317,14 +319,14 @@ const ClusterTableList: React.FC<{}> = () => {
}}
>批量启用</Button>
<Button danger
onClick ={()=>{
onClick={() => {
Modal.confirm({
title: '禁用集群',
content: '确定禁用选中的集群吗?',
okText: '确认',
cancelText: '取消',
onOk:async () => {
await updateEnabled(url,selectedRowsState, false);
onOk: async () => {
await updateEnabled(url, selectedRowsState, false);
setSelectedRows([]);
actionRef.current?.reloadAndRest?.();
}
......@@ -336,12 +338,13 @@ const ClusterTableList: React.FC<{}> = () => {
<CreateForm onCancel={() => handleModalVisible(false)} modalVisible={createModalVisible}>
<ProTable<ClusterTableListItem, ClusterTableListItem>
onSubmit={async (value) => {
const success = await handleAddOrUpdate(url,value);
const success = await handleAddOrUpdate(url, value);
if (success) {
handleModalVisible(false);
if (actionRef.current) {
actionRef.current.reload();
}
showCluster(dispatch);
}
}}
rowKey="id"
......@@ -352,13 +355,14 @@ const ClusterTableList: React.FC<{}> = () => {
{formValues && Object.keys(formValues).length ? (
<UpdateForm
onSubmit={async (value) => {
const success = await handleAddOrUpdate(url,value);
const success = await handleAddOrUpdate(url, value);
if (success) {
handleUpdateModalVisible(false);
setFormValues({});
if (actionRef.current) {
actionRef.current.reload();
}
showCluster(dispatch);
}
}}
onCancel={() => {
......
......@@ -75,11 +75,13 @@ export type ConnectorType = {
export type SessionType = {
session?: string;
sessionConfig?:{
type?: string;
useRemote?: string;
useRemote?: boolean;
clusterId?: number;
clusterName?: string;
address?: string;
}
createUser?: string;
createTime?: string;
connectors: ConnectorType[];
......@@ -157,7 +159,7 @@ const Model: ModelType = {
},
sql: '',
monaco: {},
currentPath: [],
currentPath: ['草稿'],
tabs: {
activeKey: 0,
panes: [{
......@@ -314,23 +316,11 @@ const Model: ModelType = {
};
},
saveSession(state, {payload}) {
let newSession = state?.session;
if(newSession) {
for (let i = 0; i < newSession.length; i++) {
if (newSession[i].key == payload) {
return {};
}
}
newSession.push(payload);
console.log(payload);
return {
...state,
session: newSession,
session: [...payload],
};
}else {
return {
...state
};
}
},
showRightClickMenu(state, {payload}) {
return {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment