From 73501a119ea1519aa776c72294c2db43610facb8 Mon Sep 17 00:00:00 2001 From: Nut He <18328704+hetao92@users.noreply.github.com> Date: Fri, 14 Apr 2023 17:52:00 +0800 Subject: [PATCH] fix: some issues (#541) * fix: some issues * mod: code review --- .../Import/TaskList/TemplateModal/index.tsx | 1 - app/pages/Import/TaskList/index.tsx | 6 +-- .../SchemaVisualization/index.module.less | 1 + app/utils/function.ts | 8 ++- .../api/studio/internal/service/datasource.go | 18 +++++-- server/api/studio/internal/service/import.go | 1 + .../internal/service/importer/importer.go | 1 + .../studio/internal/service/importer/task.go | 7 +-- .../internal/service/importer/taskmgr.go | 25 ++++++--- server/api/studio/pkg/utils/mutexMap.go | 52 ++++++++++++++++++ server/api/studio/pkg/utils/tools.go | 54 +++---------------- server/api/studio/studio.go | 4 +- 12 files changed, 104 insertions(+), 74 deletions(-) create mode 100644 server/api/studio/pkg/utils/mutexMap.go diff --git a/app/pages/Import/TaskList/TemplateModal/index.tsx b/app/pages/Import/TaskList/TemplateModal/index.tsx index 59d7ef27..9ce97a9b 100644 --- a/app/pages/Import/TaskList/TemplateModal/index.tsx +++ b/app/pages/Import/TaskList/TemplateModal/index.tsx @@ -79,7 +79,6 @@ const TemplateModal = (props: IProps) => { const validateAddress = useCallback((client) => { const msg = validateEmpty('address', client.address); - console.log('msg', msg); if(msg) return msg; const address = client.address.split(','); if(address.some(i => i.startsWith('http'))) { diff --git a/app/pages/Import/TaskList/index.tsx b/app/pages/Import/TaskList/index.tsx index 24af1bcb..756051a8 100644 --- a/app/pages/Import/TaskList/index.tsx +++ b/app/pages/Import/TaskList/index.tsx @@ -44,10 +44,8 @@ const TaskList = (props: IProps) => { const handleTaskStop = useCallback(async (id: number) => { clearTimeout(timer.current); const { code } = await stopTask(id); - if(code === 0) { - message.success(intl.get('import.stopImportingSuccess')); - getTaskList(); - } + code === 0 && message.success(intl.get('import.stopImportingSuccess')); + getTaskList(); }, []); const handleTaskDelete = useCallback(async (id: number) => { clearTimeout(timer.current); diff --git a/app/pages/Schema/SchemaConfig/List/SchemaVisualization/index.module.less b/app/pages/Schema/SchemaConfig/List/SchemaVisualization/index.module.less index 87accf57..059b49e2 100644 --- a/app/pages/Schema/SchemaConfig/List/SchemaVisualization/index.module.less +++ b/app/pages/Schema/SchemaConfig/List/SchemaVisualization/index.module.less @@ -20,6 +20,7 @@ } .tip { max-width: 600px; + min-width: 300px; background: #DBEFFF; border-radius: 3px; padding: 13px; diff --git a/app/utils/function.ts b/app/utils/function.ts index c96c6901..56bff9d9 100644 --- a/app/utils/function.ts +++ b/app/utils/function.ts @@ -11,11 +11,9 @@ export const handleVidStringName = (name: string, spaceVidType?: string) => { if (spaceVidType && spaceVidType === 'INT64') { return convertBigNumberToString(name); } - if (name.indexOf(`"`) > -1 && name.indexOf(`'`) === -1) { - return `'${name}'`; - } else { - return `"${name}"`; - } + // Add quotes to a string + // If there is '\n' in the string, it needs to be escaped + return JSON.stringify(name); }; export const convertBigNumberToString = (value: any) => { diff --git a/server/api/studio/internal/service/datasource.go b/server/api/studio/internal/service/datasource.go index e17b6c29..bc747661 100644 --- a/server/api/studio/internal/service/datasource.go +++ b/server/api/studio/internal/service/datasource.go @@ -111,11 +111,11 @@ func (d *datasourceService) Update(request types.DatasourceUpdateRequest) error } cfgStr, crypto, err := validate(typ, platform, cfg) if err != nil { - return err + return ecode.WithErrorMessage(ecode.ErrBadRequest, err) } err = d.update(datasourceId, request.Type, request.Platform, request.Name, cfgStr, crypto) if err != nil { - return err + return ecode.WithErrorMessage(ecode.ErrInternalServer, err) } return nil } @@ -184,14 +184,24 @@ func (d *datasourceService) Remove(request types.DatasourceRemoveRequest) error func (d *datasourceService) BatchRemove(request types.DatasourceBatchRemoveRequest) error { user := d.ctx.Value(auth.CtxKeyUserInfo{}).(*auth.AuthData) + var existingIDs []int + db.CtxDB.Model(&db.Datasource{}).Where("id in (?)", request.IDs).Pluck("id", &existingIDs) + if len(existingIDs) != len(request.IDs) { + var missingIDs []int + for _, id := range request.IDs { + if !utils.Contains(existingIDs, id) { + missingIDs = append(missingIDs, id) + } + } + return ecode.WithErrorMessage(ecode.ErrBadRequest, fmt.Errorf("some data are not found: %v", missingIDs)) + } result := db.CtxDB.Where("id IN (?) AND username = ?", request.IDs, user.Username).Delete(&db.Datasource{}) - if result.Error != nil { return d.gormErrorWrapper(result.Error) } if result.RowsAffected == 0 { - return ecode.WithErrorMessage(ecode.ErrBadRequest, fmt.Errorf("test"), "there is available item to delete") + return ecode.WithErrorMessage(ecode.ErrBadRequest, fmt.Errorf("no data found")) } return nil diff --git a/server/api/studio/internal/service/import.go b/server/api/studio/internal/service/import.go index 9bbcc365..310753b6 100644 --- a/server/api/studio/internal/service/import.go +++ b/server/api/studio/internal/service/import.go @@ -199,6 +199,7 @@ func (i *importService) CreateImportTask(req *types.CreateImportTaskRequest) (*t // start import if err = importer.StartImport(taskID); err != nil { task.TaskInfo.TaskStatus = importer.StatusAborted.String() + task.TaskInfo.TaskMessage = err.Error() importer.GetTaskMgr().AbortTask(taskID) return nil, ecode.WithErrorMessage(ecode.ErrInternalServer, err) } diff --git a/server/api/studio/internal/service/importer/importer.go b/server/api/studio/internal/service/importer/importer.go index 75ff0479..6fba01f5 100644 --- a/server/api/studio/internal/service/importer/importer.go +++ b/server/api/studio/internal/service/importer/importer.go @@ -57,6 +57,7 @@ func StartImport(taskID int) (err error) { abort() return } + task.Client.HasStarted = true err = mgr.Wait() if err != nil { task.TaskInfo.TaskStatus = StatusAborted.String() diff --git a/server/api/studio/internal/service/importer/task.go b/server/api/studio/internal/service/importer/task.go index 6befc0d0..5948713f 100644 --- a/server/api/studio/internal/service/importer/task.go +++ b/server/api/studio/internal/service/importer/task.go @@ -9,9 +9,10 @@ import ( ) type Client struct { - Cfg config.Configurator `json:"cfg,omitempty"` - Logger logger.Logger `json:"logger,omitempty"` - Manager manager.Manager `json:"manager,omitempty"` + Cfg config.Configurator `json:"cfg,omitempty"` + Logger logger.Logger `json:"logger,omitempty"` + Manager manager.Manager `json:"manager,omitempty"` + HasStarted bool `json:"has_started,omitempty"` } type Task struct { Client *Client `json:"client,omitempty"` diff --git a/server/api/studio/internal/service/importer/taskmgr.go b/server/api/studio/internal/service/importer/taskmgr.go index a968ed8a..aa7f9313 100644 --- a/server/api/studio/internal/service/importer/taskmgr.go +++ b/server/api/studio/internal/service/importer/taskmgr.go @@ -2,6 +2,7 @@ package importer import ( "errors" + "fmt" "os" "path/filepath" "strconv" @@ -102,9 +103,10 @@ func (mgr *TaskMgr) NewTask(host string, user string, taskName string, cfg impor task := &Task{ Client: &Client{ - Cfg: cfg, - Manager: nil, - Logger: nil, + Cfg: cfg, + Manager: nil, + Logger: nil, + HasStarted: false, }, TaskInfo: taskInfo, } @@ -214,12 +216,23 @@ and then call FinishTask */ func (mgr *TaskMgr) StopTask(taskID int) error { if task, ok := mgr.getTaskFromMap(taskID); ok { + var err error manager := task.Client.Manager - task.TaskInfo.TaskStatus = StatusStoped.String() - err := manager.Stop() + if manager != nil { + if task.Client.HasStarted { + err = manager.Stop() + } else { + // hack import not support stop before start() + err = errors.New("task has not started, please try later") + } + } else { + err = errors.New("manager is nil, please try later") + } + if err != nil { - return errors.New("stop task fail") + return fmt.Errorf("stop task failed: %w", err) } + task.TaskInfo.TaskStatus = StatusStoped.String() if err := mgr.FinishTask(taskID); err != nil { return ecode.WithErrorMessage(ecode.ErrInternalServer, err) } diff --git a/server/api/studio/pkg/utils/mutexMap.go b/server/api/studio/pkg/utils/mutexMap.go new file mode 100644 index 00000000..605e8081 --- /dev/null +++ b/server/api/studio/pkg/utils/mutexMap.go @@ -0,0 +1,52 @@ +package utils + +import "sync" + +type mutexMap[T any] struct { + mu sync.RWMutex + data map[string]T +} + +func NewMutexMap[T any]() *mutexMap[T] { + return &mutexMap[T]{ + data: make(map[string]T), + } +} + +func (m *mutexMap[T]) Get(key string) (T, bool) { + m.mu.RLock() + defer m.mu.RUnlock() + val, ok := m.data[key] + return val, ok +} + +func (m *mutexMap[T]) Set(key string, val T) { + m.mu.Lock() + defer m.mu.Unlock() + m.data[key] = val +} + +func (m *mutexMap[T]) Delete(key string) { + m.mu.Lock() + defer m.mu.Unlock() + delete(m.data, key) +} +func (m *mutexMap[T]) Size() int { + m.mu.Lock() + defer m.mu.Unlock() + return len(m.data) +} + +func (m *mutexMap[T]) ForEach(f func(key string, val T)) { + m.mu.RLock() + defer m.mu.RUnlock() + for k, v := range m.data { + f(k, v) + } +} + +func (m *mutexMap[T]) Clear() { + m.mu.Lock() + defer m.mu.Unlock() + m.data = make(map[string]T) +} diff --git a/server/api/studio/pkg/utils/tools.go b/server/api/studio/pkg/utils/tools.go index 605e8081..5298746a 100644 --- a/server/api/studio/pkg/utils/tools.go +++ b/server/api/studio/pkg/utils/tools.go @@ -1,52 +1,10 @@ package utils -import "sync" - -type mutexMap[T any] struct { - mu sync.RWMutex - data map[string]T -} - -func NewMutexMap[T any]() *mutexMap[T] { - return &mutexMap[T]{ - data: make(map[string]T), +func Contains[T comparable](s []T, e T) bool { + for _, a := range s { + if a == e { + return true + } } -} - -func (m *mutexMap[T]) Get(key string) (T, bool) { - m.mu.RLock() - defer m.mu.RUnlock() - val, ok := m.data[key] - return val, ok -} - -func (m *mutexMap[T]) Set(key string, val T) { - m.mu.Lock() - defer m.mu.Unlock() - m.data[key] = val -} - -func (m *mutexMap[T]) Delete(key string) { - m.mu.Lock() - defer m.mu.Unlock() - delete(m.data, key) -} -func (m *mutexMap[T]) Size() int { - m.mu.Lock() - defer m.mu.Unlock() - return len(m.data) -} - -func (m *mutexMap[T]) ForEach(f func(key string, val T)) { - m.mu.RLock() - defer m.mu.RUnlock() - for k, v := range m.data { - f(k, v) - } -} - -func (m *mutexMap[T]) Clear() { - m.mu.Lock() - defer m.mu.Unlock() - m.data = make(map[string]T) + return false } diff --git a/server/api/studio/studio.go b/server/api/studio/studio.go index bbaafe4c..16d9329a 100644 --- a/server/api/studio/studio.go +++ b/server/api/studio/studio.go @@ -37,9 +37,7 @@ func main() { var c config.Config conf.MustLoad(*configFile, &c, conf.UseEnv()) - var lc logx.LogConf - conf.MustLoad(*configFile, &lc) - logx.MustSetup(lc) + logx.MustSetup(c.Log) defer logx.Close() // init logger