// internal/concurrency/worker.gopackageconcurrencyimport("context""fmt""sync""time")// WorkerPool manages a pool of workerstypeWorkerPoolstruct{workersintjobQueuechanJobresultChanchanResultwgsync.WaitGroupctxcontext.Contextcancelcontext.CancelFunc}// Job represents a unit of worktypeJobstruct{IDstringDatainterface{}}// Result represents the result of a jobtypeResultstruct{JobIDstringDatainterface{}Errorerror}// NewWorkerPool creates a new worker poolfuncNewWorkerPool(workersint,bufferSizeint)*WorkerPool{ctx,cancel:=context.WithCancel(context.Background())return&WorkerPool{workers:workers,jobQueue:make(chanJob,bufferSize),resultChan:make(chanResult,bufferSize),ctx:ctx,cancel:cancel,}}// Start begins processing jobsfunc(wp*WorkerPool)Start(){fori:=0;i<wp.workers;i++{wp.wg.Add(1)gowp.worker(i)}}// worker processes jobs from the queuefunc(wp*WorkerPool)worker(idint){deferwp.wg.Done()for{select{casejob:=<-wp.jobQueue:result:=wp.processJob(job)wp.resultChan<-resultcase<-wp.ctx.Done():return}}}// processJob handles individual job processingfunc(wp*WorkerPool)processJob(jobJob)Result{// Simulate worktime.Sleep(100*time.Millisecond)returnResult{JobID:job.ID,Data:fmt.Sprintf("Processed: %v",job.Data),Error:nil,}}// Submit adds a job to the queuefunc(wp*WorkerPool)Submit(jobJob)error{select{casewp.jobQueue<-job:returnnilcase<-wp.ctx.Done():returnfmt.Errorf("worker pool is shutting down")}}// Results returns the result channelfunc(wp*WorkerPool)Results()<-chanResult{returnwp.resultChan}// Stop gracefully shuts down the worker poolfunc(wp*WorkerPool)Stop(){wp.cancel()close(wp.jobQueue)wp.wg.Wait()close(wp.resultChan)}
// internal/concurrency/pipeline.gopackageconcurrencyimport("context""fmt")// Pipeline represents a processing pipelinetypePipelinestruct{stages[]Stage}// Stage represents a pipeline stagetypeStageinterface{Process(ctxcontext.Context,input<-chaninterface{})<-chaninterface{}}// TransformStage transforms datatypeTransformStagestruct{transformfunc(interface{})interface{}}// Process implements the Stage interfacefunc(ts*TransformStage)Process(ctxcontext.Context,input<-chaninterface{})<-chaninterface{}{output:=make(chaninterface{})gofunc(){deferclose(output)for{select{casedata,ok:=<-input:if!ok{return}transformed:=ts.transform(data)output<-transformedcase<-ctx.Done():return}}}()returnoutput}// FilterStage filters datatypeFilterStagestruct{predicatefunc(interface{})bool}// Process implements the Stage interfacefunc(fs*FilterStage)Process(ctxcontext.Context,input<-chaninterface{})<-chaninterface{}{output:=make(chaninterface{})gofunc(){deferclose(output)for{select{casedata,ok:=<-input:if!ok{return}iffs.predicate(data){output<-data}case<-ctx.Done():return}}}()returnoutput}// NewPipeline creates a new pipelinefuncNewPipeline(stages...Stage)*Pipeline{return&Pipeline{stages:stages}}// Execute runs the pipelinefunc(p*Pipeline)Execute(ctxcontext.Context,input<-chaninterface{})<-chaninterface{}{current:=inputfor_,stage:=rangep.stages{current=stage.Process(ctx,current)}returncurrent}
// internal/concurrency/timeout.gopackageconcurrencyimport("context""time")// WithTimeout creates a context with timeoutfuncWithTimeout(parentcontext.Context,timeouttime.Duration)(context.Context,context.CancelFunc){returncontext.WithTimeout(parent,timeout)}// WithDeadline creates a context with deadlinefuncWithDeadline(parentcontext.Context,deadlinetime.Time)(context.Context,context.CancelFunc){returncontext.WithDeadline(parent,deadline)}// DoWithTimeout executes a function with timeoutfuncDoWithTimeout(ctxcontext.Context,fnfunc()error,timeouttime.Duration)error{ctx,cancel:=WithTimeout(ctx,timeout)defercancel()done:=make(chanerror,1)gofunc(){done<-fn()}()select{caseerr:=<-done:returnerrcase<-ctx.Done():returnctx.Err()}}// RetryWithBackoff retries a function with exponential backofffuncRetryWithBackoff(ctxcontext.Context,fnfunc()error,maxRetriesint,initialDelaytime.Duration)error{varerrerrorfori:=0;i<maxRetries;i++{select{case<-ctx.Done():returnctx.Err()default:}err=fn()iferr==nil{returnnil}ifi<maxRetries-1{delay:=time.Duration(1<<uint(i))*initialDelaytime.Sleep(delay)}}returnerr}
// internal/concurrency/sync.gopackageconcurrencyimport("sync""time")// SafeCounter is a thread-safe countertypeSafeCounterstruct{musync.RWMutexcountint}// Increment safely increments the counterfunc(sc*SafeCounter)Increment(){sc.mu.Lock()defersc.mu.Unlock()sc.count++}// Get safely gets the counter valuefunc(sc*SafeCounter)Get()int{sc.mu.RLock()defersc.mu.RUnlock()returnsc.count}// SafeMap is a thread-safe maptypeSafeMapstruct{musync.RWMutexmmap[string]interface{}}// NewSafeMap creates a new thread-safe mapfuncNewSafeMap()*SafeMap{return&SafeMap{m:make(map[string]interface{}),}}// Set safely sets a valuefunc(sm*SafeMap)Set(keystring,valueinterface{}){sm.mu.Lock()defersm.mu.Unlock()sm.m[key]=value}// Get safely gets a valuefunc(sm*SafeMap)Get(keystring)(interface{},bool){sm.mu.RLock()defersm.mu.RUnlock()value,ok:=sm.m[key]returnvalue,ok}// Delete safely deletes a valuefunc(sm*SafeMap)Delete(keystring){sm.mu.Lock()defersm.mu.Unlock()delete(sm.m,key)}
// internal/concurrency/circuitbreaker.gopackageconcurrencyimport("context""errors""sync""time")// CircuitState represents the state of the circuit breakertypeCircuitStateintconst(StateClosedCircuitState=iotaStateOpenStateHalfOpen)// CircuitBreaker implements the circuit breaker patterntypeCircuitBreakerstruct{musync.RWMutexstateCircuitStatefailuresintthresholdinttimeouttime.DurationlastFailuretime.Time}// NewCircuitBreaker creates a new circuit breakerfuncNewCircuitBreaker(thresholdint,timeouttime.Duration)*CircuitBreaker{return&CircuitBreaker{state:StateClosed,threshold:threshold,timeout:timeout,}}// Execute executes a function with circuit breaker protectionfunc(cb*CircuitBreaker)Execute(ctxcontext.Context,fnfunc()error)error{if!cb.allowRequest(){returnerrors.New("circuit breaker is open")}err:=fn()cb.recordResult(err)returnerr}// allowRequest checks if a request should be allowedfunc(cb*CircuitBreaker)allowRequest()bool{cb.mu.RLock()defercb.mu.RUnlock()switchcb.state{caseStateClosed:returntruecaseStateOpen:returntime.Since(cb.lastFailure)>cb.timeoutcaseStateHalfOpen:returntruedefault:returnfalse}}// recordResult records the result of a requestfunc(cb*CircuitBreaker)recordResult(errerror){cb.mu.Lock()defercb.mu.Unlock()iferr!=nil{cb.failures++cb.lastFailure=time.Now()ifcb.failures>=cb.threshold{cb.state=StateOpen}}else{cb.failures=0cb.state=StateClosed}}
// internal/concurrency/ratelimiter.gopackageconcurrencyimport("context""sync""time")// RateLimiter implements token bucket rate limitingtypeRateLimiterstruct{musync.Mutextokensintcapacityintratetime.DurationlastTimetime.Time}// NewRateLimiter creates a new rate limiterfuncNewRateLimiter(capacityint,ratetime.Duration)*RateLimiter{return&RateLimiter{tokens:capacity,capacity:capacity,rate:rate,lastTime:time.Now(),}}// Allow checks if a request is allowedfunc(rl*RateLimiter)Allow()bool{rl.mu.Lock()deferrl.mu.Unlock()now:=time.Now()elapsed:=now.Sub(rl.lastTime)// Add tokens based on elapsed timetokensToAdd:=int(elapsed/rl.rate)iftokensToAdd>0{rl.tokens=min(rl.capacity,rl.tokens+tokensToAdd)rl.lastTime=now}ifrl.tokens>0{rl.tokens--returntrue}returnfalse}// Wait waits for a token to become availablefunc(rl*RateLimiter)Wait(ctxcontext.Context)error{for{ifrl.Allow(){returnnil}select{case<-ctx.Done():returnctx.Err()case<-time.After(rl.rate):// Try again}}}// min returns the minimum of two integersfuncmin(a,bint)int{ifa<b{returna}returnb}
// internal/concurrency/errors.gopackageconcurrencyimport("context""errors""fmt""sync")// ConcurrencyError represents a concurrency-related errortypeConcurrencyErrorstruct{OpstringErrerror}// Error implements the error interfacefunc(ce*ConcurrencyError)Error()string{returnfmt.Sprintf("concurrency error in %s: %v",ce.Op,ce.Err)}// Unwrap returns the underlying errorfunc(ce*ConcurrencyError)Unwrap()error{returnce.Err}// ErrorGroup manages a group of goroutines with error handlingtypeErrorGroupstruct{wgsync.WaitGrouperrs[]errormusync.Mutexctxcontext.Contextcancelcontext.CancelFunc}// NewErrorGroup creates a new error groupfuncNewErrorGroup(ctxcontext.Context)*ErrorGroup{ctx,cancel:=context.WithCancel(ctx)return&ErrorGroup{ctx:ctx,cancel:cancel,}}// Go runs a function in a goroutinefunc(eg*ErrorGroup)Go(fnfunc()error){eg.wg.Add(1)gofunc(){defereg.wg.Done()iferr:=fn();err!=nil{eg.mu.Lock()eg.errs=append(eg.errs,err)eg.mu.Unlock()eg.cancel()}}()}// Wait waits for all goroutines to completefunc(eg*ErrorGroup)Wait()error{eg.wg.Wait()eg.cancel()iflen(eg.errs)>0{returnfmt.Errorf("multiple errors: %v",eg.errs)}returnnil}
// internal/concurrency/concurrency_test.gopackageconcurrencyimport("context""testing""time")funcTestWorkerPool(t*testing.T){pool:=NewWorkerPool(3,10)pool.Start()deferpool.Stop()// Submit jobsfori:=0;i<5;i++{job:=Job{ID:fmt.Sprintf("job-%d",i),Data:fmt.Sprintf("data-%d",i),}err:=pool.Submit(job)iferr!=nil{t.Fatalf("Failed to submit job: %v",err)}}// Collect resultsresults:=make([]Result,0,5)fori:=0;i<5;i++{select{caseresult:=<-pool.Results():results=append(results,result)case<-time.After(5*time.Second):t.Fatal("Timeout waiting for results")}}iflen(results)!=5{t.Errorf("Expected 5 results, got %d",len(results))}}funcTestCircuitBreaker(t*testing.T){cb:=NewCircuitBreaker(2,100*time.Millisecond)// Test successful executionerr:=cb.Execute(context.Background(),func()error{returnnil})iferr!=nil{t.Errorf("Expected no error, got %v",err)}// Test failure thresholdfori:=0;i<3;i++{err:=cb.Execute(context.Background(),func()error{returnerrors.New("test error")})ifi<2&&err==nil{t.Error("Expected error for failed execution")}ifi>=2&&err==nil{t.Error("Expected circuit breaker to be open")}}}