This Go project implements a concurrent worker pool that processes jobs efficiently using goroutines and channels. It mirrors what would be necessary for real-world scenarios where tasks need to be executed in parallel, such as:
-
Data Processing Pipelines β Handling large-scale batch jobs like log analysis or ETL workflows.
-
Web Scraping β Running multiple concurrent scrapers without overloading a single process.
-
API Rate Limiting β Managing controlled, retryable requests to external services.
-
Task Queues β Offloading CPU-intensive or asynchronous tasks in a distributed system.
-
Load Testing β Simulating high-traffic scenarios by distributing requests across multiple workers.
If a job fails, it automatically retries up to a defined limit before marking it as failed. The number of workers, jobs, and retry attempts are fully configurable via CLI arguments, making this project highly flexible and scalable.
β Concurrent Processing β Uses goroutines & channels to process jobs efficiently.
β Automatic Retries β Jobs retry on failure up to a max retry limit.
β Configurable via CLI β Set the number of workers, jobs, and retries dynamically.
β Graceful Shutdown β Ensures all jobs complete safely before exiting.
β Unit Tests β Includes robust test cases to validate worker behavior and retries.
β GitHub Actions CI β Automatically runs tests on every push.
git clone https://github.com/yourusername/go-load-tester.git
cd go-load-tester
go run main.go
go run main.go --workers=5 --jobs=20 --retries=3
go test -v
I attempted to benchmark the worker pool, but faced unique challenges:
-
Retries complicate measurement β If jobs fail and retry, total execution time fluctuates.
-
Channel closing issues β Workers sometimes attempted to retry jobs after the jobs channel was closed, causing panics.
-
Go's b.N scaling β The benchmark runner dynamically sets b.N, but the presence of retries led to inconsistent performance results.
To properly benchmark, I could:
-
Separate success and failure benchmarking β Measure jobs that complete without retries separately.
-
Track execution time per worker β Instead of total time, record each workerβs processing speed.
-
Log performance data instead of benchmarking β Capture real-world execution stats without go test -bench constraints.
πΉ Logging β Save job results & errors to a file for debugging.
πΉ Dynamic Worker Scaling β Auto-adjust the number of workers based on job load.
πΉ Retry Backoff β Use an exponential backoff for failed job retries.
πΉ More Robust Benchmarking β Develop a specialized benchmark without retries interfering.