mirror of
https://github.com/MichaelMure/git-bug.git
synced 2024-12-14 17:51:44 +03:00
87 lines
1.9 KiB
Go
87 lines
1.9 KiB
Go
package entity
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// Resolver is an interface to find an Entity from its Id
|
|
type Resolver interface {
|
|
Resolve(id Id) (Interface, error)
|
|
}
|
|
|
|
// Resolvers is a collection of Resolver, for different type of Entity
|
|
type Resolvers map[Interface]Resolver
|
|
|
|
// Resolve use the appropriate sub-resolver for the given type and find the Entity matching the Id.
|
|
func Resolve[T Interface](rs Resolvers, id Id) (T, error) {
|
|
var zero T
|
|
for t, resolver := range rs {
|
|
switch t.(type) {
|
|
case T:
|
|
val, err := resolver.(Resolver).Resolve(id)
|
|
if err != nil {
|
|
return zero, err
|
|
}
|
|
return val.(T), nil
|
|
}
|
|
}
|
|
return zero, fmt.Errorf("unknown type to resolve")
|
|
}
|
|
|
|
var _ Resolver = &CachedResolver{}
|
|
|
|
// CachedResolver is a resolver ensuring that loading is done only once through another Resolver.
|
|
type CachedResolver struct {
|
|
resolver Resolver
|
|
mu sync.RWMutex
|
|
entities map[Id]Interface
|
|
}
|
|
|
|
func NewCachedResolver(resolver Resolver) *CachedResolver {
|
|
return &CachedResolver{
|
|
resolver: resolver,
|
|
entities: make(map[Id]Interface),
|
|
}
|
|
}
|
|
|
|
func (c *CachedResolver) Resolve(id Id) (Interface, error) {
|
|
c.mu.RLock()
|
|
if i, ok := c.entities[id]; ok {
|
|
c.mu.RUnlock()
|
|
return i, nil
|
|
}
|
|
c.mu.RUnlock()
|
|
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
i, err := c.resolver.Resolve(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c.entities[id] = i
|
|
return i, nil
|
|
}
|
|
|
|
var _ Resolver = ResolverFunc(nil)
|
|
|
|
// ResolverFunc is a helper to morph a function resolver into a Resolver
|
|
type ResolverFunc func(id Id) (Interface, error)
|
|
|
|
func (fn ResolverFunc) Resolve(id Id) (Interface, error) {
|
|
return fn(id)
|
|
}
|
|
|
|
// MakeResolver create a resolver able to return the given entities.
|
|
func MakeResolver(entities ...Interface) Resolver {
|
|
return ResolverFunc(func(id Id) (Interface, error) {
|
|
for _, entity := range entities {
|
|
if entity.Id() == id {
|
|
return entity, nil
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("entity not found")
|
|
})
|
|
}
|