mirror of
https://github.com/weaveworks/scope.git
synced 2026-02-14 18:09:59 +00:00
It is not a singleton anymore. Instead it is an object with a registry backend. The default registry backend is provided, which is equivalent to what used to be before. Custom backend can be provided for testing purposes. The registry also supports batch operations to remove and add handlers as an atomic step.
132 lines
3.6 KiB
Go
132 lines
3.6 KiB
Go
package controls
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/weaveworks/scope/common/xfer"
|
|
)
|
|
|
|
// HandlerRegistryBackend is an interface for storing control request
|
|
// handlers.
|
|
type HandlerRegistryBackend interface {
|
|
// Lock locks the backend, so the batch insertions or
|
|
// removals can be performed.
|
|
Lock()
|
|
// Unlock unlocks the registry.
|
|
Unlock()
|
|
// Register a new control handler under a given
|
|
// id. Implementations should not call Lock() or Unlock()
|
|
// here, it will be done by HandlerRegistry.
|
|
Register(control string, f xfer.ControlHandlerFunc)
|
|
// Rm deletes the handler for a given name. Implementations
|
|
// should not call Lock() or Unlock() here, it will be done by
|
|
// HandlerRegistry.
|
|
Rm(control string)
|
|
// Handler gets the handler for a control. Implementations
|
|
// should not call Lock() or Unlock() here, it will be done by
|
|
// HandlerRegistry.
|
|
Handler(control string) (xfer.ControlHandlerFunc, bool)
|
|
}
|
|
|
|
type defaultBackend struct {
|
|
handlers map[string]xfer.ControlHandlerFunc
|
|
mtx sync.Mutex
|
|
}
|
|
|
|
// NewDefaultHandlerRegistryBackend creates a default backend for
|
|
// handler registry.
|
|
func NewDefaultHandlerRegistryBackend() HandlerRegistryBackend {
|
|
return &defaultBackend{
|
|
handlers: map[string]xfer.ControlHandlerFunc{},
|
|
}
|
|
}
|
|
|
|
// Lock locks the registry, so the batch insertions or
|
|
// removals can be performed.
|
|
func (b *defaultBackend) Lock() {
|
|
b.mtx.Lock()
|
|
}
|
|
|
|
// Unlock unlocks the registry.
|
|
func (b *defaultBackend) Unlock() {
|
|
b.mtx.Unlock()
|
|
}
|
|
|
|
// Register a new control handler under a given id.
|
|
func (b *defaultBackend) Register(control string, f xfer.ControlHandlerFunc) {
|
|
b.handlers[control] = f
|
|
}
|
|
|
|
// Rm deletes the handler for a given name.
|
|
func (b *defaultBackend) Rm(control string) {
|
|
delete(b.handlers, control)
|
|
}
|
|
|
|
// Handler gets the handler for a control.
|
|
func (b *defaultBackend) Handler(control string) (xfer.ControlHandlerFunc, bool) {
|
|
handler, ok := b.handlers[control]
|
|
return handler, ok
|
|
}
|
|
|
|
// HandlerRegistry uses backend for storing and retrieving control
|
|
// requests handlers.
|
|
type HandlerRegistry struct {
|
|
backend HandlerRegistryBackend
|
|
}
|
|
|
|
// NewDefaultHandlerRegistry creates a registry with a default
|
|
// backend.
|
|
func NewDefaultHandlerRegistry() *HandlerRegistry {
|
|
return NewHandlerRegistry(NewDefaultHandlerRegistryBackend())
|
|
}
|
|
|
|
// NewHandlerRegistry creates a registry with a custom backend.
|
|
func NewHandlerRegistry(backend HandlerRegistryBackend) *HandlerRegistry {
|
|
return &HandlerRegistry{
|
|
backend: backend,
|
|
}
|
|
}
|
|
|
|
// Register registers a new control handler under a given name.
|
|
func (r *HandlerRegistry) Register(control string, f xfer.ControlHandlerFunc) {
|
|
r.backend.Lock()
|
|
defer r.backend.Unlock()
|
|
r.backend.Register(control, f)
|
|
}
|
|
|
|
// Rm deletes the handler for a given name.
|
|
func (r *HandlerRegistry) Rm(control string) {
|
|
r.backend.Lock()
|
|
defer r.backend.Unlock()
|
|
r.backend.Rm(control)
|
|
}
|
|
|
|
// Batch first deletes handlers for given names in toRemove then
|
|
// registers new handlers for given names in toAdd.
|
|
func (r *HandlerRegistry) Batch(toRemove []string, toAdd map[string]xfer.ControlHandlerFunc) {
|
|
r.backend.Lock()
|
|
defer r.backend.Unlock()
|
|
for _, control := range toRemove {
|
|
r.backend.Rm(control)
|
|
}
|
|
for control, handler := range toAdd {
|
|
r.backend.Register(control, handler)
|
|
}
|
|
}
|
|
|
|
// HandleControlRequest performs a control request.
|
|
func (r *HandlerRegistry) HandleControlRequest(req xfer.Request) xfer.Response {
|
|
h, ok := r.handler(req.Control)
|
|
if !ok {
|
|
return xfer.ResponseErrorf("Control %q not recognised", req.Control)
|
|
}
|
|
|
|
return h(req)
|
|
}
|
|
|
|
func (r *HandlerRegistry) handler(control string) (xfer.ControlHandlerFunc, bool) {
|
|
r.backend.Lock()
|
|
defer r.backend.Unlock()
|
|
return r.backend.Handler(control)
|
|
}
|