2024-03-15 09:01:51 +00:00
package api
import (
2024-10-21 22:27:42 +08:00
"context"
2024-10-20 03:52:23 +00:00
"fmt"
2024-03-15 09:01:51 +00:00
"mayfly-go/internal/db/api/form"
"mayfly-go/internal/db/api/vo"
"mayfly-go/internal/db/application"
2024-10-20 03:52:23 +00:00
"mayfly-go/internal/db/dbm/dbi"
"mayfly-go/internal/db/dbm/sqlparser"
2024-03-15 09:01:51 +00:00
"mayfly-go/internal/db/domain/entity"
2024-11-20 22:43:53 +08:00
"mayfly-go/internal/db/imsg"
2024-10-21 22:27:42 +08:00
fileapp "mayfly-go/internal/file/application"
2024-10-20 03:52:23 +00:00
msgapp "mayfly-go/internal/msg/application"
msgdto "mayfly-go/internal/msg/application/dto"
tagapp "mayfly-go/internal/tag/application"
2024-03-15 09:01:51 +00:00
"mayfly-go/pkg/biz"
2024-11-20 22:43:53 +08:00
"mayfly-go/pkg/i18n"
2024-10-20 03:52:23 +00:00
"mayfly-go/pkg/model"
2024-03-15 09:01:51 +00:00
"mayfly-go/pkg/req"
2024-10-20 03:52:23 +00:00
"mayfly-go/pkg/utils/anyx"
2024-11-20 22:43:53 +08:00
"mayfly-go/pkg/utils/collx"
2024-10-20 03:52:23 +00:00
"mayfly-go/pkg/utils/stringx"
"mayfly-go/pkg/ws"
2024-03-15 09:01:51 +00:00
"strings"
2024-10-20 03:52:23 +00:00
"time"
2024-10-21 22:27:42 +08:00
"github.com/may-fly/cast"
2024-03-15 09:01:51 +00:00
)
type DbTransferTask struct {
DbTransferTask application . DbTransferTask ` inject:"DbTransferTaskApp" `
2024-10-20 03:52:23 +00:00
DbTransferFile application . DbTransferFile ` inject:"DbTransferFileApp" `
DbApp application . Db ` inject:"" `
TagApp tagapp . TagTree ` inject:"TagTreeApp" `
MsgApp msgapp . Msg ` inject:"" `
DbSqlExecApp application . DbSqlExec ` inject:"" `
2024-10-21 22:27:42 +08:00
FileApp fileapp . File ` inject:"" `
2024-03-15 09:01:51 +00:00
}
func ( d * DbTransferTask ) Tasks ( rc * req . Ctx ) {
queryCond , page := req . BindQueryAndPage [ * entity . DbTransferTaskQuery ] ( rc , new ( entity . DbTransferTaskQuery ) )
res , err := d . DbTransferTask . GetPageList ( queryCond , page , new ( [ ] vo . DbTransferTaskListVO ) )
biz . ErrIsNil ( err )
2024-10-20 03:52:23 +00:00
2024-10-21 22:27:42 +08:00
if res . List != nil {
list := res . List . ( * [ ] vo . DbTransferTaskListVO )
for _ , item := range * list {
item . RunningState = entity . DbTransferTaskRunStateSuccess
if d . DbTransferTask . IsRunning ( item . Id ) {
item . RunningState = entity . DbTransferTaskRunStateRunning
}
2024-10-20 03:52:23 +00:00
}
}
2024-03-15 09:01:51 +00:00
rc . ResData = res
}
func ( d * DbTransferTask ) SaveTask ( rc * req . Ctx ) {
reqForm := & form . DbTransferTaskForm { }
task := req . BindJsonAndCopyTo [ * entity . DbTransferTask ] ( rc , reqForm , new ( entity . DbTransferTask ) )
rc . ReqParam = reqForm
biz . ErrIsNil ( d . DbTransferTask . Save ( rc . MetaCtx , task ) )
}
func ( d * DbTransferTask ) DeleteTask ( rc * req . Ctx ) {
taskId := rc . PathParam ( "taskId" )
rc . ReqParam = taskId
ids := strings . Split ( taskId , "," )
2024-11-20 22:43:53 +08:00
uids := collx . ArrayMap [ string , uint64 ] ( ids , func ( val string ) uint64 {
return cast . ToUint64 ( val )
} )
2024-10-20 03:52:23 +00:00
biz . ErrIsNil ( d . DbTransferTask . DeleteById ( rc . MetaCtx , uids ... ) )
}
func ( d * DbTransferTask ) ChangeStatus ( rc * req . Ctx ) {
form := & form . DbTransferTaskStatusForm { }
task := req . BindJsonAndCopyTo [ * entity . DbTransferTask ] ( rc , form , new ( entity . DbTransferTask ) )
_ = d . DbTransferTask . UpdateById ( rc . MetaCtx , task )
task , err := d . DbTransferTask . GetById ( task . Id )
2024-11-20 22:43:53 +08:00
biz . ErrIsNil ( err , "task not found" )
2024-10-20 03:52:23 +00:00
d . DbTransferTask . AddCronJob ( rc . MetaCtx , task )
// 记录请求日志
rc . ReqParam = form
2024-03-15 09:01:51 +00:00
}
func ( d * DbTransferTask ) Run ( rc * req . Ctx ) {
2024-04-12 07:53:42 +00:00
taskId := uint64 ( rc . PathParamInt ( "taskId" ) )
logId , _ := d . DbTransferTask . CreateLog ( rc . MetaCtx , taskId )
go d . DbTransferTask . Run ( rc . MetaCtx , taskId , logId )
rc . ResData = logId
2024-03-15 09:01:51 +00:00
}
func ( d * DbTransferTask ) Stop ( rc * req . Ctx ) {
2024-03-28 22:20:39 +08:00
biz . ErrIsNil ( d . DbTransferTask . Stop ( rc . MetaCtx , uint64 ( rc . PathParamInt ( "taskId" ) ) ) )
2024-03-15 09:01:51 +00:00
}
2024-10-20 03:52:23 +00:00
func ( d * DbTransferTask ) Files ( rc * req . Ctx ) {
queryCond , page := req . BindQueryAndPage [ * entity . DbTransferFileQuery ] ( rc , new ( entity . DbTransferFileQuery ) )
res , err := d . DbTransferFile . GetPageList ( queryCond , page , new ( [ ] vo . DbTransferFileListVO ) )
biz . ErrIsNil ( err )
rc . ResData = res
}
func ( d * DbTransferTask ) FileDel ( rc * req . Ctx ) {
fileId := rc . PathParam ( "fileId" )
rc . ReqParam = fileId // 记录操作日志
ids := strings . Split ( fileId , "," )
uIds := make ( [ ] uint64 , len ( ids ) )
for _ , v := range ids {
2024-10-21 22:27:42 +08:00
uIds = append ( uIds , cast . ToUint64 ( v ) )
2024-10-20 03:52:23 +00:00
}
biz . ErrIsNil ( d . DbTransferFile . Delete ( rc . MetaCtx , uIds ... ) )
}
func ( d * DbTransferTask ) FileRun ( rc * req . Ctx ) {
fm := req . BindJsonAndValid ( rc , & form . DbTransferFileRunForm { } )
rc . ReqParam = fm
tFile , err := d . DbTransferFile . GetById ( fm . Id )
2024-11-20 22:43:53 +08:00
biz . IsTrue ( tFile != nil && err == nil , "file not found" )
2024-10-20 03:52:23 +00:00
targetDbConn , err := d . DbApp . GetDbConn ( fm . TargetDbId , fm . TargetDbName )
2024-11-20 22:43:53 +08:00
biz . ErrIsNilAppendErr ( err , "failed to connect to the target database: %s" )
2024-10-20 03:52:23 +00:00
biz . ErrIsNilAppendErr ( d . TagApp . CanAccess ( rc . GetLoginAccount ( ) . Id , targetDbConn . Info . CodePath ... ) , "%s" )
defer func ( ) {
if err := recover ( ) ; err != nil {
errInfo := anyx . ToString ( err )
if len ( errInfo ) > 300 {
errInfo = errInfo [ : 300 ] + "..."
}
2024-11-20 22:43:53 +08:00
d . MsgApp . CreateAndSend ( rc . GetLoginAccount ( ) , msgdto . ErrSysMsg ( i18n . T ( imsg . SqlScriptRunFail ) , fmt . Sprintf ( "[%s][%s] run failed: [%s]" , tFile . FileKey , targetDbConn . Info . GetLogDesc ( ) , errInfo ) ) . WithClientId ( fm . ClientId ) )
2024-10-20 03:52:23 +00:00
}
} ( )
go func ( ) {
d . fileRun ( rc . GetLoginAccount ( ) , fm , tFile , targetDbConn )
} ( )
}
func ( d * DbTransferTask ) fileRun ( la * model . LoginAccount , fm * form . DbTransferFileRunForm , tFile * entity . DbTransferFile , targetDbConn * dbi . DbConn ) {
2024-10-21 22:27:42 +08:00
filename , reader , err := d . FileApp . GetReader ( context . TODO ( ) , tFile . FileKey )
2024-10-20 03:52:23 +00:00
executedStatements := 0
progressId := stringx . Rand ( 32 )
laId := la . Id
ticker := time . NewTicker ( time . Second * 1 )
defer ticker . Stop ( )
if err != nil {
2024-11-20 22:43:53 +08:00
biz . ErrIsNilAppendErr ( err , "failed to connect to the target database: %s" )
2024-10-20 03:52:23 +00:00
}
2024-10-21 22:27:42 +08:00
err = sqlparser . SQLSplit ( reader , func ( sql string ) error {
2024-10-20 03:52:23 +00:00
select {
case <- ticker . C :
2024-11-20 22:43:53 +08:00
ws . SendJsonMsg ( ws . UserId ( laId ) , fm . ClientId , msgdto . InfoSqlProgressMsg ( i18n . T ( imsg . SqlScripRunProgress ) , & progressMsg {
2024-10-20 03:52:23 +00:00
Id : progressId ,
2024-10-21 22:27:42 +08:00
Title : filename ,
2024-10-20 03:52:23 +00:00
ExecutedStatements : executedStatements ,
Terminated : false ,
} ) . WithCategory ( progressCategory ) )
default :
}
executedStatements ++
_ , err = targetDbConn . Exec ( sql )
return err
} )
if err != nil {
2024-11-20 22:43:53 +08:00
biz . ErrIsNilAppendErr ( err , "sql execution failed: %s" )
2024-10-20 03:52:23 +00:00
}
2024-11-20 22:43:53 +08:00
d . MsgApp . CreateAndSend ( la , msgdto . SuccessSysMsg ( i18n . T ( imsg . SqlScriptRunSuccess ) , fmt . Sprintf ( "sql execution successfully: %s" , filename ) ) . WithClientId ( fm . ClientId ) )
2024-10-20 03:52:23 +00:00
}