github.com/erda-project/erda-infra@v1.0.10-0.20240327085753-f3a249292aeb/pkg/parallel/future.go (about) 1 // Copyright (c) 2021 Terminus, Inc. 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 parallel 16 17 import ( 18 "context" 19 20 "github.com/erda-project/erda-infra/pkg/trace" 21 ) 22 23 // Future . 24 type Future interface { 25 Get() (interface{}, error) 26 Cancel() 27 } 28 29 // Go . 30 func Go(ctx context.Context, fn func(ctx context.Context) (interface{}, error), opts ...RunOption) Future { 31 rOpts := &runOptions{} 32 for _, opt := range opts { 33 opt(rOpts) 34 } 35 f := &futureResult{ 36 result: make(chan *result, 1), 37 } 38 if rOpts.timeout > 0 { 39 f.ctx, f.cancel = context.WithTimeout(ctx, rOpts.timeout) 40 } else { 41 f.ctx, f.cancel = context.WithCancel(ctx) 42 } 43 trace.GoWithContext(f.ctx, func(ctx context.Context) { 44 defer f.cancel() 45 defer close(f.result) 46 data, err := fn(ctx) 47 f.result <- &result{data, err} 48 }) 49 return f 50 } 51 52 type futureResult struct { 53 ctx context.Context 54 cancel func() 55 56 result chan *result 57 } 58 59 type result struct { 60 data interface{} 61 err error 62 } 63 64 func (f *futureResult) Get() (interface{}, error) { 65 select { 66 case <-f.ctx.Done(): 67 select { 68 case result := <-f.result: 69 return result.data, result.err 70 default: 71 } 72 return nil, f.ctx.Err() 73 case result := <-f.result: 74 return result.data, result.err 75 } 76 } 77 78 func (f *futureResult) Cancel() { 79 f.cancel() 80 }