@@ -150,19 +150,20 @@ func (s *Service) GetCustomerByUsageAttribution(ctx context.Context, input custo
150150 return nil , err
151151 }
152152
153- c , ok := resolved [input .Key ]
154- if ! ok {
153+ c := resolved [input .Key ]
154+ if c == nil {
155155 return nil , models .NewGenericNotFoundError (
156156 fmt .Errorf ("customer with subject key %s not found in %s namespace" , input .Key , input .Namespace ),
157157 )
158158 }
159159
160- return & c , nil
160+ return c , nil
161161}
162162
163163// GetCustomersByUsageAttribution resolves multiple customers by usage attribution keys in a single
164164// query, mapping each input key to the customer it matches with key-over-subject precedence applied.
165- func (s * Service ) GetCustomersByUsageAttribution (ctx context.Context , input customer.GetCustomersByUsageAttributionInput ) (map [string ]customer.Customer , error ) {
165+ // Every input key is present in the returned map; keys that match no customer map to a nil value.
166+ func (s * Service ) GetCustomersByUsageAttribution (ctx context.Context , input customer.GetCustomersByUsageAttributionInput ) (map [string ]* customer.Customer , error ) {
166167 if err := input .Validate (); err != nil {
167168 return nil , models .NewGenericValidationError (
168169 fmt .Errorf ("error getting customers by usage attribution: %w" , err ),
@@ -175,7 +176,7 @@ func (s *Service) GetCustomersByUsageAttribution(ctx context.Context, input cust
175176// resolveCustomersByUsageAttribution runs the shared usage-attribution lookup: fetch the raw
176177// candidate customers from the adapter, then apply key-over-subject precedence. Both the single-key
177178// and bulk service methods route through this so their core resolution stays identical.
178- func (s * Service ) resolveCustomersByUsageAttribution (ctx context.Context , input customer.GetCustomersByUsageAttributionInput ) (map [string ]customer.Customer , error ) {
179+ func (s * Service ) resolveCustomersByUsageAttribution (ctx context.Context , input customer.GetCustomersByUsageAttributionInput ) (map [string ]* customer.Customer , error ) {
179180 customers , err := s .adapter .GetCustomersByUsageAttribution (ctx , input )
180181 if err != nil {
181182 return nil , err
@@ -188,13 +189,15 @@ func (s *Service) resolveCustomersByUsageAttribution(ctx context.Context, input
188189// either by the customer's own key or by one of its subject keys; when a key matches both a
189190// distinct key-owner and a distinct subject-owner, the key-owner takes precedence. Key-over-subject
190191// collisions are structurally rare and resolved deterministically here, so they are not surfaced as
191- // errors or logs; investigate the underlying data via the database if ever needed. Keys with no
192- // match are absent from the returned map.
193- func resolveCustomersByKeyWithPrecedence (customers []customer.Customer , keys []string ) map [string ]customer.Customer {
194- byKey := make (map [string ]customer.Customer , len (customers ))
195- bySubject := make (map [string ]customer.Customer , len (customers ))
192+ // errors or logs; investigate the underlying data via the database if ever needed. Every input key
193+ // is present in the returned map; keys that match no customer have a nil value.
194+ func resolveCustomersByKeyWithPrecedence (customers []customer.Customer , keys []string ) map [string ]* customer.Customer {
195+ byKey := make (map [string ]* customer.Customer , len (customers ))
196+ bySubject := make (map [string ]* customer.Customer , len (customers ))
197+
198+ for i := range customers {
199+ c := & customers [i ]
196200
197- for _ , c := range customers {
198201 if c .Key != nil {
199202 byKey [* c .Key ] = c
200203 }
@@ -208,7 +211,7 @@ func resolveCustomersByKeyWithPrecedence(customers []customer.Customer, keys []s
208211 }
209212 }
210213
211- resolved := make (map [string ]customer.Customer , len (keys ))
214+ resolved := make (map [string ]* customer.Customer , len (keys ))
212215
213216 for _ , k := range keys {
214217 if keyOwner , ok := byKey [k ]; ok {
@@ -218,7 +221,10 @@ func resolveCustomersByKeyWithPrecedence(customers []customer.Customer, keys []s
218221
219222 if subjectOwner , ok := bySubject [k ]; ok {
220223 resolved [k ] = subjectOwner
224+ continue
221225 }
226+
227+ resolved [k ] = nil // present, but no matching customer
222228 }
223229
224230 return resolved
0 commit comments