readysite / hosting / internal / websites / events.go
1.3 KB
events.go
package websites

import "sync"

// Event represents a status update for a site.
type Event struct {
	Status  string `json:"status"`
	Message string `json:"message"`
}

var (
	mu          sync.Mutex
	subscribers = map[string][]chan Event{}
)

// Subscribe returns a channel that receives events for a site.
func Subscribe(siteID string) chan Event {
	mu.Lock()
	defer mu.Unlock()
	ch := make(chan Event, 16)
	subscribers[siteID] = append(subscribers[siteID], ch)
	return ch
}

// Unsubscribe removes a channel and closes it.
// Safe to call multiple times — only closes the channel once.
func Unsubscribe(siteID string, ch chan Event) {
	mu.Lock()
	defer mu.Unlock()
	subs := subscribers[siteID]
	found := false
	for i, sub := range subs {
		if sub == ch {
			subscribers[siteID] = append(subs[:i], subs[i+1:]...)
			found = true
			break
		}
	}
	if len(subscribers[siteID]) == 0 {
		delete(subscribers, siteID)
	}
	// Only close if the channel was still subscribed (prevents double-close panic)
	if found {
		close(ch)
	}
}

// publish sends an event to all subscribers for a site.
func publish(siteID string, event Event) {
	mu.Lock()
	defer mu.Unlock()
	for _, ch := range subscribers[siteID] {
		select {
		case ch <- event:
		default: // drop if subscriber is slow
		}
	}
}
← Back