chore: add generic registry with context support (#15203)

This commit is contained in:
andig 2024-08-02 17:23:19 +02:00 • committed by GitHub
parent ec9a2ab6e9
commit ccc9e6c19a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 76 additions and 76 deletions

View file

@ -1,31 +1,21 @@
package charger
import (
"context"
"fmt"
"strings"
"github.com/evcc-io/evcc/api"
reg "github.com/evcc-io/evcc/util/registry"
)
type chargerRegistry map[string]func(map[string]interface{}) (api.Charger, error)
var registry = reg.New[api.Charger]("charger")
func (r chargerRegistry) Add(name string, factory func(map[string]interface{}) (api.Charger, error)) {
if _, exists := r[name]; exists {
panic(fmt.Sprintf("cannot register duplicate charger type: %s", name))
}
r[name] = factory
// Types returns the list of types
func Types() []string {
return registry.Types()
}
func (r chargerRegistry) Get(name string) (func(map[string]interface{}) (api.Charger, error), error) {
factory, exists := r[name]
if !exists {
return nil, fmt.Errorf("invalid charger type: %s", name)
}
return factory, nil
}
var registry chargerRegistry = make(map[string]func(map[string]interface{}) (api.Charger, error))
// NewFromConfig creates charger from configuration
func NewFromConfig(typ string, other map[string]interface{}) (api.Charger, error) {
factory, err := registry.Get(strings.ToLower(typ))
@ -33,7 +23,7 @@ func NewFromConfig(typ string, other map[string]interface{}) (api.Charger, error
return nil, err
}
v, err := factory(other)
v, err := factory(context.TODO(), other)
if err != nil {
err = fmt.Errorf("cannot create charger type '%s': %w", typ, err)
}

View file

@ -1,31 +1,21 @@
package meter
import (
"context"
"fmt"
"strings"
"github.com/evcc-io/evcc/api"
reg "github.com/evcc-io/evcc/util/registry"
)
type meterRegistry map[string]func(map[string]interface{}) (api.Meter, error)
var registry = reg.New[api.Meter]("meter")
func (r meterRegistry) Add(name string, factory func(map[string]interface{}) (api.Meter, error)) {
if _, exists := r[name]; exists {
panic(fmt.Sprintf("cannot register duplicate meter type: %s", name))
}
r[name] = factory
// Types returns the list of types
func Types() []string {
return registry.Types()
}
func (r meterRegistry) Get(name string) (func(map[string]interface{}) (api.Meter, error), error) {
factory, exists := r[name]
if !exists {
return nil, fmt.Errorf("invalid meter type: %s", name)
}
return factory, nil
}
var registry meterRegistry = make(map[string]func(map[string]interface{}) (api.Meter, error))
// NewFromConfig creates meter from configuration
func NewFromConfig(typ string, other map[string]interface{}) (api.Meter, error) {
factory, err := registry.Get(strings.ToLower(typ))
@ -33,7 +23,7 @@ func NewFromConfig(typ string, other map[string]interface{}) (api.Meter, error)
return nil, err
}
v, err := factory(other)
v, err := factory(context.TODO(), other)
if err != nil {
err = fmt.Errorf("cannot create meter type '%s': %w", typ, err)
}

View file

@ -1,31 +1,21 @@
package tariff
import (
"context"
"fmt"
"strings"
"github.com/evcc-io/evcc/api"
reg "github.com/evcc-io/evcc/util/registry"
)
type tariffRegistry map[string]func(map[string]interface{}) (api.Tariff, error)
var registry = reg.New[api.Tariff]("tariff")
func (r tariffRegistry) Add(name string, factory func(map[string]interface{}) (api.Tariff, error)) {
if _, exists := r[name]; exists {
panic(fmt.Sprintf("cannot register duplicate tariff type: %s", name))
}
r[name] = factory
// Types returns the list of types
func Types() []string {
return registry.Types()
}
func (r tariffRegistry) Get(name string) (func(map[string]interface{}) (api.Tariff, error), error) {
factory, exists := r[name]
if !exists {
return nil, fmt.Errorf("invalid tariff type: %s", name)
}
return factory, nil
}
var registry tariffRegistry = make(map[string]func(map[string]interface{}) (api.Tariff, error))
// NewFromConfig creates tariff from configuration
func NewFromConfig(typ string, other map[string]interface{}) (api.Tariff, error) {
factory, err := registry.Get(strings.ToLower(typ))
@ -33,7 +23,7 @@ func NewFromConfig(typ string, other map[string]interface{}) (api.Tariff, error)
return nil, err
}
v, err := factory(other)
v, err := factory(context.TODO(), other)
if err != nil {
err = fmt.Errorf("cannot create tariff type '%s': %w", typ, err)
}

49
util/registry/registry.go Normal file
View file

@ -0,0 +1,49 @@
package registry
import (
"context"
"fmt"
"golang.org/x/exp/maps"
)
type (
factoryFunc[T any] func(context.Context, map[string]any) (T, error)
registry[T any] struct {
typ string
data map[string]factoryFunc[T]
}
)
func (r registry[T]) Add(name string, factory func(map[string]any) (T, error)) {
r.AddCtx(name, func(_ context.Context, cc map[string]any) (T, error) {
return factory(cc)
})
}
func (r registry[T]) AddCtx(name string, factory factoryFunc[T]) {
if _, exists := r.data[name]; exists {
panic(fmt.Sprintf("cannot register duplicate %s type: %s", r.typ, name))
}
r.data[name] = factory
}
func (r registry[T]) Get(name string) (factoryFunc[T], error) {
factory, exists := r.data[name]
if !exists {
return nil, fmt.Errorf("invalid %s type: %s", r.typ, name)
}
return factory, nil
}
func (r registry[T]) Types() []string {
return maps.Keys(r.data)
}
func New[T any](typ string) registry[T] {
return registry[T]{
typ: typ,
data: make(map[string]factoryFunc[T]),
}
}

View file

@ -1,12 +1,14 @@
package vehicle
import (
"context"
"fmt"
"strings"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
reg "github.com/evcc-io/evcc/util/registry"
)
const (
@ -14,32 +16,11 @@ const (
interval = 15 * time.Minute // refresh interval when charging
)
type vehicleRegistry map[string]func(map[string]interface{}) (api.Vehicle, error)
var registry = reg.New[api.Vehicle]("vehicle")
func (r vehicleRegistry) Add(name string, factory func(map[string]interface{}) (api.Vehicle, error)) {
if _, exists := r[name]; exists {
panic(fmt.Sprintf("cannot register duplicate vehicle type: %s", name))
}
r[name] = factory
}
func (r vehicleRegistry) Get(name string) (func(map[string]interface{}) (api.Vehicle, error), error) {
factory, exists := r[name]
if !exists {
return nil, fmt.Errorf("invalid vehicle type: %s", name)
}
return factory, nil
}
var registry vehicleRegistry = make(map[string]func(map[string]interface{}) (api.Vehicle, error))
// Types returns the list of vehicle types
// Types returns the list of types
func Types() []string {
var res []string
for typ := range registry {
res = append(res, typ)
}
return res
return registry.Types()
}
// NewFromConfig creates vehicle from configuration
@ -63,7 +44,7 @@ func NewFromConfig(typ string, other map[string]interface{}) (api.Vehicle, error
return nil, err
}
v, err := factory(cc.Other)
v, err := factory(context.TODO(), cc.Other)
if err != nil {
err = fmt.Errorf("cannot create vehicle type '%s': %w", typ, err)
}