Skip to content

Commit 591e2f6

Browse files
Core: Refactor Default Account Resolving (prebid#3012)
1 parent 79487fa commit 591e2f6

21 files changed

Lines changed: 550 additions & 983 deletions

src/main/java/org/prebid/server/activity/utils/AccountActivitiesConfigurationUtils.java renamed to src/main/java/org/prebid/server/activity/ActivitiesConfigResolver.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package org.prebid.server.activity.utils;
1+
package org.prebid.server.activity;
22

3-
import org.prebid.server.activity.Activity;
3+
import io.vertx.core.logging.LoggerFactory;
4+
import org.prebid.server.log.ConditionalLogger;
45
import org.prebid.server.settings.model.Account;
56
import org.prebid.server.settings.model.AccountPrivacyConfig;
67
import org.prebid.server.settings.model.activity.AccountActivityConfiguration;
@@ -14,27 +15,51 @@
1415
import java.util.Optional;
1516
import java.util.stream.Collectors;
1617

17-
public class AccountActivitiesConfigurationUtils {
18+
public class ActivitiesConfigResolver {
1819

19-
private AccountActivitiesConfigurationUtils() {
20+
private static final ConditionalLogger conditionalLogger =
21+
new ConditionalLogger(LoggerFactory.getLogger(ActivitiesConfigResolver.class));
22+
23+
private final double logSamplingRate;
24+
25+
public ActivitiesConfigResolver(double logSamplingRate) {
26+
this.logSamplingRate = logSamplingRate;
27+
}
28+
29+
public Account resolve(Account account) {
30+
if (!isInvalidActivitiesConfiguration(account)) {
31+
return account;
32+
}
33+
34+
conditionalLogger.warn(
35+
"Activity configuration for account %s contains conditional rule with empty array."
36+
.formatted(account.getId()),
37+
logSamplingRate);
38+
39+
final AccountPrivacyConfig accountPrivacyConfig = account.getPrivacy();
40+
return account.toBuilder()
41+
.privacy(accountPrivacyConfig.toBuilder()
42+
.activities(removeInvalidRules(accountPrivacyConfig.getActivities()))
43+
.build())
44+
.build();
2045
}
2146

22-
public static boolean isInvalidActivitiesConfiguration(Account account) {
47+
private static boolean isInvalidActivitiesConfiguration(Account account) {
2348
return Optional.ofNullable(account)
2449
.map(Account::getPrivacy)
2550
.map(AccountPrivacyConfig::getActivities)
2651
.stream()
2752
.map(Map::values)
2853
.flatMap(Collection::stream)
29-
.anyMatch(AccountActivitiesConfigurationUtils::containsInvalidRule);
54+
.anyMatch(ActivitiesConfigResolver::containsInvalidRule);
3055
}
3156

3257
private static boolean containsInvalidRule(AccountActivityConfiguration accountActivityConfiguration) {
3358
return Optional.ofNullable(accountActivityConfiguration)
3459
.map(AccountActivityConfiguration::getRules)
3560
.stream()
3661
.flatMap(Collection::stream)
37-
.anyMatch(AccountActivitiesConfigurationUtils::isInvalidConditionRule);
62+
.anyMatch(ActivitiesConfigResolver::isInvalidConditionRule);
3863
}
3964

4065
private static boolean isInvalidConditionRule(AccountActivityRuleConfig rule) {
@@ -63,13 +88,13 @@ private static <E> boolean isEmptyNotNull(Collection<E> collection) {
6388
return collection != null && collection.isEmpty();
6489
}
6590

66-
public static Map<Activity, AccountActivityConfiguration> removeInvalidRules(
91+
private static Map<Activity, AccountActivityConfiguration> removeInvalidRules(
6792
Map<Activity, AccountActivityConfiguration> activitiesConfiguration) {
6893

6994
return activitiesConfiguration.entrySet().stream()
7095
.collect(Collectors.toMap(
7196
Map.Entry::getKey,
72-
entry -> AccountActivitiesConfigurationUtils.removeInvalidRules(entry.getValue())));
97+
entry -> removeInvalidRules(entry.getValue())));
7398
}
7499

75100
private static AccountActivityConfiguration removeInvalidRules(AccountActivityConfiguration activityConfiguration) {

src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java

Lines changed: 28 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ public class Ortb2RequestFactory {
9191
private static final ConditionalLogger EMPTY_ACCOUNT_LOGGER = new ConditionalLogger("empty_account", logger);
9292
private static final ConditionalLogger UNKNOWN_ACCOUNT_LOGGER = new ConditionalLogger("unknown_account", logger);
9393

94-
private final boolean enforceValidAccount;
9594
private final int timeoutAdjustmentFactor;
9695
private final double logSamplingRate;
9796
private final List<String> blacklistedAccounts;
@@ -110,8 +109,7 @@ public class Ortb2RequestFactory {
110109
private final Metrics metrics;
111110
private final Clock clock;
112111

113-
public Ortb2RequestFactory(boolean enforceValidAccount,
114-
int timeoutAdjustmentFactor,
112+
public Ortb2RequestFactory(int timeoutAdjustmentFactor,
115113
double logSamplingRate,
116114
List<String> blacklistedAccounts,
117115
UidsCookieService uidsCookieService,
@@ -133,7 +131,6 @@ public Ortb2RequestFactory(boolean enforceValidAccount,
133131
throw new IllegalArgumentException("Expected timeout adjustment factor should be in [0, 100].");
134132
}
135133

136-
this.enforceValidAccount = enforceValidAccount;
137134
this.timeoutAdjustmentFactor = timeoutAdjustmentFactor;
138135
this.logSamplingRate = logSamplingRate;
139136
this.blacklistedAccounts = Objects.requireNonNull(blacklistedAccounts);
@@ -457,20 +454,26 @@ private String validateIfAccountBlacklisted(String accountId) {
457454
return accountId;
458455
}
459456

460-
private Future<Account> loadAccount(Timeout timeout,
461-
HttpRequestContext httpRequest,
462-
String accountId) {
463-
464-
final Future<Account> accountFuture = StringUtils.isBlank(accountId)
465-
? responseForEmptyAccount(httpRequest)
466-
: applicationSettings.getAccountById(accountId, timeout)
467-
.compose(this::ensureAccountActive,
468-
exception -> accountFallback(exception, accountId, httpRequest));
457+
private Future<Account> loadAccount(Timeout timeout, HttpRequestContext httpRequest, String accountId) {
458+
if (StringUtils.isBlank(accountId)) {
459+
EMPTY_ACCOUNT_LOGGER.warn(accountErrorMessage("Account not specified", httpRequest), logSamplingRate);
460+
}
469461

470-
return accountFuture
462+
return applicationSettings.getAccountById(accountId, timeout)
463+
.compose(this::ensureAccountActive)
464+
.recover(exception -> wrapFailure(exception, accountId, httpRequest))
471465
.onFailure(ignored -> metrics.updateAccountRequestRejectedByInvalidAccountMetrics(accountId));
472466
}
473467

468+
private Future<Account> ensureAccountActive(Account account) {
469+
final String accountId = account.getId();
470+
471+
return account.getStatus() == AccountStatus.inactive
472+
? Future.failedFuture(
473+
new UnauthorizedAccountException("Account %s is inactive".formatted(accountId), accountId))
474+
: Future.succeededFuture(account);
475+
}
476+
474477
/**
475478
* Extracts publisher id either from {@link BidRequest}.app.publisher or {@link BidRequest}.site.publisher.
476479
* If neither is present returns empty string.
@@ -505,48 +508,26 @@ private String parentAccountIdFromExtPublisher(ExtPublisher extPublisher) {
505508
return extPublisherPrebid != null ? StringUtils.stripToNull(extPublisherPrebid.getParentAccount()) : null;
506509
}
507510

508-
private Future<Account> responseForEmptyAccount(HttpRequestContext httpRequest) {
509-
EMPTY_ACCOUNT_LOGGER.warn(accountErrorMessage("Account not specified", httpRequest), logSamplingRate);
510-
return responseForUnknownAccount(StringUtils.EMPTY);
511-
}
512-
513-
private static String accountErrorMessage(String message, HttpRequestContext httpRequest) {
514-
return "%s, Url: %s and Referer: %s".formatted(
515-
message,
516-
httpRequest.getAbsoluteUri(),
517-
httpRequest.getHeaders().get(HttpUtil.REFERER_HEADER));
518-
}
519-
520-
private Future<Account> accountFallback(Throwable exception,
521-
String accountId,
522-
HttpRequestContext httpRequest) {
523-
524-
if (exception instanceof PreBidException) {
511+
private Future<Account> wrapFailure(Throwable exception, String accountId, HttpRequestContext httpRequest) {
512+
if (exception instanceof UnauthorizedAccountException) {
513+
return Future.failedFuture(exception);
514+
} else if (exception instanceof PreBidException) {
525515
UNKNOWN_ACCOUNT_LOGGER.warn(accountErrorMessage(exception.getMessage(), httpRequest), 100);
526516
} else {
527517
metrics.updateAccountRequestRejectedByFailedFetch(accountId);
528518
logger.warn("Error occurred while fetching account: {0}", exception.getMessage());
529519
logger.debug("Error occurred while fetching account", exception);
530520
}
531521

532-
// hide all errors occurred while fetching account
533-
return responseForUnknownAccount(accountId);
534-
}
535-
536-
private Future<Account> responseForUnknownAccount(String accountId) {
537-
return enforceValidAccount
538-
? Future.failedFuture(new UnauthorizedAccountException(
539-
"Unauthorized account id: " + accountId, accountId))
540-
: Future.succeededFuture(Account.empty(accountId));
522+
return Future.failedFuture(
523+
new UnauthorizedAccountException("Unauthorized account id: " + accountId, accountId));
541524
}
542525

543-
private Future<Account> ensureAccountActive(Account account) {
544-
final String accountId = account.getId();
545-
546-
return account.getStatus() == AccountStatus.inactive
547-
? Future.failedFuture(new UnauthorizedAccountException(
548-
"Account %s is inactive".formatted(accountId), accountId))
549-
: Future.succeededFuture(account);
526+
private static String accountErrorMessage(String message, HttpRequestContext httpRequest) {
527+
return "%s, Url: %s and Referer: %s".formatted(
528+
message,
529+
httpRequest.getAbsoluteUri(),
530+
httpRequest.getHeaders().get(HttpUtil.REFERER_HEADER));
550531
}
551532

552533
private ExtRequest enrichExtRequest(ExtRequest ext, Account account) {

src/main/java/org/prebid/server/cookie/CookieDeprecationService.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import org.prebid.server.settings.model.AccountPrivacySandboxCookieDeprecationConfig;
1818
import org.prebid.server.util.HttpUtil;
1919

20-
import java.util.Objects;
2120
import java.util.Optional;
2221

2322
public class CookieDeprecationService {
@@ -26,20 +25,12 @@ public class CookieDeprecationService {
2625
private static final String DEVICE_EXT_COOKIE_DEPRECATION_FIELD_NAME = "cdep";
2726
private static final long DEFAULT_MAX_AGE = 604800L;
2827

29-
private final Account defaultAccount;
30-
31-
public CookieDeprecationService(Account defaultAccount) {
32-
this.defaultAccount = Objects.requireNonNull(defaultAccount);
33-
}
34-
3528
public PartitionedCookie makeCookie(Account account, RoutingContext routingContext) {
36-
final Account resolvedAccount = account.isEmpty() ? defaultAccount : account;
37-
38-
if (hasDeprecationCookieInRequest(routingContext) || isCookieDeprecationDisabled(resolvedAccount)) {
29+
if (hasDeprecationCookieInRequest(routingContext) || isCookieDeprecationDisabled(account)) {
3930
return null;
4031
}
4132

42-
final Long maxAge = getCookieDeprecationConfig(resolvedAccount)
33+
final Long maxAge = getCookieDeprecationConfig(account)
4334
.map(AccountPrivacySandboxCookieDeprecationConfig::getTtlSec)
4435
.orElse(DEFAULT_MAX_AGE);
4536

@@ -61,13 +52,9 @@ public BidRequest updateBidRequestDevice(BidRequest bidRequest, AuctionContext a
6152
.get(HttpUtil.SEC_COOKIE_DEPRECATION);
6253

6354
final Account account = auctionContext.getAccount();
64-
final Account resolvedAccount = account.isEmpty() ? defaultAccount : account;
6555
final Device device = bidRequest.getDevice();
6656

67-
if (secCookieDeprecation == null
68-
|| containsCookieDeprecation(device)
69-
|| isCookieDeprecationDisabled(resolvedAccount)) {
70-
57+
if (secCookieDeprecation == null || containsCookieDeprecation(device) || isCookieDeprecationDisabled(account)) {
7158
return bidRequest;
7259
}
7360

src/main/java/org/prebid/server/floors/PriceFloorFetcher.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,8 @@ private void periodicFetch(String accountId) {
310310
}
311311

312312
private Future<Account> accountById(String accountId) {
313-
return StringUtils.isBlank(accountId)
314-
? Future.succeededFuture()
315-
: applicationSettings
316-
.getAccountById(accountId, timeoutFactory.create(ACCOUNT_FETCH_TIMEOUT_MS))
317-
.recover(ignored -> Future.succeededFuture());
313+
return applicationSettings.getAccountById(accountId, timeoutFactory.create(ACCOUNT_FETCH_TIMEOUT_MS))
314+
.otherwiseEmpty();
318315
}
319316

320317
@Value(staticConstructor = "of")

0 commit comments

Comments
 (0)