mirror of
				https://github.com/3ybactuk/marketplace-go-service-project.git
				synced 2025-10-31 06:23:44 +03:00 
			
		
		
		
	[hw-5] concurrency, graceful shutdown, concurrent tests
This commit is contained in:
		
							
								
								
									
										62
									
								
								cart/internal/infra/errgroup/errgroup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								cart/internal/infra/errgroup/errgroup.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| package errgroup | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
| ) | ||||
|  | ||||
| type Group struct { | ||||
| 	ctx    context.Context | ||||
| 	cancel context.CancelFunc | ||||
|  | ||||
| 	wg sync.WaitGroup | ||||
|  | ||||
| 	firstErr chan error | ||||
|  | ||||
| 	// Used to limit number of goroutines (workers) for group. | ||||
| 	workerLimCh chan struct{} | ||||
| } | ||||
|  | ||||
| func WithContext(parent context.Context, workers int) (*Group, context.Context) { | ||||
| 	ctx, cancel := context.WithCancel(parent) | ||||
| 	return &Group{ | ||||
| 		ctx:         ctx, | ||||
| 		cancel:      cancel, | ||||
| 		firstErr:    make(chan error, 1), | ||||
| 		workerLimCh: make(chan struct{}, workers), | ||||
| 	}, ctx | ||||
| } | ||||
|  | ||||
| func (g *Group) Go(f func(ctx context.Context) error) { | ||||
| 	// Wait for worker to be freed. | ||||
| 	g.workerLimCh <- struct{}{} | ||||
|  | ||||
| 	g.wg.Add(1) | ||||
| 	go func() { | ||||
| 		defer func() { | ||||
| 			g.wg.Done() | ||||
|  | ||||
| 			<-g.workerLimCh // release worker | ||||
| 		}() | ||||
|  | ||||
| 		if err := f(g.ctx); err != nil { | ||||
| 			select { | ||||
| 			case g.firstErr <- err: | ||||
| 				g.cancel() | ||||
| 			default: // got error from other goroutine | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| func (g *Group) Wait() error { | ||||
| 	g.wg.Wait() | ||||
| 	g.cancel() | ||||
|  | ||||
| 	select { | ||||
| 	case err := <-g.firstErr: | ||||
| 		return err | ||||
| 	default: | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Никита Шубин
					Никита Шубин