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  }