github.com/prebid/prebid-server/v2@v2.18.0/stored_requests/multifetcher.go (about) 1 package stored_requests 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 ) 8 9 // MultiFetcher is a Fetcher composed of multiple sub-Fetchers that are all polled for results. 10 type MultiFetcher []AllFetcher 11 12 // FetchRequests implements the Fetcher interface for MultiFetcher 13 func (mf MultiFetcher) FetchRequests(ctx context.Context, requestIDs []string, impIDs []string) (requestData map[string]json.RawMessage, impData map[string]json.RawMessage, errs []error) { 14 requestData = make(map[string]json.RawMessage, len(requestIDs)) 15 impData = make(map[string]json.RawMessage, len(impIDs)) 16 17 // Loop over the fetchers 18 for _, f := range mf { 19 remainingRequestIDs := filter(requestIDs, requestData) 20 requestIDs = remainingRequestIDs 21 remainingImpIDs := filter(impIDs, impData) 22 impIDs = remainingImpIDs 23 24 theseRequestData, theseImpData, rerrs := f.FetchRequests(ctx, remainingRequestIDs, remainingImpIDs) 25 // Drop NotFound errors, as other fetchers may have them. Also don't want multiple NotFound errors per ID. 26 rerrs = dropMissingIDs(rerrs) 27 if len(rerrs) > 0 { 28 errs = append(errs, rerrs...) 29 } 30 addAll(requestData, theseRequestData) 31 addAll(impData, theseImpData) 32 } 33 // Add missing ID errors back in for any IDs that are still missing 34 errs = appendNotFoundErrors("Request", requestIDs, requestData, errs) 35 errs = appendNotFoundErrors("Imp", impIDs, impData, errs) 36 return 37 } 38 39 func (mf MultiFetcher) FetchResponses(ctx context.Context, ids []string) (data map[string]json.RawMessage, errs []error) { 40 return nil, nil 41 } 42 43 func (mf MultiFetcher) FetchAccount(ctx context.Context, accountDefaultJSON json.RawMessage, accountID string) (account json.RawMessage, errs []error) { 44 for _, f := range mf { 45 if af, ok := f.(AccountFetcher); ok { 46 if account, accErrs := af.FetchAccount(ctx, accountDefaultJSON, accountID); len(accErrs) == 0 { 47 return account, nil 48 } else { 49 accErrs = dropMissingIDs(accErrs) 50 errs = append(errs, accErrs...) 51 } 52 } 53 } 54 errs = append(errs, NotFoundError{accountID, "Account"}) 55 return nil, errs 56 } 57 58 func (mf MultiFetcher) FetchCategories(ctx context.Context, primaryAdServer, publisherId, iabCategory string) (string, error) { 59 for _, f := range mf { 60 if cf, ok := f.(CategoryFetcher); ok { 61 iabCategory, _ := cf.FetchCategories(ctx, primaryAdServer, publisherId, iabCategory) 62 if iabCategory != "" { 63 return iabCategory, nil 64 } 65 } 66 } 67 68 // For now just return a NotFoundError if we didn't find it for some reason 69 errtype := fmt.Sprintf("%s_%s.%s", primaryAdServer, publisherId, iabCategory) 70 return "", NotFoundError{errtype, "Category"} 71 } 72 73 func addAll(base map[string]json.RawMessage, toAdd map[string]json.RawMessage) { 74 for k, v := range toAdd { 75 base[k] = v 76 } 77 } 78 79 func filter(original []string, exclude map[string]json.RawMessage) (filtered []string) { 80 if len(exclude) == 0 { 81 filtered = original 82 return 83 } 84 filtered = make([]string, 0, len(original)) 85 for _, id := range original { 86 if _, ok := exclude[id]; !ok { 87 filtered = append(filtered, id) 88 } 89 } 90 return 91 } 92 93 func appendNotFoundErrors(dataType string, expected []string, contains map[string]json.RawMessage, errs []error) []error { 94 for _, id := range expected { 95 if _, ok := contains[id]; !ok { 96 errs = append(errs, NotFoundError{id, dataType}) 97 } 98 } 99 return errs 100 } 101 102 // dropMissingIDs will scrub the NotFoundError's from a slice of errors. 103 // The order of the errors will not be preserved. 104 func dropMissingIDs(errs []error) []error { 105 // filtered errors 106 ferrs := errs[:0] 107 for _, e := range errs { 108 if _, ok := e.(NotFoundError); !ok { 109 ferrs = append(ferrs, e) 110 } 111 } 112 return ferrs 113 }