diff --git a/pkg/settings/cresettings/defaults.json b/pkg/settings/cresettings/defaults.json index 62bbfc34c..654069ee9 100644 --- a/pkg/settings/cresettings/defaults.json +++ b/pkg/settings/cresettings/defaults.json @@ -57,7 +57,14 @@ "TargetsLimit": "10", "ReportSizeLimit": "5kb", "EVM": { - "TransactionGasLimit": "5000000" + "TransactionGasLimit": "5000000", + "GasLimit": { + "Default": "5000000", + "Values": { + "12922642891491394802": "50000000", + "3379446385462418246": "10000000" + } + } } }, "ChainRead": { diff --git a/pkg/settings/cresettings/defaults.toml b/pkg/settings/cresettings/defaults.toml index 013475840..687bd74d8 100644 --- a/pkg/settings/cresettings/defaults.toml +++ b/pkg/settings/cresettings/defaults.toml @@ -61,6 +61,13 @@ ReportSizeLimit = '5kb' [PerWorkflow.ChainWrite.EVM] TransactionGasLimit = '5000000' +[PerWorkflow.ChainWrite.EVM.GasLimit] +Default = '5000000' + +[PerWorkflow.ChainWrite.EVM.GasLimit.Values] +12922642891491394802 = '50000000' +3379446385462418246 = '10000000' + [PerWorkflow.ChainRead] CallLimit = '10' LogQueryBlockLimit = '100' diff --git a/pkg/settings/cresettings/settings.go b/pkg/settings/cresettings/settings.go index 2fd096419..4cb2fe69d 100644 --- a/pkg/settings/cresettings/settings.go +++ b/pkg/settings/cresettings/settings.go @@ -123,6 +123,12 @@ var Default = Schema{ ReportSizeLimit: Size(5 * config.KByte), EVM: evmChainWrite{ TransactionGasLimit: Uint64(5_000_000), + GasLimit: PerChainSelector(Uint64(5_000_000), map[string]uint64{ + // geth-testnet + "3379446385462418246": 10_000_000, + // geth-devnet2 + "12922642891491394802": 50_000_000, + }), }, }, ChainRead: chainRead{ @@ -225,7 +231,8 @@ type chainWrite struct { EVM evmChainWrite } type evmChainWrite struct { - TransactionGasLimit Setting[uint64] `unit:"{gas}"` + TransactionGasLimit Setting[uint64] `unit:"{gas}"` // Deprecated + GasLimit SettingMap[uint64] `unit:"{gas}"` } type chainRead struct { CallLimit Setting[int] `unit:"{call}"` diff --git a/pkg/settings/limits/bound.go b/pkg/settings/limits/bound.go index 815bd722c..e3f34e099 100644 --- a/pkg/settings/limits/bound.go +++ b/pkg/settings/limits/bound.go @@ -49,13 +49,13 @@ func (s *simpleBoundLimiter[N]) Limit(ctx context.Context) (N, error) { return s.bound, nil } -func newBoundLimiter[N Number](f Factory, bound settings.Setting[N]) (BoundLimiter[N], error) { +func newBoundLimiter[N Number](f Factory, bound settings.SettingSpec[N]) (BoundLimiter[N], error) { b := &boundLimiter[N]{ updater: newUpdater[N](nil, func(ctx context.Context) (N, error) { return bound.GetOrDefault(ctx, f.Settings) }, nil), - key: bound.Key, - scope: bound.Scope, + key: bound.GetKey(), + scope: bound.GetScope(), } b.updater.recordLimit = func(ctx context.Context, n N) { b.recordBound(ctx, n) } @@ -63,23 +63,24 @@ func newBoundLimiter[N Number](f Factory, bound settings.Setting[N]) (BoundLimit if b.key == "" { return nil, errors.New("metrics require Key to be set") } - newGauge, newHist := metricConstructors[N](f.Meter, bound.Unit) + newGauge, newHist := metricConstructors[N](f.Meter, bound.GetUnit()) - limitGauge, err := newGauge("bound." + bound.Key + ".limit") + key := bound.GetKey() + limitGauge, err := newGauge("bound." + key + ".limit") if err != nil { return nil, err } b.recordBound = func(ctx context.Context, value N, options ...metric.RecordOption) { limitGauge.Record(ctx, value, options...) } - usageHist, err := newHist("bound." + bound.Key + ".usage") + usageHist, err := newHist("bound." + key + ".usage") if err != nil { return nil, err } b.recordUsage = func(ctx context.Context, value N, options ...metric.RecordOption) { usageHist.Record(ctx, value, options...) } - deniedHist, err := newHist("bound." + bound.Key + ".denied") + deniedHist, err := newHist("bound." + key + ".denied") if err != nil { return nil, err } @@ -93,7 +94,7 @@ func newBoundLimiter[N Number](f Factory, bound settings.Setting[N]) (BoundLimit } if f.Logger != nil { - b.lggr = logger.Sugared(f.Logger).Named("BoundLimiter").With("key", bound.Key) + b.lggr = logger.Sugared(f.Logger).Named("BoundLimiter").With("key", bound.GetKey()) } if f.Settings != nil { @@ -104,7 +105,7 @@ func newBoundLimiter[N Number](f Factory, bound settings.Setting[N]) (BoundLimit } } - if bound.Scope == settings.ScopeGlobal { + if bound.GetScope() == settings.ScopeGlobal { b.updateCRE(contexts.CRE{}) go b.updateLoop(contexts.CRE{}) } diff --git a/pkg/settings/limits/factory.go b/pkg/settings/limits/factory.go index 97c876d03..849ec11da 100644 --- a/pkg/settings/limits/factory.go +++ b/pkg/settings/limits/factory.go @@ -82,8 +82,8 @@ func MakeResourcePoolLimiter[N Number](f Factory, limit settings.Setting[N]) (Re // - bound.*.limit - gauge // - bound.*.usage - histogram // - bound.*.denied - histogram -func MakeBoundLimiter[N Number](f Factory, bound settings.Setting[N]) (BoundLimiter[N], error) { - return newBoundLimiter(f, bound) +func MakeBoundLimiter[N Number](f Factory, bound settings.IsSetting[N]) (BoundLimiter[N], error) { + return newBoundLimiter(f, bound.GetSpec()) } // MakeQueueLimiter returns a QueueLimiter for the given limit and configured by the Factory. @@ -103,8 +103,6 @@ func MakeQueueLimiter[T any](f Factory, limit settings.Setting[int]) (QueueLimit // - gate.*.limit - int gauge // - gate.*.usage - int counter // - gate.*.denied - int counter -// -// OPT: accept an interface for limit -func MakeGateLimiter(f Factory, limit settings.SettingMap[bool]) (GateLimiter, error) { - return newGateLimiter(f, limit) +func MakeGateLimiter(f Factory, limit settings.IsSetting[bool]) (GateLimiter, error) { + return newGateLimiter(f, limit.GetSpec()) } diff --git a/pkg/settings/limits/gate.go b/pkg/settings/limits/gate.go index 20f9d0cea..ceed5f0a7 100644 --- a/pkg/settings/limits/gate.go +++ b/pkg/settings/limits/gate.go @@ -44,14 +44,13 @@ func (s *simpleGateLimiter) AllowErr(ctx context.Context) error { return nil } -// OPT: interface satisfied by Setting[bool] & SettingMap[bool] -func newGateLimiter(f Factory, limit settings.SettingMap[bool]) (GateLimiter, error) { +func newGateLimiter(f Factory, limit settings.SettingSpec[bool]) (GateLimiter, error) { g := &gateLimiter{ updater: newUpdater[bool](nil, func(ctx context.Context) (bool, error) { return limit.GetOrDefault(ctx, f.Settings) }, nil), - key: limit.Default.Key, - scope: limit.Default.Scope, + key: limit.GetKey(), + scope: limit.GetScope(), } g.updater.recordLimit = func(ctx context.Context, b bool) { g.recordStatus(ctx, b) } @@ -59,7 +58,8 @@ func newGateLimiter(f Factory, limit settings.SettingMap[bool]) (GateLimiter, er if g.key == "" { return nil, errors.New("metrics require Key to be set") } - limitGauge, err := f.Meter.Int64Gauge("gate."+g.key+".limit", metric.WithUnit(limit.Default.Unit)) + unit := limit.GetUnit() + limitGauge, err := f.Meter.Int64Gauge("gate."+g.key+".limit", metric.WithUnit(unit)) if err != nil { return nil, err } @@ -70,14 +70,14 @@ func newGateLimiter(f Factory, limit settings.SettingMap[bool]) (GateLimiter, er } limitGauge.Record(ctx, val, options...) } - usageCounter, err := f.Meter.Int64Counter("gate."+g.key+".usage", metric.WithUnit(limit.Default.Unit)) + usageCounter, err := f.Meter.Int64Counter("gate."+g.key+".usage", metric.WithUnit(unit)) if err != nil { return nil, err } g.recordUsage = func(ctx context.Context, options ...metric.AddOption) { usageCounter.Add(ctx, 1, options...) } - deniedCounter, err := f.Meter.Int64Counter("gate."+g.key+".denied", metric.WithUnit(limit.Default.Unit)) + deniedCounter, err := f.Meter.Int64Counter("gate."+g.key+".denied", metric.WithUnit(unit)) if err != nil { return nil, err } @@ -91,7 +91,7 @@ func newGateLimiter(f Factory, limit settings.SettingMap[bool]) (GateLimiter, er } if f.Logger != nil { - g.lggr = logger.Sugared(f.Logger).Named("GateLimiter").With("key", limit.Default.Key) + g.lggr = logger.Sugared(f.Logger).Named("GateLimiter").With("key", limit.GetKey()) } // OPT: support settings.Registry subscriptions diff --git a/pkg/settings/map.go b/pkg/settings/map.go index c758d9c16..634082036 100644 --- a/pkg/settings/map.go +++ b/pkg/settings/map.go @@ -23,12 +23,22 @@ func PerChainSelector[T any](defaultValue Setting[T], vals map[string]T) Setting } } +var _ IsSetting[int] = SettingMap[int]{} + type SettingMap[T any] struct { Default Setting[T] Values map[string]string // unparsed KeyFromCtx func(context.Context) (uint64, error) `json:"-" toml:"-"` } +func (s SettingMap[T]) GetSpec() SettingSpec[T] { return &s } + +func (s *SettingMap[T]) GetKey() string { return s.Default.Key } + +func (s *SettingMap[T]) GetScope() Scope { return s.Default.Scope } + +func (s *SettingMap[T]) GetUnit() string { return s.Default.Unit } + func (s *SettingMap[T]) initSetting(key string, scope Scope, unit *string) error { if s.KeyFromCtx == nil { return errors.New("missing KeyFromCtx func") @@ -86,3 +96,11 @@ func (s *SettingMap[T]) GetOrDefault(ctx context.Context, g Getter) (value T, er } return } + +func (s *SettingMap[T]) Subscribe(ctx context.Context, registry Registry) (<-chan Update[T], func()) { + //TODO subscribe to Values & Default + + // no-op + ch := make(chan Update[T]) + return ch, func() { close(ch) } +} diff --git a/pkg/settings/settings.go b/pkg/settings/settings.go index e8b955bbb..688d18d2f 100644 --- a/pkg/settings/settings.go +++ b/pkg/settings/settings.go @@ -30,6 +30,21 @@ type Registry interface { SubscribeScoped(ctx context.Context, scope Scope, key string) (updates <-chan Update[string], stop func()) } +//TODO use this everywhere +type IsSetting[T any] interface { + GetSpec() SettingSpec[T] +} + +type SettingSpec[T any] interface { + GetKey() string + GetScope() Scope + GetUnit() string + GetOrDefault(context.Context, Getter) (T, error) + Subscribe(context.Context, Registry) (<-chan Update[T], func()) +} + +var _ IsSetting[int] = Setting[int]{} + // Setting holds a key, default value, and parsing function for a particular setting. // Use Setting.GetOrDefault with a Getter to look up settings. // Use Setting.Subscribe with a Registry to have updates pushed over a channel. @@ -41,6 +56,14 @@ type Setting[T any] struct { Unit string } +func (s Setting[T]) GetSpec() SettingSpec[T] { return &s } + +func (s *Setting[T]) GetKey() string { return s.Key } + +func (s *Setting[T]) GetScope() Scope { return s.Scope } + +func (s *Setting[T]) GetUnit() string { return s.Unit } + func (s Setting[T]) MarshalText() ([]byte, error) { return fmt.Appendf(nil, "%v", s.DefaultValue), nil }