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  }