github.com/matrixorigin/matrixone@v0.7.0/pkg/cnservice/server_task.go (about) 1 // Copyright 2021 - 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cnservice 16 17 import ( 18 "context" 19 "fmt" 20 "time" 21 22 "github.com/matrixorigin/matrixone/pkg/common/moerr" 23 "github.com/matrixorigin/matrixone/pkg/common/runtime" 24 "github.com/matrixorigin/matrixone/pkg/config" 25 "github.com/matrixorigin/matrixone/pkg/frontend" 26 "github.com/matrixorigin/matrixone/pkg/logutil" 27 logservicepb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 28 "github.com/matrixorigin/matrixone/pkg/pb/task" 29 "github.com/matrixorigin/matrixone/pkg/taskservice" 30 "github.com/matrixorigin/matrixone/pkg/util/export" 31 "github.com/matrixorigin/matrixone/pkg/util/file" 32 ie "github.com/matrixorigin/matrixone/pkg/util/internalExecutor" 33 "github.com/matrixorigin/matrixone/pkg/util/metric" 34 "github.com/matrixorigin/matrixone/pkg/util/sysview" 35 "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace" 36 "go.uber.org/zap" 37 ) 38 39 const ( 40 defaultSystemInitTimeout = time.Minute * 5 41 ) 42 43 func (s *service) adjustSQLAddress() { 44 if s.cfg.SQLAddress == "" { 45 ip := "127.0.0.1" 46 if s.cfg.Frontend.Host != "" && 47 s.cfg.Frontend.Host != "0.0.0.0" { 48 ip = s.cfg.Frontend.Host 49 } 50 51 s.cfg.SQLAddress = fmt.Sprintf("%s:%d", 52 ip, 53 s.cfg.Frontend.Port) 54 } 55 } 56 57 func (s *service) initTaskServiceHolder() { 58 s.adjustSQLAddress() 59 60 s.task.Lock() 61 defer s.task.Unlock() 62 if s.task.storageFactory == nil { 63 s.task.holder = taskservice.NewTaskServiceHolder( 64 runtime.ProcessLevelRuntime(), 65 func(context.Context) (string, error) { return s.cfg.SQLAddress, nil }) 66 } else { 67 s.task.holder = taskservice.NewTaskServiceHolderWithTaskStorageFactorySelector( 68 runtime.ProcessLevelRuntime(), 69 func(context.Context) (string, error) { return s.cfg.SQLAddress, nil }, 70 func(_, _, _ string) taskservice.TaskStorageFactory { 71 return s.task.storageFactory 72 }) 73 } 74 75 if err := s.stopper.RunTask(s.waitSystemInitCompleted); err != nil { 76 panic(err) 77 } 78 } 79 80 func (s *service) createTaskService(command *logservicepb.CreateTaskService) { 81 // Notify frontend to setup the special account used to task framework create and query async tasks. 82 // The account is always in the memory. 83 frontend.SetSpecialUser(command.User.Username, []byte(command.User.Password)) 84 85 if err := s.task.holder.Create(*command); err != nil { 86 s.logger.Error("create task service failed", zap.Error(err)) 87 return 88 } 89 s.startTaskRunner() 90 } 91 92 func (s *service) startTaskRunner() { 93 s.task.Lock() 94 defer s.task.Unlock() 95 96 if s.task.runner != nil { 97 return 98 } 99 100 ts, ok := s.task.holder.Get() 101 if !ok { 102 panic("task service must created") 103 } 104 105 s.task.runner = taskservice.NewTaskRunner(s.cfg.UUID, 106 ts, 107 taskservice.WithRunnerLogger(s.logger), 108 taskservice.WithOptions( 109 s.cfg.TaskRunner.QueryLimit, 110 s.cfg.TaskRunner.Parallelism, 111 s.cfg.TaskRunner.MaxWaitTasks, 112 s.cfg.TaskRunner.FetchInterval.Duration, 113 s.cfg.TaskRunner.FetchTimeout.Duration, 114 s.cfg.TaskRunner.RetryInterval.Duration, 115 s.cfg.TaskRunner.HeartbeatInterval.Duration, 116 ), 117 ) 118 119 s.registerExecutorsLocked() 120 if err := s.task.runner.Start(); err != nil { 121 s.logger.Error("start task runner failed", 122 zap.Error(err)) 123 } 124 } 125 126 func (s *service) GetTaskRunner() taskservice.TaskRunner { 127 s.task.RLock() 128 defer s.task.RUnlock() 129 return s.task.runner 130 } 131 132 func (s *service) GetTaskService() (taskservice.TaskService, bool) { 133 s.task.RLock() 134 defer s.task.RUnlock() 135 return s.task.holder.Get() 136 } 137 138 func (s *service) WaitSystemInitCompleted(ctx context.Context) error { 139 s.waitSystemInitCompleted(ctx) 140 return ctx.Err() 141 } 142 143 func (s *service) waitSystemInitCompleted(ctx context.Context) { 144 defer logutil.LogAsyncTask(s.logger, "cnservice/wait-system-init-task")() 145 146 startAt := time.Now() 147 s.logger.Debug("wait all init task completed task started") 148 wait := func() { 149 time.Sleep(time.Second) 150 } 151 for { 152 select { 153 case <-ctx.Done(): 154 s.logger.Debug("wait all init task completed task stopped") 155 return 156 default: 157 ts, ok := s.GetTaskService() 158 if ok { 159 tasks, err := ts.QueryTask(ctx, 160 taskservice.WithTaskExecutorCond(taskservice.EQ, task.TaskCode_SystemInit), 161 taskservice.WithTaskStatusCond(taskservice.EQ, task.TaskStatus_Completed)) 162 if err != nil { 163 s.logger.Error("wait all init task completed failed", zap.Error(err)) 164 break 165 } 166 s.logger.Debug("waiting all init task completed", 167 zap.Int("completed", len(tasks))) 168 if len(tasks) > 0 { 169 if err := file.WriteFile(s.metadataFS, 170 "./system_init_completed", 171 []byte("OK")); err != nil { 172 panic(err) 173 } 174 return 175 } 176 } 177 } 178 wait() 179 if time.Since(startAt) > defaultSystemInitTimeout { 180 panic("wait system init timeout") 181 } 182 } 183 } 184 185 func (s *service) stopTask() error { 186 defer logutil.LogClose(s.logger, "cnservice/task")() 187 188 s.task.Lock() 189 defer s.task.Unlock() 190 if err := s.task.holder.Close(); err != nil { 191 return err 192 } 193 if s.task.runner != nil { 194 return s.task.runner.Stop() 195 } 196 return nil 197 } 198 199 func (s *service) registerExecutorsLocked() { 200 if s.task.runner == nil { 201 return 202 } 203 204 pu := config.NewParameterUnit( 205 &s.cfg.Frontend, 206 nil, 207 nil, 208 nil, 209 s.pu.GetClusterDetails, 210 ) 211 pu.StorageEngine = s.storeEngine 212 pu.TxnClient = s._txnClient 213 s.cfg.Frontend.SetDefaultValues() 214 pu.FileService = s.fileService 215 moServerCtx := context.WithValue(context.Background(), config.ParameterUnitKey, pu) 216 ieFactory := func() ie.InternalExecutor { 217 return frontend.NewInternalExecutor(pu, s.mo.GetRoutineManager().GetAutoIncrCache()) 218 } 219 220 ts, ok := s.task.holder.Get() 221 if !ok { 222 panic(moerr.NewInternalErrorNoCtx("task Service not ok")) 223 } 224 s.task.runner.RegisterExecutor(task.TaskCode_SystemInit, 225 func(ctx context.Context, t task.Task) error { 226 if err := frontend.InitSysTenant(moServerCtx, s.mo.GetRoutineManager().GetAutoIncrCache()); err != nil { 227 return err 228 } 229 if err := sysview.InitSchema(moServerCtx, ieFactory); err != nil { 230 return err 231 } 232 if err := metric.InitSchema(moServerCtx, ieFactory); err != nil { 233 return err 234 } 235 if err := motrace.InitSchema(moServerCtx, ieFactory); err != nil { 236 return err 237 } 238 239 // init metric/log merge task cron rule 240 if err := export.CreateCronTask(moServerCtx, task.TaskCode_MetricLogMerge, ts); err != nil { 241 return err 242 } 243 244 // init metric task 245 if err := metric.CreateCronTask(moServerCtx, task.TaskCode_MetricStorageUsage, ts); err != nil { 246 return err 247 } 248 249 return nil 250 }) 251 252 // init metric/log merge task executor 253 s.task.runner.RegisterExecutor(task.TaskCode_MetricLogMerge, 254 export.MergeTaskExecutorFactory(export.WithFileService(s.fileService))) 255 // init metric task 256 s.task.runner.RegisterExecutor(task.TaskCode_MetricStorageUsage, 257 metric.GetMetricStorageUsageExecutor(ieFactory)) 258 }