Ctrl K
ComunidadGuías…

server/internal/handlers/incident_dispatch.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package handlers

import (
	"log"
	"sync"
	"time"

	"blackbox/shared/types"
)

const (
	incidentDispatchTimeout = 30 * time.Second
	maxPendingIncidentSends = 64
)

var incidentDispatchSem = make(chan struct{}, maxPendingIncidentSends)
var incidentDispatchWG sync.WaitGroup

func dispatchToIncidentChannelWithShutdown(ch chan<- types.Entry, shutdown <-chan struct{}, entry types.Entry) {
	if ch == nil {
		log.Printf("incidents: skipping incident dispatch for entry %s (service %s): channel is nil", entry.ID, entry.Service)
		return
	}

	select {
	case incidentDispatchSem <- struct{}{}:
	default:
		log.Printf(
			"incidents: dispatch queue saturated, skipping entry %s (service %s depth=%d cap=%d)",
			entry.ID,
			entry.Service,
			len(ch),
			cap(ch),
		)
		return
	}

	incidentDispatchWG.Add(1)
	go func(e types.Entry) {
		defer incidentDispatchWG.Done()
		defer func() { <-incidentDispatchSem }()

		timer := time.NewTimer(incidentDispatchTimeout)
		defer timer.Stop()

		select {
		case ch <- e:
		case <-timer.C:
			log.Printf(
				"incidents: channel stalled >30s, skipping incident processing for entry %s (service %s depth=%d cap=%d)",
				e.ID,
				e.Service,
				len(ch),
				cap(ch),
			)
		case <-shutdown:
		}
	}(entry)
}

func WaitForIncidentDispatches(timeout time.Duration) bool {
	done := make(chan struct{})
	go func() {
		incidentDispatchWG.Wait()
		close(done)
	}()

	if timeout <= 0 {
		<-done
		return true
	}

	timer := time.NewTimer(timeout)
	defer timer.Stop()

	select {
	case <-done:
		return true
	case <-timer.C:
		return false
	}
}