bouncer/internal/proxy/director/layer/util/revisioned_rule_engine.go

52 lines
1.1 KiB
Go

package util
import (
"context"
"sync"
"forge.cadoles.com/cadoles/bouncer/internal/rule"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/logger"
)
type RuleEngineFactoryFunc[V any, O any] func(ops O) (*rule.Engine[V], error)
type RevisionedRuleEngine[V any, O any] struct {
mutex sync.RWMutex
revision int
engine *rule.Engine[V]
factory RuleEngineFactoryFunc[V, O]
}
func (e *RevisionedRuleEngine[V, O]) Get(ctx context.Context, revision int, opts O) (*rule.Engine[V], error) {
e.mutex.RLock()
if revision == e.revision {
logger.Debug(ctx, "using cached rule engine", logger.F("layerRevision", revision))
defer e.mutex.RUnlock()
return e.engine, nil
}
e.mutex.RUnlock()
e.mutex.Lock()
defer e.mutex.Unlock()
logger.Debug(ctx, "creating rule engine", logger.F("layerRevision", revision))
engine, err := e.factory(opts)
if err != nil {
return nil, errors.WithStack(err)
}
e.engine = engine
e.revision = revision
return engine, nil
}
func NewRevisionedRuleEngine[V any, O any](factory RuleEngineFactoryFunc[V, O]) *RevisionedRuleEngine[V, O] {
return &RevisionedRuleEngine[V, O]{
factory: factory,
}
}