github.com/prebid/prebid-server/v2@v2.18.0/hooks/repo.go (about) 1 package hooks 2 3 import ( 4 "fmt" 5 6 "github.com/prebid/prebid-server/v2/hooks/hookstage" 7 ) 8 9 // HookRepository is the interface that exposes methods 10 // that return instance of the certain hook interface. 11 // 12 // Each method accepts hook ID and returns hook interface 13 // registered under this ID and true if hook found 14 // otherwise nil value returned with the false, 15 // indicating not found hook for this ID. 16 type HookRepository interface { 17 GetEntrypointHook(id string) (hookstage.Entrypoint, bool) 18 GetRawAuctionHook(id string) (hookstage.RawAuctionRequest, bool) 19 GetProcessedAuctionHook(id string) (hookstage.ProcessedAuctionRequest, bool) 20 GetBidderRequestHook(id string) (hookstage.BidderRequest, bool) 21 GetRawBidderResponseHook(id string) (hookstage.RawBidderResponse, bool) 22 GetAllProcessedBidResponsesHook(id string) (hookstage.AllProcessedBidResponses, bool) 23 GetAuctionResponseHook(id string) (hookstage.AuctionResponse, bool) 24 } 25 26 // NewHookRepository returns a new instance of the HookRepository interface. 27 // 28 // The hooks argument represents a mapping of hook IDs to types 29 // implementing at least one of the available hook interfaces, see [hookstage] pkg. 30 // 31 // Error returned if provided interface doesn't implement any hook interface 32 // or hook with same ID already exists. 33 func NewHookRepository(hooks map[string]interface{}) (HookRepository, error) { 34 repo := new(hookRepository) 35 for id, hook := range hooks { 36 if err := repo.add(id, hook); err != nil { 37 return nil, err 38 } 39 } 40 41 return repo, nil 42 } 43 44 type hookRepository struct { 45 entrypointHooks map[string]hookstage.Entrypoint 46 rawAuctionHooks map[string]hookstage.RawAuctionRequest 47 processedAuctionHooks map[string]hookstage.ProcessedAuctionRequest 48 bidderRequestHooks map[string]hookstage.BidderRequest 49 rawBidderResponseHooks map[string]hookstage.RawBidderResponse 50 allProcessedBidResponseHooks map[string]hookstage.AllProcessedBidResponses 51 auctionResponseHooks map[string]hookstage.AuctionResponse 52 } 53 54 func (r *hookRepository) GetEntrypointHook(id string) (hookstage.Entrypoint, bool) { 55 return getHook(r.entrypointHooks, id) 56 } 57 58 func (r *hookRepository) GetRawAuctionHook(id string) (hookstage.RawAuctionRequest, bool) { 59 return getHook(r.rawAuctionHooks, id) 60 } 61 62 func (r *hookRepository) GetProcessedAuctionHook(id string) (hookstage.ProcessedAuctionRequest, bool) { 63 return getHook(r.processedAuctionHooks, id) 64 } 65 66 func (r *hookRepository) GetBidderRequestHook(id string) (hookstage.BidderRequest, bool) { 67 return getHook(r.bidderRequestHooks, id) 68 } 69 70 func (r *hookRepository) GetRawBidderResponseHook(id string) (hookstage.RawBidderResponse, bool) { 71 return getHook(r.rawBidderResponseHooks, id) 72 } 73 74 func (r *hookRepository) GetAllProcessedBidResponsesHook(id string) (hookstage.AllProcessedBidResponses, bool) { 75 return getHook(r.allProcessedBidResponseHooks, id) 76 } 77 78 func (r *hookRepository) GetAuctionResponseHook(id string) (hookstage.AuctionResponse, bool) { 79 return getHook(r.auctionResponseHooks, id) 80 } 81 82 func (r *hookRepository) add(id string, hook interface{}) error { 83 var hasAnyHooks bool 84 var err error 85 86 if h, ok := hook.(hookstage.Entrypoint); ok { 87 hasAnyHooks = true 88 if r.entrypointHooks, err = addHook(r.entrypointHooks, h, id); err != nil { 89 return err 90 } 91 } 92 93 if h, ok := hook.(hookstage.RawAuctionRequest); ok { 94 hasAnyHooks = true 95 if r.rawAuctionHooks, err = addHook(r.rawAuctionHooks, h, id); err != nil { 96 return err 97 } 98 } 99 100 if h, ok := hook.(hookstage.ProcessedAuctionRequest); ok { 101 hasAnyHooks = true 102 if r.processedAuctionHooks, err = addHook(r.processedAuctionHooks, h, id); err != nil { 103 return err 104 } 105 } 106 107 if h, ok := hook.(hookstage.BidderRequest); ok { 108 hasAnyHooks = true 109 if r.bidderRequestHooks, err = addHook(r.bidderRequestHooks, h, id); err != nil { 110 return err 111 } 112 } 113 114 if h, ok := hook.(hookstage.RawBidderResponse); ok { 115 hasAnyHooks = true 116 if r.rawBidderResponseHooks, err = addHook(r.rawBidderResponseHooks, h, id); err != nil { 117 return err 118 } 119 } 120 121 if h, ok := hook.(hookstage.AllProcessedBidResponses); ok { 122 hasAnyHooks = true 123 if r.allProcessedBidResponseHooks, err = addHook(r.allProcessedBidResponseHooks, h, id); err != nil { 124 return err 125 } 126 } 127 128 if h, ok := hook.(hookstage.AuctionResponse); ok { 129 hasAnyHooks = true 130 if r.auctionResponseHooks, err = addHook(r.auctionResponseHooks, h, id); err != nil { 131 return err 132 } 133 } 134 135 if !hasAnyHooks { 136 return fmt.Errorf(`hook "%s" does not implement any supported hook interface`, id) 137 } 138 139 return nil 140 } 141 142 func getHook[T any](hooks map[string]T, id string) (T, bool) { 143 hook, ok := hooks[id] 144 return hook, ok 145 } 146 147 func addHook[T any](hooks map[string]T, hook T, id string) (map[string]T, error) { 148 if hooks == nil { 149 hooks = make(map[string]T) 150 } 151 152 if _, ok := hooks[id]; ok { 153 return nil, fmt.Errorf(`hook of type "%T" with id "%s" already registered`, new(T), id) 154 } 155 156 hooks[id] = hook 157 158 return hooks, nil 159 }