github.com/grafana/synthetic-monitoring-agent@v0.64.2/internal/pusher/registry.go (about) 1 package pusher 2 3 import ( 4 "fmt" 5 "sort" 6 "sync" 7 ) 8 9 // registry to register and obtain instances of the named type. 10 // 11 // This type is not exported to prevent creating instances without calling NewRegistry. 12 type registry[T any] struct { 13 mu sync.Mutex 14 entries map[string]T 15 } 16 17 func NewRegistry[T any]() *registry[T] { 18 var r registry[T] 19 20 r.entries = make(map[string]T) 21 22 return &r 23 } 24 25 func (r *registry[T]) Register(name string, handler T) error { 26 r.mu.Lock() 27 defer r.mu.Unlock() 28 29 if _, found := r.entries[name]; found { 30 return AlreadyRegisteredError(name) 31 } 32 33 r.entries[name] = handler 34 35 return nil 36 } 37 38 func (r *registry[T]) MustRegister(name string, handler T) { 39 if err := r.Register(name, handler); err != nil { 40 panic(err) 41 } 42 } 43 44 func (r *registry[T]) Lookup(name string) (T, error) { 45 r.mu.Lock() 46 defer r.mu.Unlock() 47 48 entry, found := r.entries[name] 49 if !found { 50 var ( 51 zero T 52 keys []string 53 ) 54 for key := range r.entries { 55 keys = append(keys, key) 56 } 57 58 sort.Strings(keys) 59 60 return zero, NotFoundError{ 61 Requested: name, 62 Accepted: keys, 63 } 64 } 65 66 return entry, nil 67 } 68 69 type NotFoundError struct { 70 Requested string 71 Accepted []string 72 } 73 74 func (e NotFoundError) Error() string { 75 return fmt.Sprintf("`%s` not found. Must be one of %v", e.Requested, e.Accepted) 76 } 77 78 type AlreadyRegisteredError string 79 80 func (e AlreadyRegisteredError) Error() string { 81 return fmt.Sprintf("entry `%s` already registered", string(e)) 82 }