func (m *WorkerPoolManager) GetPool(key string, sendSize int) (WorkerPool, chan<- bool) {
	pool, doneUsing, _ := m.GetPoolWithFactory(key, sendSize, NewWorkerPool)
	return pool, doneUsing
}
GetPool returns the WorkerPool for this key, building a BaseWorkerPool and caching it if necessary.
Spawns sendSize workers, up to a max of the manager's poolSize.

This returns the pool in an "unexpirable" state - the caller should signal the returned done channel when it
no longer requires the returned bundle.
package pool
import (
	"sync"
	"time"
	"github.com/diegobernardes/ttlcache"
)
type WorkerPoolManager struct {
	workerPoolCache     *ttlcache.Cache
	workerPoolMaxSize   int
	poolReservationLock *sync.Mutex
	stalePoolExpiration time.Duration
	maxPoolLifetime     time.Duration
}
func NewWorkerPoolManager(
	poolSize int, stalePoolExpiration time.Duration, maxPoolLifetime time.Duration,
) *WorkerPoolManager {
	workerPoolCache := ttlcache.NewCache()
	workerPoolCache.SetTTL(stalePoolExpiration)
	workerPoolCache.SetExpirationCallback(func(key string, cachedPool interface{}) {
		cachedPool.(WorkerPool).Dispose()
	})
	return &WorkerPoolManager{
		workerPoolCache:     workerPoolCache,
		workerPoolMaxSize:   poolSize,
		poolReservationLock: &sync.Mutex{},
		stalePoolExpiration: stalePoolExpiration,
		maxPoolLifetime:     maxPoolLifetime,
	}
}