package main

import (
	"errors"
	"sync"
	"time"
)

// Eklenti basina es zamanli surec sayisi. Genis tutuldu: normal kullanimi engellemez,
// yalnizca asiri istek patlamalarina karsi koruma saglar.
const eklentiEsZamanliSinir = 16

// Bir slot icin en fazla bu kadar beklenir; asilirsa "mesgul" hatasi doner.
const eklentiSlotBeklemeZamani = 30 * time.Second

var errEklentiMesgul = errors.New("eklenti su an yogun, lutfen tekrar deneyin")

var (
	esZamanliMu       sync.Mutex
	esZamanliKanallar = map[string]chan struct{}{}
)

// eklentiSlotAl: anahtar (genelde eklenti yolu) icin bir calisma slotu alir. Donen fonksiyon slotu birakir.
func eklentiSlotAl(anahtar string) (func(), error) {
	esZamanliMu.Lock()
	kanal, ok := esZamanliKanallar[anahtar]
	if !ok {
		kanal = make(chan struct{}, eklentiEsZamanliSinir)
		esZamanliKanallar[anahtar] = kanal
	}
	esZamanliMu.Unlock()
	zamanlayici := time.NewTimer(eklentiSlotBeklemeZamani)
	defer zamanlayici.Stop()
	select {
	case kanal <- struct{}{}:
		return func() { <-kanal }, nil
	case <-zamanlayici.C:
		return nil, errEklentiMesgul
	}
}
