Tunny, senkron API'ları kullanarak herhangi bir sayıda gorutinden işi sınırlamanıza izin veren ve gorutin havuzları oluşturup yönetmenizi sağlayan bir Golang kütüphanesidir.

İşiniz herhangi bir sayıda asenkron kaynaktan geliyorsa, ancak paralel işleme kapasiteniz sınırlıysa, sabit bir gorutin havuzu son derece kullanışlıdır. Örneğin, CPU yoğunluğunda HTTP istek işlemleri sırasında, CPU sayısına göre bir havuz oluşturabilirsiniz.

## Yükleme
```shell
go get github.com/Jeffail/tunny

Alternatif olarak, dep kullanarak:

dep ensure -add github.com/Jeffail/tunny

Kullanım

Çoğu durumda, ağır işiniz basit bir func() ile temsil edilebilir, bu durumda NewFunc kullanabilirsiniz. HTTP isteklerinden CPU sayısını hesaplama örneğimizi nasıl kullanacağımıza bakalım:

package main

import (
	"io/ioutil"
	"net/http"
	"runtime"

	"github.com/Jeffail/tunny"
)

func main() {
	numCPUs := runtime.NumCPU()

	pool := tunny.NewFunc(numCPUs, func(payload interface{}) interface{} {
		var result []byte

		// TODO: payload ile bazı CPU-yoğun işlemleri gerçekleştirin

		return result
	})
	defer pool.Close()

	http.HandleFunc("/work", func(w http.ResponseWriter, r *http.Request) {
		input, err := ioutil.ReadAll(r.Body)
		if err != nil {
			http.Error(w, "İç hata", http.StatusInternalServerError)
		}
		defer r.Body.Close()

		// Bu işi havuzumuza dahil edin. Bu çağrı senkron ve iş tamamlanana kadar bloklanacaktır.
		result := pool.Process(input)

		w.Write(result.([]byte))
	})

	http.ListenAndServe(":8080", nil)
}

Tunny, zaman aşımını da destekler. Yukarıdaki Process çağrısını aşağıdaki kod ile değiştirebilirsiniz:

result, err := pool.ProcessTimed(input, time.Second*5)
if err == tunny.ErrJobTimedOut {
	http.Error(w, "İstek zaman aşımına uğradı", http.StatusRequestTimeout)
}

Ayrıca istek bağlamını (veya herhangi bir bağlamı) zaman aşımını ve son tarihleri işlemek için de kullanabilirsiniz. Sadece Process çağrısını aşağıdaki kod ile değiştirin:

result, err := pool.ProcessCtx(r.Context(), input)
if err == context.DeadlineExceeded {
	http.Error(w, "İstek zaman aşımına uğradı", http.StatusRequestTimeout)
}

Havuz Boyutunu Değiştirme

SetSize(int) kullanarak Tunny havuzunun boyutunu istediğiniz zaman değiştirebilirsiniz.

pool.SetSize(10) // 10 gorutin
pool.SetSize(100) // 100 gorutin

Bu, diğer gorutinler hala işlem yapıyorken bile güvenlidir.

Durumlu Gorutin

Bazen, Tunny havuzundaki her gorutin kendi yönetim durumuna ihtiyaç duyar. Bu durumda, tunny.Worker 'i uygulamanız gerekecektir, bu durum kapatma, kesmeyi (eğer bir iş zaman aşımına uğrarsa ve artık gerekli değilse) ve belirli bir koşul karşılanana kadar bir sonraki işin tahsisini engelleme çağrılarını içerir.

Worker türü ile havuz oluştururken, özel uygulamanızı oluşturmak için bir kurucu sağlamanız gerekir:

pool := tunny.New(poolSize, func() Worker {
	// TODO: Her gorutin için durum tahsisi yapın.
	return newCustomWorker()
})

Bu şekilde, Tunny havuz boyutu değiştiğinde Worker türünün yaratılıp yok edilmesini temizleyebilir.

Sıralama

Bekleyen işlerin sırayla işlenmesi garanti edilmez. Mevcut kanalların ve seçim bloklarının uygulaması nedeniyle, bekleyen iş yığınları FIFO kuyruğu olarak işlenir. Ancak, bu davranış özellik değildir ve buna güvenilmemelidir.