58 lines
1.3 KiB
Go
58 lines
1.3 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"sort"
|
|
"sync"
|
|
)
|
|
|
|
type Definition struct{ Key, Name, Description string }
|
|
type Tool interface {
|
|
Definition() Definition
|
|
StudentHandler() http.Handler
|
|
}
|
|
type InstructorTool interface{ InstructorHandler() http.Handler }
|
|
type Runner interface{ Run(context.Context) error }
|
|
|
|
var ErrNotFound = errors.New("tool not found")
|
|
|
|
type Registry struct {
|
|
mu sync.RWMutex
|
|
tools map[string]Tool
|
|
}
|
|
|
|
func NewRegistry() *Registry { return &Registry{tools: make(map[string]Tool)} }
|
|
func (r *Registry) Register(t Tool) error {
|
|
if t == nil || t.Definition().Key == "" {
|
|
return errors.New("tool key is required")
|
|
}
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
if _, ok := r.tools[t.Definition().Key]; ok {
|
|
return errors.New("duplicate tool key")
|
|
}
|
|
r.tools[t.Definition().Key] = t
|
|
return nil
|
|
}
|
|
func (r *Registry) Get(key string) (Tool, error) {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
t, ok := r.tools[key]
|
|
if !ok {
|
|
return nil, ErrNotFound
|
|
}
|
|
return t, nil
|
|
}
|
|
func (r *Registry) List() []Tool {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
out := make([]Tool, 0, len(r.tools))
|
|
for _, t := range r.tools {
|
|
out = append(out, t)
|
|
}
|
|
sort.Slice(out, func(i, j int) bool { return out[i].Definition().Name < out[j].Definition().Name })
|
|
return out
|
|
}
|