github.com/prebid/prebid-server/v2@v2.18.0/modules/modules.go (about)

     1  package modules
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	"github.com/golang/glog"
     8  	"github.com/prebid/prebid-server/v2/config"
     9  	"github.com/prebid/prebid-server/v2/hooks"
    10  	"github.com/prebid/prebid-server/v2/modules/moduledeps"
    11  	"github.com/prebid/prebid-server/v2/util/jsonutil"
    12  )
    13  
    14  //go:generate go run ./generator/buildergen.go
    15  
    16  // NewBuilder returns a new module builder.
    17  func NewBuilder() Builder {
    18  	return &builder{builders()}
    19  }
    20  
    21  // Builder is the interfaces intended for building modules
    22  // implementing hook interfaces [github.com/prebid/prebid-server/hooks/hookstage].
    23  type Builder interface {
    24  	// Build initializes existing hook modules passing them config and other dependencies.
    25  	// It returns hook repository created based on the implemented hook interfaces by modules
    26  	// and a map of modules to a list of stage names for which module provides hooks
    27  	// or an error encountered during module initialization.
    28  	Build(cfg config.Modules, client moduledeps.ModuleDeps) (hooks.HookRepository, map[string][]string, error)
    29  }
    30  
    31  type (
    32  	// ModuleBuilders mapping between module name and its builder: map[vendor]map[module]ModuleBuilderFn
    33  	ModuleBuilders map[string]map[string]ModuleBuilderFn
    34  	// ModuleBuilderFn returns an interface{} type that implements certain hook interfaces.
    35  	ModuleBuilderFn func(cfg json.RawMessage, deps moduledeps.ModuleDeps) (interface{}, error)
    36  )
    37  
    38  type builder struct {
    39  	builders ModuleBuilders
    40  }
    41  
    42  // Build walks over the list of registered modules and initializes them.
    43  //
    44  // The ID chosen for the module's hooks represents a fully qualified module path in the format
    45  // "vendor.module_name" and should be used to retrieve module hooks from the hooks.HookRepository.
    46  //
    47  // Method returns a hooks.HookRepository and a map of modules to a list of stage names
    48  // for which module provides hooks or an error occurred during modules initialization.
    49  func (m *builder) Build(
    50  	cfg config.Modules,
    51  	deps moduledeps.ModuleDeps,
    52  ) (hooks.HookRepository, map[string][]string, error) {
    53  	modules := make(map[string]interface{})
    54  	for vendor, moduleBuilders := range m.builders {
    55  		for moduleName, builder := range moduleBuilders {
    56  			var err error
    57  			var conf json.RawMessage
    58  			var isEnabled bool
    59  
    60  			id := fmt.Sprintf("%s.%s", vendor, moduleName)
    61  			if data, ok := cfg[vendor][moduleName]; ok {
    62  				if conf, err = jsonutil.Marshal(data); err != nil {
    63  					return nil, nil, fmt.Errorf(`failed to marshal "%s" module config: %s`, id, err)
    64  				}
    65  
    66  				if values, ok := data.(map[string]interface{}); ok {
    67  					if value, ok := values["enabled"].(bool); ok {
    68  						isEnabled = value
    69  					}
    70  				}
    71  			}
    72  
    73  			if !isEnabled {
    74  				glog.Infof("Skip %s module, disabled.", id)
    75  				continue
    76  			}
    77  
    78  			module, err := builder(conf, deps)
    79  			if err != nil {
    80  				return nil, nil, fmt.Errorf(`failed to init "%s" module: %s`, id, err)
    81  			}
    82  
    83  			modules[id] = module
    84  		}
    85  	}
    86  
    87  	collection, err := createModuleStageNamesCollection(modules)
    88  	if err != nil {
    89  		return nil, nil, err
    90  	}
    91  
    92  	repo, err := hooks.NewHookRepository(modules)
    93  
    94  	return repo, collection, err
    95  }