github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/pkg/publisher/combo/fallback.go (about) 1 package combo 2 3 import ( 4 "context" 5 6 "github.com/filecoin-project/bacalhau/pkg/model" 7 "github.com/filecoin-project/bacalhau/pkg/publisher" 8 "github.com/rs/zerolog/log" 9 "go.uber.org/multierr" 10 ) 11 12 type fallbackPublisher struct { 13 publishers []publisher.Publisher 14 } 15 16 // NewFallbackPublisher returns a publisher.Publisher that will try multiple other 17 // Publishers in order until one succeeds. 18 // 19 // The Publishers are tried in the order specified in the call to 20 // NewFallbackPublisher. If and only if all the Publishers return an error 21 // result, the fallback publisher will also return an error result. Otherwise, 22 // it will return the result of the first Publisher to succeed and will swallow 23 // any errors. Subsequent Publishers will not be attempted after one succeeds. 24 func NewFallbackPublisher(publishers ...publisher.Publisher) publisher.Publisher { 25 return &fallbackPublisher{ 26 publishers: publishers, 27 } 28 } 29 30 // fallback accepts a slice of publisher objects and passes them to the supplied 31 // function in order, until one does not return an error value and then returns 32 // that result. If all publishers return an error value, a composite error is 33 // returned. 34 func fallback[T any, P any](ctx context.Context, publishers []P, method func(P) (T, error)) (T, error) { 35 var anyErr error 36 for _, publisher := range publishers { 37 result, err := method(publisher) 38 if err == nil { 39 return result, nil 40 } else { 41 log.Ctx(ctx).Warn().Msgf("publisher %v returned an error: %s", publisher, err.Error()) 42 anyErr = multierr.Append(anyErr, err) 43 } 44 } 45 46 var zeroResult T 47 return zeroResult, anyErr 48 } 49 50 // IsInstalled implements publisher.Publisher 51 func (f *fallbackPublisher) IsInstalled(ctx context.Context) (bool, error) { 52 return fallback(ctx, f.publishers, func(p publisher.Publisher) (bool, error) { 53 return p.IsInstalled(ctx) 54 }) 55 } 56 57 // PublishShardResult implements publisher.Publisher 58 func (f *fallbackPublisher) PublishShardResult( 59 ctx context.Context, 60 shard model.JobShard, 61 hostID string, 62 shardResultPath string, 63 ) (model.StorageSpec, error) { 64 return fallback(ctx, f.publishers, func(p publisher.Publisher) (model.StorageSpec, error) { 65 return p.PublishShardResult(ctx, shard, hostID, shardResultPath) 66 }) 67 }