github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/tasks/job.go (about)

     1  // Copyright 2021 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 tasks
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    24  	"github.com/panjf2000/ants/v2"
    25  )
    26  
    27  type JobType = uint16
    28  
    29  const (
    30  	JTAny             JobType = iota
    31  	JTCustomizedStart         = 100
    32  
    33  	JTInvalid = 10000
    34  )
    35  
    36  var jobTypeNames = map[JobType]string{
    37  	JTAny: "AnyJob",
    38  }
    39  
    40  func RegisterJobType(jt JobType, jn string) {
    41  	_, ok := jobTypeNames[jt]
    42  	if ok {
    43  		panic(any(moerr.NewInternalErrorNoCtx("duplicate job type: %d", jt)))
    44  	}
    45  	jobTypeNames[jt] = jn
    46  }
    47  
    48  func JobName(jt JobType) string {
    49  	n, ok := jobTypeNames[jt]
    50  	if !ok {
    51  		panic(any(moerr.NewInternalErrorNoCtx("specified job type: %d not found", jt)))
    52  	}
    53  	return n
    54  }
    55  
    56  type JobScheduler interface {
    57  	Schedule(job *Job) error
    58  	Stop()
    59  }
    60  
    61  type JobExecutor = func(context.Context) *JobResult
    62  
    63  type JobResult struct {
    64  	Err error
    65  	Res any
    66  }
    67  
    68  var SerialJobScheduler = new(simpleJobScheduler)
    69  
    70  type simpleJobScheduler struct{}
    71  
    72  func (s *simpleJobScheduler) Stop() {}
    73  func (s *simpleJobScheduler) Schedule(job *Job) (err error) {
    74  	job.Run()
    75  	return
    76  }
    77  
    78  type parallelJobScheduler struct {
    79  	pool *ants.Pool
    80  }
    81  
    82  func NewParallelJobScheduler(parallism int) *parallelJobScheduler {
    83  	pool, err := ants.NewPool(parallism)
    84  	if err != nil {
    85  		panic(any(err))
    86  	}
    87  	return &parallelJobScheduler{
    88  		pool: pool,
    89  	}
    90  }
    91  
    92  func (s *parallelJobScheduler) Stop() {
    93  	s.pool.Release()
    94  	s.pool = nil
    95  }
    96  
    97  func (s *parallelJobScheduler) Schedule(job *Job) (err error) {
    98  	err = s.pool.Submit(job.Run)
    99  	return
   100  }
   101  
   102  type Job struct {
   103  	id      string
   104  	typ     JobType
   105  	wg      sync.WaitGroup
   106  	ctx     context.Context
   107  	exec    JobExecutor
   108  	result  *JobResult
   109  	startTs time.Time
   110  	endTs   time.Time
   111  }
   112  
   113  func (job *Job) Run() {
   114  	defer job.wg.Done()
   115  	job.startTs = time.Now()
   116  	defer func() {
   117  		job.endTs = time.Now()
   118  		/*logutil.Debug("run-job", common.AnyField("name", job.String()),
   119  		common.ErrorField(job.result.Err),
   120  		common.DurationField(job.endTs.Sub(job.startTs)))*/
   121  	}()
   122  	result := job.exec(job.ctx)
   123  	job.result = result
   124  }
   125  
   126  func (job *Job) ID() string {
   127  	return job.id
   128  }
   129  
   130  func (job *Job) String() string {
   131  	return fmt.Sprintf("Job[%s]-[%s]", JobName(job.typ), job.id)
   132  }
   133  
   134  func (job *Job) Type() JobType {
   135  	return job.typ
   136  }
   137  
   138  func (job *Job) WaitDone() *JobResult {
   139  	job.wg.Wait()
   140  	return job.result
   141  }
   142  
   143  func (job *Job) GetResult() *JobResult {
   144  	job.wg.Wait()
   145  	return job.result
   146  }
   147  
   148  func (job *Job) DoneWithErr(err error) {
   149  	defer job.wg.Done()
   150  	job.result = &JobResult{
   151  		Err: err,
   152  	}
   153  }
   154  
   155  func (job *Job) Close() {
   156  	job.result = nil
   157  }
   158  
   159  func (job *Job) Reset() {
   160  	job.result = nil
   161  	job.typ = JTInvalid
   162  	job.id = ""
   163  	job.ctx = nil
   164  	job.wg = sync.WaitGroup{}
   165  	job.exec = nil
   166  }
   167  
   168  func (job *Job) Init(
   169  	ctx context.Context,
   170  	id string,
   171  	typ JobType,
   172  	exec JobExecutor) {
   173  	job.id = id
   174  	job.ctx = ctx
   175  	job.exec = exec
   176  	job.typ = typ
   177  	job.wg.Add(1)
   178  }