openmeter / pkg /models /servicehook.go
Leon4gr45's picture
Upload folder using huggingface_hub (part 10)
6380833 verified
Raw
History Blame Contribute Delete
3.31 kB
package models
import (
"context"
"fmt"
"sync"
)
type ServiceHook[T any] interface {
PreUpdate(context.Context, *T) error
PreDelete(context.Context, *T) error
PostCreate(context.Context, *T) error
PostUpdate(context.Context, *T) error
PostDelete(context.Context, *T) error
}
type ServiceHooks[T any] interface {
RegisterHooks(...ServiceHook[T])
}
var (
_ ServiceHooks[any] = (*ServiceHookRegistry[any])(nil)
_ ServiceHook[any] = (*ServiceHookRegistry[any])(nil)
)
type loopKey string
var loopVal = struct{}{}
type ServiceHookRegistry[T any] struct {
hooks []ServiceHook[T]
mu sync.RWMutex
id loopKey
once sync.Once
}
func (r *ServiceHookRegistry[T]) init() {
r.once.Do(func() {
r.id = loopKey(fmt.Sprintf("service-hook-registry-%p", r))
})
}
func (r *ServiceHookRegistry[T]) PreUpdate(ctx context.Context, t *T) error {
r.init()
if v := ctx.Value(r.id); v != nil {
return nil
}
ctx = context.WithValue(ctx, r.id, loopVal)
r.mu.RLock()
defer r.mu.RUnlock()
for _, hook := range r.hooks {
if err := hook.PreUpdate(ctx, t); err != nil {
return err
}
}
return nil
}
func (r *ServiceHookRegistry[T]) PreDelete(ctx context.Context, t *T) error {
r.init()
if v := ctx.Value(r.id); v != nil {
return nil
}
ctx = context.WithValue(ctx, r.id, loopVal)
r.mu.RLock()
defer r.mu.RUnlock()
for _, hook := range r.hooks {
if err := hook.PreDelete(ctx, t); err != nil {
return err
}
}
return nil
}
func (r *ServiceHookRegistry[T]) PostCreate(ctx context.Context, t *T) error {
r.init()
if v := ctx.Value(r.id); v != nil {
return nil
}
ctx = context.WithValue(ctx, r.id, loopVal)
r.mu.RLock()
defer r.mu.RUnlock()
for _, hook := range r.hooks {
if err := hook.PostCreate(ctx, t); err != nil {
return err
}
}
return nil
}
func (r *ServiceHookRegistry[T]) PostUpdate(ctx context.Context, t *T) error {
r.init()
if v := ctx.Value(r.id); v != nil {
return nil
}
ctx = context.WithValue(ctx, r.id, loopVal)
r.mu.RLock()
defer r.mu.RUnlock()
for _, hook := range r.hooks {
if err := hook.PostUpdate(ctx, t); err != nil {
return err
}
}
return nil
}
func (r *ServiceHookRegistry[T]) PostDelete(ctx context.Context, t *T) error {
r.init()
if v := ctx.Value(r.id); v != nil {
return nil
}
ctx = context.WithValue(ctx, r.id, loopVal)
r.mu.RLock()
defer r.mu.RUnlock()
for _, hook := range r.hooks {
if err := hook.PostDelete(ctx, t); err != nil {
return err
}
}
return nil
}
func (r *ServiceHookRegistry[T]) RegisterHooks(hooks ...ServiceHook[T]) {
r.mu.Lock()
defer r.mu.Unlock()
r.hooks = append(r.hooks, hooks...)
}
func NewServiceHookRegistry[T any]() *ServiceHookRegistry[T] {
return &ServiceHookRegistry[T]{
hooks: []ServiceHook[T]{},
mu: sync.RWMutex{},
}
}
var _ ServiceHook[any] = (*NoopServiceHook[any])(nil)
type NoopServiceHook[T any] struct{}
func (n NoopServiceHook[T]) PreUpdate(context.Context, *T) error {
return nil
}
func (n NoopServiceHook[T]) PreDelete(context.Context, *T) error {
return nil
}
func (n NoopServiceHook[T]) PostCreate(context.Context, *T) error {
return nil
}
func (n NoopServiceHook[T]) PostUpdate(context.Context, *T) error {
return nil
}
func (n NoopServiceHook[T]) PostDelete(context.Context, *T) error {
return nil
}