github.com/ethersphere/bee/v2@v2.2.0/pkg/file/redundancy/getter/strategies.go (about) 1 // Copyright 2023 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package getter 6 7 import ( 8 "context" 9 "fmt" 10 "time" 11 12 "github.com/ethersphere/bee/v2/pkg/log" 13 "github.com/ethersphere/bee/v2/pkg/retrieval" 14 ) 15 16 const ( 17 DefaultStrategy = DATA // default prefetching strategy 18 DefaultStrict = false // default fallback modes 19 DefaultFetchTimeout = retrieval.RetrieveChunkTimeout // timeout for each chunk retrieval 20 ) 21 22 type ( 23 strategyKey struct{} 24 modeKey struct{} 25 fetchTimeoutKey struct{} 26 loggerKey struct{} 27 Strategy = int 28 ) 29 30 // Config is the configuration for the getter - public 31 type Config struct { 32 Strategy Strategy 33 Strict bool 34 FetchTimeout time.Duration 35 Logger log.Logger 36 } 37 38 const ( 39 NONE Strategy = iota // no prefetching and no decoding 40 DATA // just retrieve data shards no decoding 41 PROX // proximity driven selective fetching 42 RACE // aggressive fetching racing all chunks 43 strategyCnt 44 ) 45 46 // DefaultConfig is the default configuration for the getter 47 var DefaultConfig = Config{ 48 Strategy: DefaultStrategy, 49 Strict: DefaultStrict, 50 FetchTimeout: DefaultFetchTimeout, 51 Logger: log.Noop, 52 } 53 54 // NewConfigFromContext returns a new Config based on the context 55 func NewConfigFromContext(ctx context.Context, def Config) (conf Config, err error) { 56 var ok bool 57 conf = def 58 e := func(s string) error { 59 return fmt.Errorf("error setting %s from context", s) 60 } 61 if val := ctx.Value(strategyKey{}); val != nil { 62 conf.Strategy, ok = val.(Strategy) 63 if !ok { 64 return conf, e("strategy") 65 } 66 } 67 if val := ctx.Value(modeKey{}); val != nil { 68 conf.Strict, ok = val.(bool) 69 if !ok { 70 return conf, e("fallback mode") 71 } 72 } 73 if val := ctx.Value(fetchTimeoutKey{}); val != nil { 74 conf.FetchTimeout, ok = val.(time.Duration) 75 if !ok { 76 return conf, e("fetcher timeout") 77 } 78 } 79 if val := ctx.Value(loggerKey{}); val != nil { 80 conf.Logger, ok = val.(log.Logger) 81 if !ok { 82 return conf, e("strategy timeout") 83 } 84 } 85 86 return conf, nil 87 } 88 89 // SetStrategy sets the strategy for the retrieval 90 func SetStrategy(ctx context.Context, s Strategy) context.Context { 91 return context.WithValue(ctx, strategyKey{}, s) 92 } 93 94 // SetStrict sets the strict mode for the retrieval 95 func SetStrict(ctx context.Context, strict bool) context.Context { 96 return context.WithValue(ctx, modeKey{}, strict) 97 } 98 99 // SetFetchTimeout sets the timeout for each fetch 100 func SetFetchTimeout(ctx context.Context, timeout time.Duration) context.Context { 101 return context.WithValue(ctx, fetchTimeoutKey{}, timeout) 102 } 103 104 func SetLogger(ctx context.Context, l log.Logger) context.Context { 105 return context.WithValue(ctx, loggerKey{}, l) 106 } 107 108 // SetConfigInContext sets the config params in the context 109 func SetConfigInContext(ctx context.Context, s *Strategy, fallbackmode *bool, fetchTimeout *string, logger log.Logger) (context.Context, error) { 110 if s != nil { 111 ctx = SetStrategy(ctx, *s) 112 } 113 114 if fallbackmode != nil { 115 ctx = SetStrict(ctx, !(*fallbackmode)) 116 } 117 118 if fetchTimeout != nil { 119 dur, err := time.ParseDuration(*fetchTimeout) 120 if err != nil { 121 return nil, err 122 } 123 ctx = SetFetchTimeout(ctx, dur) 124 } 125 126 if logger != nil { 127 ctx = SetLogger(ctx, logger) 128 } 129 130 return ctx, nil 131 }