Skip to content

Commit 7df560b

Browse files
author
softcoder594
committed
optable-targeting: Update caching key generation
1 parent eff725f commit 7df560b

10 files changed

Lines changed: 170 additions & 28 deletions

File tree

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.prebid.server.hooks.modules.optable.targeting.model;
2+
3+
import lombok.AllArgsConstructor;
4+
import org.apache.commons.collections4.CollectionUtils;
5+
6+
import java.net.URLEncoder;
7+
import java.nio.charset.StandardCharsets;
8+
import java.util.List;
9+
10+
@AllArgsConstructor(staticName = "of")
11+
public class CachingKey {
12+
13+
String tenant;
14+
15+
String origin;
16+
17+
Query query;
18+
19+
List<String> ips;
20+
21+
public String toString() {
22+
return "%s:%s:%s:%s".formatted(
23+
tenant,
24+
origin,
25+
CollectionUtils.isNotEmpty(ips) ? ips.getFirst() : "none",
26+
query.getIds());
27+
}
28+
29+
public String toEncodedString() {
30+
return "%s:%s:%s:%s".formatted(
31+
tenant,
32+
origin,
33+
CollectionUtils.isNotEmpty(ips) ? ips.getFirst() : "none",
34+
URLEncoder.encode(query.getIds(), StandardCharsets.UTF_8));
35+
}
36+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.prebid.server.hooks.modules.optable.targeting.model;
2+
3+
import lombok.Value;
4+
5+
@Value(staticConstructor = "of")
6+
public class Query {
7+
8+
String ids;
9+
10+
String attributes;
11+
12+
public String toQueryString() {
13+
return ids + attributes;
14+
}
15+
}

extra/modules/optable-targeting/src/main/java/org/prebid/server/hooks/modules/optable/targeting/v1/core/Cache.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ public Future<TargetingResult> get(String query) {
3434
}
3535

3636
public Future<Void> put(String query, TargetingResult value, int ttlSeconds) {
37-
if (value == null) return Future.succeededFuture();
37+
if (value == null) {
38+
return Future.succeededFuture();
39+
}
3840

3941
return cacheService.storeEntry(
4042
query,

extra/modules/optable-targeting/src/main/java/org/prebid/server/hooks/modules/optable/targeting/v1/core/OptableTargeting.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
import com.iab.openrtb.request.BidRequest;
44
import io.vertx.core.Future;
5+
import org.prebid.server.hooks.modules.optable.targeting.model.CachingKey;
56
import org.prebid.server.hooks.modules.optable.targeting.model.OptableAttributes;
7+
import org.prebid.server.hooks.modules.optable.targeting.model.Query;
68
import org.prebid.server.hooks.modules.optable.targeting.model.config.CacheProperties;
79
import org.prebid.server.hooks.modules.optable.targeting.model.config.OptableTargetingProperties;
810
import org.prebid.server.hooks.modules.optable.targeting.model.openrtb.TargetingResult;
911
import org.prebid.server.hooks.modules.optable.targeting.v1.net.APIClient;
1012

11-
import java.net.URLEncoder;
12-
import java.nio.charset.StandardCharsets;
1313
import java.util.List;
1414
import java.util.Objects;
1515
import java.util.Optional;
@@ -59,23 +59,24 @@ public Future<TargetingResult> getTargeting(OptableTargetingProperties propertie
5959

6060
private Future<TargetingResult> getOrFetchTargetingResults(CacheProperties cacheProperties, String apiKey,
6161
String tenant, String origin,
62-
String query, List<String> ips, long timeout) {
62+
Query query, List<String> ips, long timeout) {
6363

64-
final String key = tenant + ":" +URLEncoder.encode(query, StandardCharsets.UTF_8);
64+
final CachingKey cachingKey = CachingKey.of(tenant, origin, query, ips);
6565

66-
return cache.get(key)
66+
return cache.get(cachingKey.toEncodedString())
6767
.recover(err -> Future.succeededFuture(null))
6868
.compose(entry -> entry != null
6969
? Future.succeededFuture(entry)
70-
: fetchAndCacheResult(tenant, origin, cacheProperties.getTtlseconds(), apiKey,
70+
: fetchAndCacheResult(cachingKey, tenant, origin, cacheProperties.getTtlseconds(), apiKey,
7171
query, ips, timeout));
7272

7373
}
7474

75-
private Future<TargetingResult> fetchAndCacheResult(String tenant, String origin, int ttlSeconds, String apiKey,
76-
String query, List<String> ips, long timeout) {
75+
private Future<TargetingResult> fetchAndCacheResult(CachingKey cachingKey, String tenant, String origin,
76+
int ttlSeconds, String apiKey, Query query, List<String> ips,
77+
long timeout) {
7778

7879
return apiClient.getTargeting(apiKey, tenant, origin, query, ips, timeout)
79-
.compose(result -> cache.put(tenant + ":" + query, result, ttlSeconds).map(result));
80+
.compose(result -> cache.put(cachingKey.toString(), result, ttlSeconds).map(result));
8081
}
8182
}

extra/modules/optable-targeting/src/main/java/org/prebid/server/hooks/modules/optable/targeting/v1/core/QueryBuilder.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.apache.commons.lang3.StringUtils;
55
import org.prebid.server.hooks.modules.optable.targeting.model.Id;
66
import org.prebid.server.hooks.modules.optable.targeting.model.OptableAttributes;
7+
import org.prebid.server.hooks.modules.optable.targeting.model.Query;
78

89
import java.net.URLEncoder;
910
import java.nio.charset.StandardCharsets;
@@ -15,17 +16,20 @@
1516

1617
public class QueryBuilder {
1718

18-
public String build(List<Id> ids, OptableAttributes optableAttributes, String idPrefixOrder) {
19+
public Query build(List<Id> ids, OptableAttributes optableAttributes, String idPrefixOrder) {
1920
if (CollectionUtils.isEmpty(ids)) {
2021
return null;
2122
}
2223

24+
return Query.of(buildIdsString(ids, idPrefixOrder), buildAttributesString(optableAttributes));
25+
}
26+
27+
private String buildIdsString(List<Id> ids, String idPrefixOrder) {
2328
final StringBuilder sb = new StringBuilder();
2429
final List<Id> reorderedIds = reorderIds(ids, idPrefixOrder);
2530
if (CollectionUtils.isNotEmpty(reorderedIds)) {
2631
buildQueryString(sb, reorderedIds);
2732
}
28-
addAttributes(sb, optableAttributes);
2933

3034
return sb.toString();
3135
}
@@ -51,7 +55,8 @@ private int checkOrder(Id item, List<String> order, int lastIndex) {
5155
return value;
5256
}
5357

54-
private void addAttributes(StringBuilder sb, OptableAttributes optableAttributes) {
58+
private String buildAttributesString(OptableAttributes optableAttributes) {
59+
final StringBuilder sb = new StringBuilder();
5560
Optional.ofNullable(optableAttributes.getGdprConsent()).ifPresent(consent ->
5661
sb.append("&gdpr_consent=").append(consent));
5762
Optional.of(optableAttributes.isGdprApplies()).ifPresent(applies ->
@@ -65,6 +70,8 @@ private void addAttributes(StringBuilder sb, OptableAttributes optableAttributes
6570
});
6671
Optional.ofNullable(optableAttributes.getTimeout()).ifPresent(timeout ->
6772
sb.append("&timeout=").append(timeout).append("ms"));
73+
74+
return sb.toString();
6875
}
6976

7077
private void buildQueryString(StringBuilder sb, List<Id> ids) {

extra/modules/optable-targeting/src/main/java/org/prebid/server/hooks/modules/optable/targeting/v1/net/APIClient.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import io.vertx.core.http.impl.headers.HeadersMultiMap;
99
import org.apache.commons.collections4.CollectionUtils;
1010
import org.apache.commons.lang3.StringUtils;
11+
import org.prebid.server.hooks.modules.optable.targeting.model.Query;
1112
import org.prebid.server.hooks.modules.optable.targeting.model.net.HttpRequest;
1213
import org.prebid.server.hooks.modules.optable.targeting.model.net.HttpResponse;
1314
import org.prebid.server.hooks.modules.optable.targeting.model.net.OptableCall;
@@ -52,7 +53,7 @@ public APIClient(String endpoint,
5253
}
5354

5455
public Future<TargetingResult> getTargeting(String apiKey, String tenant, String origin,
55-
String query, List<String> ips, long timeout) {
56+
Query query, List<String> ips, long timeout) {
5657

5758
final MultiMap headers = HeadersMultiMap.headers()
5859
.add(HttpUtil.ACCEPT_HEADER, "application/json");
@@ -69,7 +70,7 @@ public Future<TargetingResult> getTargeting(String apiKey, String tenant, String
6970

7071
final HttpRequest request = HttpRequest.builder()
7172
.uri(EndpointResolver.resolve(endpoint, tenant, origin))
72-
.query(query)
73+
.query(query.toQueryString())
7374
.headers(headers)
7475
.build();
7576

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.prebid.server.hooks.modules.optable.targeting.model;
2+
3+
import org.assertj.core.api.Assertions;
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.util.List;
7+
8+
public class CachingKeyTest {
9+
10+
@Test
11+
public void shouldBuildCachingUrlEncodedKey() {
12+
// given
13+
final Query query = Query.of("query?String", "&attributes");
14+
final CachingKey cachingKey = CachingKey.of("tenant", "origin", query, List.of("8.8.8.8"));
15+
16+
// when
17+
final String key = cachingKey.toEncodedString();
18+
19+
// then
20+
Assertions.assertThat(key).isEqualTo("tenant:origin:8.8.8.8:query%3FString");
21+
}
22+
23+
@Test
24+
public void shouldBuildCachingKey() {
25+
// given
26+
final Query query = Query.of("query?String", "&attributes");
27+
final CachingKey cachingKey = CachingKey.of("tenant", "origin", query, List.of("8.8.8.8"));
28+
29+
// when
30+
final String key = cachingKey.toString();
31+
32+
// then
33+
Assertions.assertThat(key).isEqualTo("tenant:origin:8.8.8.8:query?String");
34+
}
35+
36+
@Test
37+
public void shouldPutNoneIfNoIpAddress() {
38+
// given
39+
final Query query = Query.of("query?String", "&attributes");
40+
final CachingKey cachingKey = CachingKey.of("tenant", "origin", query, null);
41+
42+
// when
43+
final String key = cachingKey.toString();
44+
45+
// then
46+
Assertions.assertThat(key).isEqualTo("tenant:origin:none:query?String");
47+
}
48+
}

extra/modules/optable-targeting/src/test/java/org/prebid/server/hooks/modules/optable/targeting/v1/BaseOptableTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.prebid.server.hooks.modules.optable.targeting.model.EnrichmentStatus;
2323
import org.prebid.server.hooks.modules.optable.targeting.model.Metrics;
2424
import org.prebid.server.hooks.modules.optable.targeting.model.ModuleContext;
25+
import org.prebid.server.hooks.modules.optable.targeting.model.Query;
2526
import org.prebid.server.hooks.modules.optable.targeting.model.config.CacheProperties;
2627
import org.prebid.server.hooks.modules.optable.targeting.model.config.OptableTargetingProperties;
2728
import org.prebid.server.hooks.modules.optable.targeting.model.openrtb.Audience;
@@ -183,4 +184,8 @@ protected OptableTargetingProperties givenOptableTargetingProperties(boolean ena
183184
new CacheProperties(enableCache, 86400)
184185
);
185186
}
187+
188+
protected Query givenQuery() {
189+
return Query.of("que", "ry");
190+
}
186191
}

extra/modules/optable-targeting/src/test/java/org/prebid/server/hooks/modules/optable/targeting/v1/core/QueryBuilderTest.java

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.junit.jupiter.api.Test;
55
import org.prebid.server.hooks.modules.optable.targeting.model.Id;
66
import org.prebid.server.hooks.modules.optable.targeting.model.OptableAttributes;
7+
import org.prebid.server.hooks.modules.optable.targeting.model.Query;
78

89
import java.util.List;
910

@@ -24,13 +25,39 @@ public void setUp() {
2425
idPrefixOrder = "c,c1";
2526
}
2627

28+
@Test
29+
public void shouldSeparateAttributesFromIds() {
30+
// given
31+
final List<Id> ids = List.of(Id.of(Id.EMAIL, "email"), Id.of(Id.PHONE, "123"));
32+
33+
// when
34+
final Query query = target.build(ids, optableAttributes, idPrefixOrder);
35+
36+
// then
37+
assertThat(query.getIds()).isEqualTo("e%3Aemail&id=p%3A123");
38+
assertThat(query.getAttributes()).isEqualTo("&gdpr_consent=tcf&gdpr=1&timeout=100ms");
39+
}
40+
41+
@Test
42+
public void shouldBuildFullQueryString() {
43+
// given
44+
final List<Id> ids = List.of(Id.of(Id.EMAIL, "email"), Id.of(Id.PHONE, "123"));
45+
46+
// when
47+
final Query query = target.build(ids, optableAttributes, idPrefixOrder);
48+
49+
// then
50+
assertThat(query.getIds()).isEqualTo("e%3Aemail&id=p%3A123");
51+
assertThat(query.getAttributes()).isEqualTo("&gdpr_consent=tcf&gdpr=1&timeout=100ms");
52+
}
53+
2754
@Test
2855
public void shouldBuildQueryStringWhenHaveIds() {
2956
// given
3057
final List<Id> ids = List.of(Id.of(Id.EMAIL, "email"), Id.of(Id.PHONE, "123"));
3158

3259
// when
33-
final String query = target.build(ids, optableAttributes, idPrefixOrder);
60+
final String query = target.build(ids, optableAttributes, idPrefixOrder).toQueryString();
3461

3562
// then
3663
assertThat(query).contains("e%3Aemail", "p%3A123");
@@ -42,7 +69,7 @@ public void shouldBuildQueryStringWithExtraAttributes() {
4269
final List<Id> ids = List.of(Id.of(Id.EMAIL, "email"), Id.of(Id.PHONE, "123"));
4370

4471
// when
45-
final String query = target.build(ids, optableAttributes, idPrefixOrder);
72+
final String query = target.build(ids, optableAttributes, idPrefixOrder).toQueryString();
4673

4774
// then
4875
assertThat(query).contains("&gdpr=1", "&gdpr_consent=tcf", "&timeout=100ms");
@@ -55,7 +82,7 @@ public void shouldBuildQueryStringWithRightOrder() {
5582
Id.of("c", "234"));
5683

5784
// when
58-
final String query = target.build(ids, optableAttributes, idPrefixOrder);
85+
final String query = target.build(ids, optableAttributes, idPrefixOrder).toQueryString();
5986

6087
// then
6188
assertThat(query).startsWith("c%3A234&id=c1%3A123&id=id5%3AID5&id=e%3Aemail");
@@ -67,7 +94,7 @@ public void shouldNotBuildQueryStringWhenIdsListIsEmpty() {
6794
final List<Id> ids = List.of();
6895

6996
// when
70-
final String query = target.build(ids, optableAttributes, idPrefixOrder);
97+
final String query = target.build(ids, optableAttributes, idPrefixOrder).toQueryString();
7198

7299
// then
73100

0 commit comments

Comments
 (0)