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, } }