openmeter / namespace /namespace.go
Leon4gr45's picture
Upload folder using huggingface_hub (part 6)
d6f631f verified
Raw
History Blame Contribute Delete
3.47 kB
// Package namespace adds a concept of tenancy to OpenMeter allowing to segment clients.
package namespace
import (
"context"
"errors"
"sync"
)
// Manager is responsible for managing namespaces in different components.
type Manager struct {
config ManagerConfig
mu sync.RWMutex
}
type ManagerConfig struct {
DefaultNamespace string
DisableManagement bool
Handlers []Handler
}
func NewManager(config ManagerConfig) (*Manager, error) {
if config.DefaultNamespace == "" {
return nil, errors.New("default namespace is required")
}
for _, handler := range config.Handlers {
if handler == nil {
return nil, errors.New("handler must not be nil")
}
}
manager := Manager{
config: config,
mu: sync.RWMutex{},
}
return &manager, nil
}
// Handler is responsible for creating a namespace in a given component.
//
// An empty name means a default namespace is supposed to be created.
// The concept of a default namespace is implementation specific.
//
// The behavior for trying to create a namespace that already exists is unspecified at the moment.
type Handler interface {
CreateNamespace(ctx context.Context, name string) error
DeleteNamespace(ctx context.Context, name string) error
}
// CreateNamespace orchestrates namespace creation across different components.
func (m *Manager) CreateNamespace(ctx context.Context, name string) error {
if name == "" {
return errors.New("cannot create empty namespace")
}
return m.createNamespace(ctx, name)
}
// DeleteNamespace orchestrates namespace creation across different components.
func (m *Manager) DeleteNamespace(ctx context.Context, name string) error {
if name == "" {
return errors.New("cannot delete empty namespace")
}
if name == m.config.DefaultNamespace {
return errors.New("cannot delete default namespace")
}
return m.deleteNamespace(ctx, name)
}
// RegisterHandler registers handler to be invoked on namespace create/delete.
func (m *Manager) RegisterHandler(handler Handler) error {
if handler == nil {
return errors.New("cannot register nil handler")
}
m.mu.Lock()
defer m.mu.Unlock()
m.config.Handlers = append(m.config.Handlers, handler)
return nil
}
// CreateDefaultNamespace orchestrates the creation of a default namespace.
//
// The concept of a default namespace is implementation specific.
func (m *Manager) CreateDefaultNamespace(ctx context.Context) error {
return m.createNamespace(ctx, m.config.DefaultNamespace)
}
func (m *Manager) GetDefaultNamespace() string {
return m.config.DefaultNamespace
}
func (m *Manager) IsManagementDisabled() bool {
return m.config.DisableManagement
}
// TODO: introduce some resiliency (eg. retries or rollbacks in case a component fails to create a namespace).
func (m *Manager) createNamespace(ctx context.Context, name string) error {
var errs []error
m.mu.RLock()
defer m.mu.RUnlock()
for _, handler := range m.config.Handlers {
err := handler.CreateNamespace(ctx, name)
if err != nil {
errs = append(errs, err)
}
}
return errors.Join(errs...)
}
// TODO: introduce some resiliency (eg. retries or rollbacks in case a component fails to delete a namespace).
func (m *Manager) deleteNamespace(ctx context.Context, name string) error {
var errs []error
m.mu.RLock()
defer m.mu.RUnlock()
for _, handler := range m.config.Handlers {
err := handler.DeleteNamespace(ctx, name)
if err != nil {
errs = append(errs, err)
}
}
return errors.Join(errs...)
}