mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 23:40:24 +08:00
refactor: 数据同步优化 & 标签树支持双击展开节点 & mysql支持with语句
This commit is contained in:
1
frontend/src/assets/icon/db/sql.svg
Normal file
1
frontend/src/assets/icon/db/sql.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.0 KiB |
@@ -1,6 +1,7 @@
|
|||||||
import { VNode, h, render } from 'vue';
|
import { VNode, h, render } from 'vue';
|
||||||
import MonacoEditorDialog from './MonacoEditorDialog.vue';
|
import MonacoEditorDialog from './MonacoEditorDialog.vue';
|
||||||
import * as monaco from 'monaco-editor';
|
import * as monaco from 'monaco-editor';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
export type MonacoEditorDialogProps = {
|
export type MonacoEditorDialogProps = {
|
||||||
content: string;
|
content: string;
|
||||||
@@ -53,7 +54,23 @@ const MonacoEditorBox = (props: MonacoEditorDialogProps): void => {
|
|||||||
console.log('close editor');
|
console.log('close editor');
|
||||||
},
|
},
|
||||||
onConfirm: () => {
|
onConfirm: () => {
|
||||||
props.confirmFn && props.confirmFn(props.content);
|
let value = props.content;
|
||||||
|
if (props.language === 'json') {
|
||||||
|
let val;
|
||||||
|
try {
|
||||||
|
val = JSON.parse(value);
|
||||||
|
if (typeof val !== 'object') {
|
||||||
|
ElMessage.error('Invalid json');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
ElMessage.error('Invalid json');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 压缩json字符串
|
||||||
|
value = JSON.stringify(val);
|
||||||
|
}
|
||||||
|
props.confirmFn && props.confirmFn(value);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// 将虚拟dom渲染到 container dom 上
|
// 将虚拟dom渲染到 container dom 上
|
||||||
|
|||||||
@@ -76,11 +76,11 @@ const confirm = async () => {
|
|||||||
try {
|
try {
|
||||||
val = JSON.parse(value);
|
val = JSON.parse(value);
|
||||||
if (typeof val !== 'object') {
|
if (typeof val !== 'object') {
|
||||||
ElMessage.error('请输入正确的json');
|
ElMessage.error('Invalid json');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ElMessage.error('请输入正确的json');
|
ElMessage.error('Invalid json');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,12 @@
|
|||||||
:default-expanded-keys="props.defaultExpandedKeys"
|
:default-expanded-keys="props.defaultExpandedKeys"
|
||||||
>
|
>
|
||||||
<template #default="{ node, data }">
|
<template #default="{ node, data }">
|
||||||
<span :id="node.key" @dblclick="treeNodeDblclick(data)" :class="data.type.nodeDblclickFunc ? 'none-select' : ''">
|
<span
|
||||||
|
:id="node.key"
|
||||||
|
@dblclick="treeNodeDblclick(data, node)"
|
||||||
|
class="node-container none-select"
|
||||||
|
:class="data.type.nodeDblclickFunc ? 'none-select' : ''"
|
||||||
|
>
|
||||||
<span v-if="data.type.value == TagTreeNode.TagPath">
|
<span v-if="data.type.value == TagTreeNode.TagPath">
|
||||||
<tag-info :tag-path="data.label" />
|
<tag-info :tag-path="data.label" />
|
||||||
</span>
|
</span>
|
||||||
@@ -157,7 +162,13 @@ const treeNodeClick = async (data: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 树节点双击事件
|
// 树节点双击事件
|
||||||
const treeNodeDblclick = (data: any) => {
|
const treeNodeDblclick = (data: any, node: any) => {
|
||||||
|
if (node.expanded) {
|
||||||
|
node.collapse();
|
||||||
|
} else {
|
||||||
|
node.expand();
|
||||||
|
}
|
||||||
|
|
||||||
// emit('nodeDblick', data);
|
// emit('nodeDblick', data);
|
||||||
if (!data.disabled && data.type.nodeDblclickFunc) {
|
if (!data.disabled && data.type.nodeDblclickFunc) {
|
||||||
data.type.nodeDblclickFunc(data);
|
data.type.nodeDblclickFunc(data);
|
||||||
@@ -245,5 +256,12 @@ defineExpose({
|
|||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.node-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%; // 确保容器宽度占满整个节点区域
|
||||||
|
cursor: pointer; // 添加鼠标指针样式
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ const TableIcon = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const SqlIcon = {
|
const SqlIcon = {
|
||||||
name: 'Files',
|
name: 'icon db/sql',
|
||||||
color: '#f56c6c',
|
color: '#f56c6c',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -450,11 +450,11 @@ const NodeTypeTableMenu = new NodeType(SqlExecNodeType.TableMenu)
|
|||||||
// 设置父节点参数的表大小
|
// 设置父节点参数的表大小
|
||||||
parentNode.params.dbTableSize = dbTableSize == 0 ? '' : formatByteSize(dbTableSize);
|
parentNode.params.dbTableSize = dbTableSize == 0 ? '' : formatByteSize(dbTableSize);
|
||||||
return tablesNode;
|
return tablesNode;
|
||||||
})
|
|
||||||
.withNodeDblclickFunc((node: TagTreeNode) => {
|
|
||||||
const params = node.params;
|
|
||||||
addTablesOpTab({ id: params.id, db: params.db, type: params.type, version: params.version, nodeKey: node.key });
|
|
||||||
});
|
});
|
||||||
|
// .withNodeDblclickFunc((node: TagTreeNode) => {
|
||||||
|
// const params = node.params;
|
||||||
|
// addTablesOpTab({ id: params.id, db: params.db, type: params.type, version: params.version, nodeKey: node.key });
|
||||||
|
// });
|
||||||
|
|
||||||
// 数据库sql模板菜单节点
|
// 数据库sql模板菜单节点
|
||||||
const NodeTypeSqlMenu = new NodeType(SqlExecNodeType.SqlMenu)
|
const NodeTypeSqlMenu = new NodeType(SqlExecNodeType.SqlMenu)
|
||||||
|
|||||||
@@ -8,21 +8,19 @@
|
|||||||
<el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
|
<el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
|
||||||
<el-tabs v-model="tabActiveName">
|
<el-tabs v-model="tabActiveName">
|
||||||
<el-tab-pane :label="$t('common.basic')" :name="basicTab">
|
<el-tab-pane :label="$t('common.basic')" :name="basicTab">
|
||||||
<el-form-item>
|
<el-row>
|
||||||
<el-row>
|
<el-col :span="12">
|
||||||
<el-col :span="12">
|
<el-form-item prop="taskName" :label="$t('db.taskName')" required>
|
||||||
<el-form-item prop="taskName" :label="$t('db.taskName')" required>
|
<el-input v-model.trim="form.taskName" auto-complete="off" />
|
||||||
<el-input v-model.trim="form.taskName" auto-complete="off" />
|
</el-form-item>
|
||||||
</el-form-item>
|
</el-col>
|
||||||
</el-col>
|
|
||||||
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item prop="taskCron" label="cron" required>
|
<el-form-item prop="taskCron" label="cron" required>
|
||||||
<CrontabInput v-model="form.taskCron" />
|
<CrontabInput v-model="form.taskCron" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item prop="status" :label="$t('common.status')" label-width="60" required>
|
<el-form-item prop="status" :label="$t('common.status')" label-width="60" required>
|
||||||
<el-switch
|
<el-switch
|
||||||
@@ -61,81 +59,70 @@
|
|||||||
<monaco-editor height="200px" class="task-sql" language="sql" v-model="form.dataSql" />
|
<monaco-editor height="200px" class="task-sql" language="sql" v-model="form.dataSql" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-row>
|
||||||
<el-row class="w100">
|
<el-col :span="12">
|
||||||
<el-col :span="12">
|
<el-form-item prop="targetTableName" :label="$t('db.targetDbTable')" required>
|
||||||
<el-form-item prop="targetTableName" :label="$t('db.targetDbTable')" required>
|
<el-select v-model="form.targetTableName" filterable>
|
||||||
<el-select v-model="form.targetTableName" filterable>
|
<el-option
|
||||||
<el-option
|
v-for="item in state.targetTableList"
|
||||||
v-for="item in state.targetTableList"
|
:key="item.tableName"
|
||||||
:key="item.tableName"
|
:label="item.tableName + (item.tableComment && '-' + item.tableComment)"
|
||||||
:label="item.tableName + (item.tableComment && '-' + item.tableComment)"
|
:value="item.tableName"
|
||||||
:value="item.tableName"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item prop="pageSize" :label="$t('db.pageSize')" required>
|
|
||||||
<el-input
|
|
||||||
type="number"
|
|
||||||
v-model.number="form.pageSize"
|
|
||||||
:placeholder="$t('db.pageSizePlaceholder')"
|
|
||||||
auto-complete="off"
|
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-select>
|
||||||
</el-col>
|
</el-form-item>
|
||||||
</el-row>
|
</el-col>
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
<el-col :span="12">
|
||||||
<el-row class="w100">
|
<el-form-item prop="pageSize" :label="$t('db.pageSize')" required>
|
||||||
<el-col :span="12">
|
<el-input type="number" v-model.number="form.pageSize" :placeholder="$t('db.pageSizePlaceholder')" auto-complete="off" />
|
||||||
<el-form-item class="w100" prop="updField">
|
</el-form-item>
|
||||||
<template #label>
|
</el-col>
|
||||||
{{ $t('db.updateField') }}
|
</el-row>
|
||||||
<el-tooltip :content="$t('db.updateFieldTips')" placement="top">
|
|
||||||
<SvgIcon name="question-filled" />
|
|
||||||
</el-tooltip>
|
|
||||||
</template>
|
|
||||||
<el-input v-model.trim="form.updField" :placeholder="$t('db.updateFiledPlaceholder')" auto-complete="off" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
|
|
||||||
<el-col :span="12">
|
<el-row>
|
||||||
<el-form-item class="w100" prop="updFieldVal">
|
<el-col :span="12">
|
||||||
<template #label>
|
<el-form-item class="w100" prop="updField">
|
||||||
{{ $t('db.updateFieldValue') }}
|
<template #label>
|
||||||
<el-tooltip :content="$t('db.updateFieldValueTips')" placement="top">
|
{{ $t('db.updateField') }}
|
||||||
<el-icon>
|
<el-tooltip :content="$t('db.updateFieldTips')" placement="top">
|
||||||
<question-filled />
|
<SvgIcon name="question-filled" />
|
||||||
</el-icon>
|
</el-tooltip>
|
||||||
</el-tooltip>
|
</template>
|
||||||
</template>
|
<el-input v-model.trim="form.updField" :placeholder="$t('db.updateFiledPlaceholder')" auto-complete="off" />
|
||||||
<el-input v-model.trim="form.updFieldVal" :placeholder="$t('db.updateFieldValuePlaceholder')" auto-complete="off" />
|
</el-form-item>
|
||||||
</el-form-item>
|
</el-col>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
<el-col :span="12">
|
||||||
<el-row class="w100">
|
<el-form-item class="w100" prop="updFieldVal">
|
||||||
<el-col :span="12">
|
<template #label>
|
||||||
<el-form-item class="w100" prop="updFieldSrc">
|
{{ $t('db.updateFieldValue') }}
|
||||||
<template #label>
|
<el-tooltip :content="$t('db.updateFieldValueTips')" placement="top">
|
||||||
{{ $t('db.fieldValueSrc') }}
|
<el-icon>
|
||||||
<el-tooltip :content="$t('db.fieldValueSrcTips')" placement="top">
|
<question-filled />
|
||||||
<el-icon>
|
</el-icon>
|
||||||
<question-filled />
|
</el-tooltip>
|
||||||
</el-icon>
|
</template>
|
||||||
</el-tooltip>
|
<el-input v-model.trim="form.updFieldVal" :placeholder="$t('db.updateFieldValuePlaceholder')" auto-complete="off" />
|
||||||
</template>
|
</el-form-item>
|
||||||
<el-input v-model.trim="form.updFieldSrc" :placeholder="$t('db.fieldValueSrcPlaceholder')" auto-complete="off" />
|
</el-col>
|
||||||
</el-form-item>
|
</el-row>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
<el-row>
|
||||||
</el-form-item>
|
<el-col :span="12">
|
||||||
|
<el-form-item class="w100" prop="updFieldSrc">
|
||||||
|
<template #label>
|
||||||
|
{{ $t('db.fieldValueSrc') }}
|
||||||
|
<el-tooltip :content="$t('db.fieldValueSrcTips')" placement="top">
|
||||||
|
<el-icon>
|
||||||
|
<question-filled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
<el-input v-model.trim="form.updFieldSrc" :placeholder="$t('db.fieldValueSrcPlaceholder')" auto-complete="off" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane :label="$t('db.fieldMap')" :name="fieldTab" :disabled="!baseFieldCompleted">
|
<el-tab-pane :label="$t('db.fieldMap')" :name="fieldTab" :disabled="!baseFieldCompleted">
|
||||||
|
|||||||
@@ -50,7 +50,6 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineAsyncComponent, onMounted, reactive, ref, Ref, toRefs } from 'vue';
|
import { defineAsyncComponent, onMounted, reactive, ref, Ref, toRefs } from 'vue';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
||||||
import { dbApi } from './api';
|
import { dbApi } from './api';
|
||||||
import PageTable from '@/components/pagetable/PageTable.vue';
|
import PageTable from '@/components/pagetable/PageTable.vue';
|
||||||
import { TableColumn } from '@/components/pagetable';
|
import { TableColumn } from '@/components/pagetable';
|
||||||
@@ -58,13 +57,10 @@ import { hasPerms } from '@/components/auth/auth';
|
|||||||
import { SearchItem } from '@/components/SearchForm';
|
import { SearchItem } from '@/components/SearchForm';
|
||||||
import { DbDataSyncRecentStateEnum, DbDataSyncRunningStateEnum } from './enums';
|
import { DbDataSyncRecentStateEnum, DbDataSyncRunningStateEnum } from './enums';
|
||||||
import { useI18nConfirm, useI18nCreateTitle, useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI18nEditTitle, useI18nOperateSuccessMsg } from '@/hooks/useI18n';
|
import { useI18nConfirm, useI18nCreateTitle, useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI18nEditTitle, useI18nOperateSuccessMsg } from '@/hooks/useI18n';
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
const DataSyncTaskEdit = defineAsyncComponent(() => import('./SyncTaskEdit.vue'));
|
const DataSyncTaskEdit = defineAsyncComponent(() => import('./SyncTaskEdit.vue'));
|
||||||
const DataSyncTaskLog = defineAsyncComponent(() => import('./SyncTaskLog.vue'));
|
const DataSyncTaskLog = defineAsyncComponent(() => import('./SyncTaskLog.vue'));
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const perms = {
|
const perms = {
|
||||||
save: 'db:sync:save',
|
save: 'db:sync:save',
|
||||||
del: 'db:sync:del',
|
del: 'db:sync:del',
|
||||||
@@ -77,6 +73,7 @@ const searchItems = [SearchItem.input('name', 'common.name')];
|
|||||||
// 任务名、修改人、修改时间、最近一次任务执行状态、状态(停用启用)、操作
|
// 任务名、修改人、修改时间、最近一次任务执行状态、状态(停用启用)、操作
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
TableColumn.new('taskName', 'db.taskName'),
|
TableColumn.new('taskName', 'db.taskName'),
|
||||||
|
TableColumn.new('cron', 'Cron'),
|
||||||
TableColumn.new('runningState', 'db.runState').typeTag(DbDataSyncRunningStateEnum),
|
TableColumn.new('runningState', 'db.runState').typeTag(DbDataSyncRunningStateEnum),
|
||||||
TableColumn.new('recentState', 'db.recentState').typeTag(DbDataSyncRecentStateEnum),
|
TableColumn.new('recentState', 'db.recentState').typeTag(DbDataSyncRecentStateEnum),
|
||||||
TableColumn.new('status', 'common.status').isSlot(),
|
TableColumn.new('status', 'common.status').isSlot(),
|
||||||
|
|||||||
@@ -112,11 +112,7 @@ func (d *DataSyncTask) Run(rc *req.Ctx) {
|
|||||||
func (d *DataSyncTask) Stop(rc *req.Ctx) {
|
func (d *DataSyncTask) Stop(rc *req.Ctx) {
|
||||||
taskId := d.getTaskId(rc)
|
taskId := d.getTaskId(rc)
|
||||||
rc.ReqParam = taskId
|
rc.ReqParam = taskId
|
||||||
|
biz.ErrIsNil(d.dataSyncTaskApp.StopTask(rc.MetaCtx, taskId))
|
||||||
task := new(entity.DataSyncTask)
|
|
||||||
task.Id = taskId
|
|
||||||
task.RunningState = entity.DataSyncTaskRunStateStop
|
|
||||||
_ = d.dataSyncTaskApp.UpdateById(rc.MetaCtx, task)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DataSyncTask) GetTask(rc *req.Ctx) {
|
func (d *DataSyncTask) GetTask(rc *req.Ctx) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import "time"
|
|||||||
type DataSyncTaskListVO struct {
|
type DataSyncTaskListVO struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
TaskName string `json:"taskName"`
|
TaskName string `json:"taskName"`
|
||||||
|
TaskCron string `json:"cron"`
|
||||||
CreateTime *time.Time `json:"createTime"`
|
CreateTime *time.Time `json:"createTime"`
|
||||||
Creator string `json:"creator"`
|
Creator string `json:"creator"`
|
||||||
UpdateTime *time.Time `json:"updateTime"`
|
UpdateTime *time.Time `json:"updateTime"`
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ package application
|
|||||||
import (
|
import (
|
||||||
"cmp"
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"mayfly-go/internal/db/dbm/dbi"
|
"mayfly-go/internal/db/dbm/dbi"
|
||||||
"mayfly-go/internal/db/domain/entity"
|
"mayfly-go/internal/db/domain/entity"
|
||||||
"mayfly-go/internal/db/domain/repository"
|
"mayfly-go/internal/db/domain/repository"
|
||||||
"mayfly-go/pkg/base"
|
"mayfly-go/pkg/base"
|
||||||
|
"mayfly-go/pkg/cache"
|
||||||
"mayfly-go/pkg/contextx"
|
"mayfly-go/pkg/contextx"
|
||||||
"mayfly-go/pkg/errorx"
|
"mayfly-go/pkg/errorx"
|
||||||
"mayfly-go/pkg/logx"
|
"mayfly-go/pkg/logx"
|
||||||
@@ -42,6 +42,8 @@ type DataSyncTask interface {
|
|||||||
|
|
||||||
RunCronJob(ctx context.Context, id uint64) error
|
RunCronJob(ctx context.Context, id uint64) error
|
||||||
|
|
||||||
|
StopTask(ctx context.Context, id uint64) error
|
||||||
|
|
||||||
GetTaskLogList(condition *entity.DataSyncLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
GetTaskLogList(condition *entity.DataSyncLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,17 +119,10 @@ func (app *dataSyncAppImpl) RemoveCronJobById(taskId uint64) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
scheduler.RemoveByKey(task.TaskKey)
|
scheduler.RemoveByKey(task.TaskKey)
|
||||||
}
|
}
|
||||||
}
|
app.MarkStop(taskId)
|
||||||
|
|
||||||
func (app *dataSyncAppImpl) changeRunningState(id uint64, state int8) {
|
|
||||||
task := new(entity.DataSyncTask)
|
|
||||||
task.Id = id
|
|
||||||
task.RunningState = state
|
|
||||||
_ = app.UpdateById(context.Background(), task)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *dataSyncAppImpl) RunCronJob(ctx context.Context, id uint64) error {
|
func (app *dataSyncAppImpl) RunCronJob(ctx context.Context, id uint64) error {
|
||||||
// 查询最新的任务信息
|
|
||||||
task, err := app.GetById(id)
|
task, err := app.GetById(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("task not found")
|
return errorx.NewBiz("task not found")
|
||||||
@@ -135,8 +130,9 @@ func (app *dataSyncAppImpl) RunCronJob(ctx context.Context, id uint64) error {
|
|||||||
if task.RunningState == entity.DataSyncTaskRunStateRunning {
|
if task.RunningState == entity.DataSyncTaskRunStateRunning {
|
||||||
return errorx.NewBiz("the task is in progress")
|
return errorx.NewBiz("the task is in progress")
|
||||||
}
|
}
|
||||||
// 开始运行时,修改状态为运行中
|
|
||||||
app.changeRunningState(id, entity.DataSyncTaskRunStateRunning)
|
// 标记该任务运行中
|
||||||
|
app.MarkRunning(id)
|
||||||
|
|
||||||
logx.InfofContext(ctx, "start the data synchronization task: %s => %s", task.TaskName, task.TaskKey)
|
logx.InfofContext(ctx, "start the data synchronization task: %s => %s", task.TaskName, task.TaskKey)
|
||||||
|
|
||||||
@@ -183,8 +179,11 @@ func (app *dataSyncAppImpl) RunCronJob(ctx context.Context, id uint64) error {
|
|||||||
log.ErrText = fmt.Sprintf("execution failure: %s", err.Error())
|
log.ErrText = fmt.Sprintf("execution failure: %s", err.Error())
|
||||||
logx.ErrorContext(ctx, log.ErrText)
|
logx.ErrorContext(ctx, log.ErrText)
|
||||||
log.Status = entity.DataSyncTaskStateFail
|
log.Status = entity.DataSyncTaskStateFail
|
||||||
app.endRunning(task, log)
|
} else {
|
||||||
|
log.Status = entity.DataSyncTaskStateSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.endRunning(task, log)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -210,16 +209,6 @@ func (app *dataSyncAppImpl) doDataSync(ctx context.Context, sql string, task *en
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return syncLog, errorx.NewBiz("failed to connect to the target database: %s", err.Error())
|
return syncLog, errorx.NewBiz("failed to connect to the target database: %s", err.Error())
|
||||||
}
|
}
|
||||||
targetDbTx, err := targetConn.Begin()
|
|
||||||
if err != nil {
|
|
||||||
return syncLog, errorx.NewBiz("failed to start the target database transaction: %s", err.Error())
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
targetDbTx.Rollback()
|
|
||||||
err = fmt.Errorf("%v", r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// task.FieldMap为json数组字符串 [{"src":"id","target":"id"}],转为map
|
// task.FieldMap为json数组字符串 [{"src":"id","target":"id"}],转为map
|
||||||
var fieldMap []map[string]string
|
var fieldMap []map[string]string
|
||||||
@@ -227,13 +216,11 @@ func (app *dataSyncAppImpl) doDataSync(ctx context.Context, sql string, task *en
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return syncLog, errorx.NewBiz("there was an error parsing the field map json: %s", err.Error())
|
return syncLog, errorx.NewBiz("there was an error parsing the field map json: %s", err.Error())
|
||||||
}
|
}
|
||||||
var updFieldType *dbi.DbDataType
|
|
||||||
|
|
||||||
// 记录本次同步数据总数
|
// 记录本次同步数据总数
|
||||||
total := 0
|
total := 0
|
||||||
batchSize := task.PageSize
|
batchSize := task.PageSize
|
||||||
result := make([]map[string]any, 0)
|
result := make([]map[string]any, 0)
|
||||||
var queryColumns []*dbi.QueryColumn
|
|
||||||
|
|
||||||
// 如果有数据库别名,则从UpdField中去掉数据库别名, 如:a.id => id,用于获取字段具体名称
|
// 如果有数据库别名,则从UpdField中去掉数据库别名, 如:a.id => id,用于获取字段具体名称
|
||||||
updFieldName := task.UpdField
|
updFieldName := task.UpdField
|
||||||
@@ -255,23 +242,10 @@ func (app *dataSyncAppImpl) doDataSync(ctx context.Context, sql string, task *en
|
|||||||
})
|
})
|
||||||
|
|
||||||
_, err = srcConn.WalkQueryRows(context.Background(), sql, func(row map[string]any, columns []*dbi.QueryColumn) error {
|
_, err = srcConn.WalkQueryRows(context.Background(), sql, func(row map[string]any, columns []*dbi.QueryColumn) error {
|
||||||
if len(queryColumns) == 0 {
|
|
||||||
queryColumns = columns
|
|
||||||
|
|
||||||
// 遍历columns 取task.UpdField的字段类型
|
|
||||||
updFieldType = dbi.DefaultDbDataType
|
|
||||||
for _, column := range columns {
|
|
||||||
if strings.EqualFold(column.Name, updFieldName) {
|
|
||||||
updFieldType = column.DbDataType
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
total++
|
total++
|
||||||
result = append(result, row)
|
result = append(result, row)
|
||||||
if total%batchSize == 0 {
|
if total%batchSize == 0 {
|
||||||
if err := app.srcData2TargetDb(result, fieldMap, updFieldType, updFieldName, task, targetConn, targetDbTx, targetInsertColumns); err != nil {
|
if err := app.srcData2TargetDb(result, fieldMap, updFieldName, task, targetConn, targetInsertColumns); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,43 +256,37 @@ func (app *dataSyncAppImpl) doDataSync(ctx context.Context, sql string, task *en
|
|||||||
app.saveLog(syncLog)
|
app.saveLog(syncLog)
|
||||||
|
|
||||||
result = result[:0]
|
result = result[:0]
|
||||||
|
|
||||||
|
// 运行过程中,判断状态是否为已关闭,是则结束运行,否则继续运行
|
||||||
|
if !app.IsRunning(task.Id) {
|
||||||
|
return errorx.NewBiz("the task has been terminated manually")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
targetDbTx.Rollback()
|
|
||||||
return syncLog, err
|
return syncLog, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理剩余的数据
|
// 处理剩余的数据
|
||||||
if len(result) > 0 {
|
if len(result) > 0 {
|
||||||
if err := app.srcData2TargetDb(result, fieldMap, updFieldType, updFieldName, task, targetConn, targetDbTx, targetInsertColumns); err != nil {
|
if err := app.srcData2TargetDb(result, fieldMap, updFieldName, task, targetConn, targetInsertColumns); err != nil {
|
||||||
targetDbTx.Rollback()
|
|
||||||
return syncLog, err
|
return syncLog, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果是mssql,暂不手动提交事务,否则报错 mssql: The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
|
|
||||||
if err := targetDbTx.Commit(); err != nil {
|
|
||||||
if targetConn.Info.Type != dbi.ToDbType("mssql") {
|
|
||||||
return syncLog, errorx.NewBiz("data synchronization - The target database transaction failed to commit: %s", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logx.InfofContext(ctx, "synchronous task: [%s], finished execution, save records successfully: [%d]", task.TaskName, total)
|
logx.InfofContext(ctx, "synchronous task: [%s], finished execution, save records successfully: [%d]", task.TaskName, total)
|
||||||
|
|
||||||
// 保存执行成功日志
|
// 执行成功日志
|
||||||
syncLog.ErrText = fmt.Sprintf("the synchronous task was executed successfully. New data: %d", total)
|
syncLog.ErrText = fmt.Sprintf("the synchronous task was executed successfully. New data: %d", total)
|
||||||
syncLog.Status = entity.DataSyncTaskStateSuccess
|
|
||||||
syncLog.ResNum = total
|
syncLog.ResNum = total
|
||||||
app.endRunning(task, syncLog)
|
|
||||||
|
|
||||||
return syncLog, nil
|
return syncLog, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *dataSyncAppImpl) srcData2TargetDb(srcRes []map[string]any, fieldMap []map[string]string, updFieldType *dbi.DbDataType, updFieldName string, task *entity.DataSyncTask, targetDbConn *dbi.DbConn, targetDbTx *sql.Tx, targetInsertColumns []dbi.Column) error {
|
func (app *dataSyncAppImpl) srcData2TargetDb(srcRes []map[string]any, fieldMap []map[string]string, updFieldName string, task *entity.DataSyncTask, targetDbConn *dbi.DbConn, targetInsertColumns []dbi.Column) (err error) {
|
||||||
// 遍历res,组装数据
|
// 遍历res,组装数据
|
||||||
var targetData = make([]map[string]any, 0)
|
var targetData = make([]map[string]any, 0)
|
||||||
for _, srcData := range srcRes {
|
for _, srcData := range srcRes {
|
||||||
@@ -341,6 +309,37 @@ func (app *dataSyncAppImpl) srcData2TargetDb(srcRes []map[string]any, fieldMap [
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 执行插入
|
// 执行插入
|
||||||
|
targetDialect := targetDbConn.GetDialect()
|
||||||
|
|
||||||
|
// 生成目标数据库批量插入sql,并执行
|
||||||
|
sqls := targetDialect.GetSQLGenerator().GenInsert(task.TargetTableName, targetInsertColumns, tragetValues, cmp.Or(task.DuplicateStrategy, dbi.DuplicateStrategyNone))
|
||||||
|
|
||||||
|
// 开启本批次执行事务
|
||||||
|
targetDbTx, err := targetDbConn.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return errorx.NewBiz("failed to start the target database transaction: %s", err.Error())
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
targetDbTx.Rollback()
|
||||||
|
err = fmt.Errorf("%v", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for _, sql := range sqls {
|
||||||
|
_, err := targetDbTx.Exec(sql)
|
||||||
|
if err != nil {
|
||||||
|
targetDbTx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是mssql,暂不手动提交事务,否则报错 mssql: The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
|
||||||
|
if err := targetDbTx.Commit(); err != nil {
|
||||||
|
if targetDbConn.Info.Type != dbi.ToDbType("mssql") {
|
||||||
|
return errorx.NewBiz("data synchronization - The target database transaction failed to commit: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setUpdateFieldVal := func(field string) {
|
setUpdateFieldVal := func(field string) {
|
||||||
// 解决字段大小写问题
|
// 解决字段大小写问题
|
||||||
@@ -351,27 +350,20 @@ func (app *dataSyncAppImpl) srcData2TargetDb(srcRes []map[string]any, fieldMap [
|
|||||||
|
|
||||||
task.UpdFieldVal = cast.ToString(updFieldVal)
|
task.UpdFieldVal = cast.ToString(updFieldVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果指定了更新字段,则以更新字段取值
|
// 如果指定了更新字段,则以更新字段取值
|
||||||
setUpdateFieldVal(cmp.Or(task.UpdFieldSrc, updFieldName))
|
setUpdateFieldVal(cmp.Or(task.UpdFieldSrc, updFieldName))
|
||||||
|
|
||||||
targetDialect := targetDbConn.GetDialect()
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// 生成目标数据库批量插入sql,并执行
|
func (app *dataSyncAppImpl) StopTask(ctx context.Context, taskId uint64) error {
|
||||||
sqls := targetDialect.GetSQLGenerator().GenInsert(task.TargetTableName, targetInsertColumns, tragetValues, cmp.Or(task.DuplicateStrategy, dbi.DuplicateStrategyNone))
|
task := new(entity.DataSyncTask)
|
||||||
for _, sql := range sqls {
|
task.Id = taskId
|
||||||
_, err := targetDbTx.Exec(sql)
|
task.RunningState = entity.DataSyncTaskRunStateStop
|
||||||
if err != nil {
|
if err := app.UpdateById(ctx, task); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
app.MarkStop(taskId)
|
||||||
// 运行过程中,判断状态是否为已关闭,是则结束运行,否则继续运行
|
|
||||||
taskParam, _ := app.GetById(task.Id)
|
|
||||||
if taskParam.RunningState == entity.DataSyncTaskRunStateStop {
|
|
||||||
return errorx.NewBiz("the task has been terminated manually")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,9 +374,7 @@ func (app *dataSyncAppImpl) endRunning(taskEntity *entity.DataSyncTask, log *ent
|
|||||||
task := new(entity.DataSyncTask)
|
task := new(entity.DataSyncTask)
|
||||||
task.Id = taskEntity.Id
|
task.Id = taskEntity.Id
|
||||||
task.RecentState = state
|
task.RecentState = state
|
||||||
if state == entity.DataSyncTaskStateSuccess {
|
task.UpdFieldVal = taskEntity.UpdFieldVal
|
||||||
task.UpdFieldVal = taskEntity.UpdFieldVal
|
|
||||||
}
|
|
||||||
task.RunningState = entity.DataSyncTaskRunStateReady
|
task.RunningState = entity.DataSyncTaskRunStateReady
|
||||||
// 运行失败之后设置任务状态为禁用
|
// 运行失败之后设置任务状态为禁用
|
||||||
//if state == entity.DataSyncTaskStateFail {
|
//if state == entity.DataSyncTaskStateFail {
|
||||||
@@ -394,6 +384,7 @@ func (app *dataSyncAppImpl) endRunning(taskEntity *entity.DataSyncTask, log *ent
|
|||||||
_ = app.UpdateById(context.Background(), task)
|
_ = app.UpdateById(context.Background(), task)
|
||||||
// 保存执行日志
|
// 保存执行日志
|
||||||
app.saveLog(log)
|
app.saveLog(log)
|
||||||
|
app.MarkStop(task.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *dataSyncAppImpl) saveLog(log *entity.DataSyncLog) {
|
func (app *dataSyncAppImpl) saveLog(log *entity.DataSyncLog) {
|
||||||
@@ -440,3 +431,23 @@ func (app *dataSyncAppImpl) InitCronJob() {
|
|||||||
func (app *dataSyncAppImpl) GetTaskLogList(condition *entity.DataSyncLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
func (app *dataSyncAppImpl) GetTaskLogList(condition *entity.DataSyncLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
||||||
return app.dbDataSyncLogRepo.GetTaskLogList(condition, pageParam, toEntity, orderBy...)
|
return app.dbDataSyncLogRepo.GetTaskLogList(condition, pageParam, toEntity, orderBy...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarkRunning 标记任务执行中
|
||||||
|
func (app *dataSyncAppImpl) MarkRunning(taskId uint64) {
|
||||||
|
task := new(entity.DataSyncTask)
|
||||||
|
task.Id = taskId
|
||||||
|
task.RunningState = entity.DataSyncTaskRunStateRunning
|
||||||
|
_ = app.UpdateById(context.Background(), task)
|
||||||
|
|
||||||
|
cache.Set(fmt.Sprintf("mayfly:db:syncdata:%d", taskId), 1, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkStop 标记任务结束
|
||||||
|
func (app *dataSyncAppImpl) MarkStop(taskId uint64) {
|
||||||
|
cache.Del(fmt.Sprintf("mayfly:db:syncdata:%d", taskId))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRunning 判断任务是否执行中
|
||||||
|
func (app *dataSyncAppImpl) IsRunning(taskId uint64) bool {
|
||||||
|
return cache.GetStr(fmt.Sprintf("mayfly:db:syncdata:%d", taskId)) != ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ func (d *dbSqlExecAppImpl) Exec(ctx context.Context, execSqlReq *dto.DbSqlExecRe
|
|||||||
return allExecRes, nil
|
return allExecRes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mysql parser with语句会分解析为两条,故需要特殊处理
|
||||||
|
currentWithSql := ""
|
||||||
for _, stmt := range stmts {
|
for _, stmt := range stmts {
|
||||||
var execRes *dto.DbSqlExecRes
|
var execRes *dto.DbSqlExecRes
|
||||||
var err error
|
var err error
|
||||||
@@ -143,7 +145,8 @@ func (d *dbSqlExecAppImpl) Exec(ctx context.Context, execSqlReq *dto.DbSqlExecRe
|
|||||||
sql := stmt.GetText()
|
sql := stmt.GetText()
|
||||||
dbSqlExecRecord := createSqlExecRecord(ctx, execSqlReq, sql)
|
dbSqlExecRecord := createSqlExecRecord(ctx, execSqlReq, sql)
|
||||||
dbSqlExecRecord.Type = entity.DbSqlExecTypeOther
|
dbSqlExecRecord.Type = entity.DbSqlExecTypeOther
|
||||||
sqlExec := &sqlExecParam{DbConn: dbConn, Sql: sql, Procdef: flowProcdef, Stmt: stmt, SqlExecRecord: dbSqlExecRecord}
|
sqlExec := &sqlExecParam{DbConn: dbConn, Sql: currentWithSql + sql, Procdef: flowProcdef, Stmt: stmt, SqlExecRecord: dbSqlExecRecord}
|
||||||
|
currentWithSql = ""
|
||||||
|
|
||||||
switch stmt.(type) {
|
switch stmt.(type) {
|
||||||
case *sqlstmt.SimpleSelectStmt:
|
case *sqlstmt.SimpleSelectStmt:
|
||||||
@@ -152,6 +155,8 @@ func (d *dbSqlExecAppImpl) Exec(ctx context.Context, execSqlReq *dto.DbSqlExecRe
|
|||||||
execRes, err = d.doSelect(ctx, sqlExec)
|
execRes, err = d.doSelect(ctx, sqlExec)
|
||||||
case *sqlstmt.OtherReadStmt:
|
case *sqlstmt.OtherReadStmt:
|
||||||
execRes, err = d.doOtherRead(ctx, sqlExec)
|
execRes, err = d.doOtherRead(ctx, sqlExec)
|
||||||
|
case *sqlstmt.WithStmt:
|
||||||
|
currentWithSql = sql
|
||||||
case *sqlstmt.UpdateStmt:
|
case *sqlstmt.UpdateStmt:
|
||||||
execRes, err = d.doUpdate(ctx, sqlExec)
|
execRes, err = d.doUpdate(ctx, sqlExec)
|
||||||
case *sqlstmt.DeleteStmt:
|
case *sqlstmt.DeleteStmt:
|
||||||
@@ -174,9 +179,13 @@ func (d *dbSqlExecAppImpl) Exec(ctx context.Context, execSqlReq *dto.DbSqlExecRe
|
|||||||
execRes, err = d.doExec(ctx, dbConn, sql)
|
execRes, err = d.doExec(ctx, dbConn, sql)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if currentWithSql != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if execRes == nil {
|
if execRes == nil {
|
||||||
execRes = &dto.DbSqlExecRes{Sql: sql}
|
execRes = &dto.DbSqlExecRes{Sql: sqlExec.Sql}
|
||||||
}
|
}
|
||||||
execRes.ErrorMsg = err.Error()
|
execRes.ErrorMsg = err.Error()
|
||||||
} else {
|
} else {
|
||||||
@@ -624,7 +633,7 @@ func isInsert(sql string) bool {
|
|||||||
|
|
||||||
func isOtherQuery(sql string) bool {
|
func isOtherQuery(sql string) bool {
|
||||||
sqlPrefix := strings.ToLower(sql[:10])
|
sqlPrefix := strings.ToLower(sql[:10])
|
||||||
return strings.Contains(sqlPrefix, "explain") || strings.Contains(sqlPrefix, "show")
|
return strings.Contains(sqlPrefix, "explain") || strings.Contains(sqlPrefix, "show") || strings.Contains(sqlPrefix, "with")
|
||||||
}
|
}
|
||||||
|
|
||||||
func isDDL(sql string) bool {
|
func isDDL(sql string) bool {
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ func (v *MysqlVisitor) VisitDmlStatement(ctx *mysqlparser.DmlStatementContext) i
|
|||||||
if ssc := ctx.SelectStatement(); ssc != nil {
|
if ssc := ctx.SelectStatement(); ssc != nil {
|
||||||
return ssc.Accept(v)
|
return ssc.Accept(v)
|
||||||
}
|
}
|
||||||
|
if withStmt := ctx.WithStatement(); withStmt != nil {
|
||||||
|
return withStmt.Accept(v)
|
||||||
|
}
|
||||||
if usc := ctx.UpdateStatement(); usc != nil {
|
if usc := ctx.UpdateStatement(); usc != nil {
|
||||||
return usc.Accept(v)
|
return usc.Accept(v)
|
||||||
}
|
}
|
||||||
@@ -94,6 +97,12 @@ func (v *MysqlVisitor) VisitUtilityStatement(ctx *mysqlparser.UtilityStatementCo
|
|||||||
return sqlstmt.NewNode(ctx.GetParser(), ctx)
|
return sqlstmt.NewNode(ctx.GetParser(), ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *MysqlVisitor) VisitWithStatement(ctx *mysqlparser.WithStatementContext) interface{} {
|
||||||
|
ort := new(sqlstmt.WithStmt)
|
||||||
|
ort.Node = sqlstmt.NewNode(ctx.GetParser(), ctx)
|
||||||
|
return ort
|
||||||
|
}
|
||||||
|
|
||||||
func (v *MysqlVisitor) VisitSimpleSelect(ctx *mysqlparser.SimpleSelectContext) interface{} {
|
func (v *MysqlVisitor) VisitSimpleSelect(ctx *mysqlparser.SimpleSelectContext) interface{} {
|
||||||
sss := new(sqlstmt.SimpleSelectStmt)
|
sss := new(sqlstmt.SimpleSelectStmt)
|
||||||
sss.Node = sqlstmt.NewNode(ctx.GetParser(), ctx)
|
sss.Node = sqlstmt.NewNode(ctx.GetParser(), ctx)
|
||||||
|
|||||||
@@ -70,6 +70,10 @@ type OtherReadStmt struct {
|
|||||||
*Node
|
*Node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WithStmt struct {
|
||||||
|
*Node
|
||||||
|
}
|
||||||
|
|
||||||
func IsSelectStmt(stmt Stmt) bool {
|
func IsSelectStmt(stmt Stmt) bool {
|
||||||
return reflect.TypeOf(stmt).AssignableTo(reflect.TypeOf(&SelectStmt{}))
|
return reflect.TypeOf(stmt).AssignableTo(reflect.TypeOf(&SelectStmt{}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ const (
|
|||||||
DataSyncTaskStatusDisable int8 = -1 // 禁用状态
|
DataSyncTaskStatusDisable int8 = -1 // 禁用状态
|
||||||
|
|
||||||
DataSyncTaskStateSuccess int8 = 1 // 执行成功状态
|
DataSyncTaskStateSuccess int8 = 1 // 执行成功状态
|
||||||
DataSyncTaskStateRunning int8 = 2 // 执行成功状态
|
DataSyncTaskStateRunning int8 = 2 // 执行中状态
|
||||||
DataSyncTaskStateFail int8 = -1 // 执行失败状态
|
DataSyncTaskStateFail int8 = -1 // 执行失败状态
|
||||||
|
|
||||||
DataSyncTaskRunStateRunning int8 = 1 // 运行中状态
|
DataSyncTaskRunStateRunning int8 = 1 // 运行中状态
|
||||||
|
|||||||
10
server/pkg/cache/str_cache.go
vendored
10
server/pkg/cache/str_cache.go
vendored
@@ -5,7 +5,6 @@ import (
|
|||||||
"mayfly-go/pkg/logx"
|
"mayfly-go/pkg/logx"
|
||||||
"mayfly-go/pkg/rediscli"
|
"mayfly-go/pkg/rediscli"
|
||||||
"mayfly-go/pkg/utils/anyx"
|
"mayfly-go/pkg/utils/anyx"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -22,7 +21,7 @@ func GetStr(key string) string {
|
|||||||
if val == nil {
|
if val == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return val.(string)
|
return cast.ToString(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
if res, err := rediscli.Get(key); err == nil {
|
if res, err := rediscli.Get(key); err == nil {
|
||||||
@@ -36,12 +35,7 @@ func GetInt(key string) int {
|
|||||||
if val == "" {
|
if val == "" {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if intV, err := strconv.Atoi(val); err != nil {
|
return cast.ToInt(key)
|
||||||
logx.Error("获取缓存中的int值转换失败", err)
|
|
||||||
return 0
|
|
||||||
} else {
|
|
||||||
return intV
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 获取缓存值,并使用json反序列化。返回是否获取成功。若不存在或者解析失败,则返回false
|
// Get 获取缓存值,并使用json反序列化。返回是否获取成功。若不存在或者解析失败,则返回false
|
||||||
|
|||||||
Reference in New Issue
Block a user