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 ¶llelJobScheduler{ 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 }