Skip to content

Commit

Permalink
Merge pull request #94 from prebid/use_server_cache
Browse files Browse the repository at this point in the history
Use server cache
  • Loading branch information
anwzhang authored Aug 22, 2018
2 parents 2cdaf68 + d558a24 commit 3f0d566
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ - (void)testAttachTopBidHelperWithNoReadyBid {
[adUnit addSize:CGSizeMake(320, 50)];
[[PBBidManager sharedInstance] registerAdUnits:@[adUnit] withAccountId:self.accountId withHost:PBServerHostAppNexus andPrimaryAdServer:PBPrimaryAdServerMoPub];

[[PBBidManager sharedInstance] attachTopBidHelperForAdUnitId:adUnit.identifier andTimeout:500 completionHandler:^{
[[PBBidManager sharedInstance] attachTopBidHelperForAdUnitId:adUnit.identifier andTimeout:50 completionHandler:^{
NSDictionary *bidKeywords = [[PBBidManager sharedInstance] keywordsForWinningBidForAdUnit:adUnit];
XCTAssertNil(bidKeywords);
[expectation fulfill];
Expand Down
68 changes: 24 additions & 44 deletions sdk/PrebidMobileTests/PrebidMobileCoreTests/PBServerAdapterTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ - (void)stopLoading
@end

@interface PBServerAdapterTests : XCTestCase<PBBidResponseDelegate>
@property void (^completionHandler)(NSArray *bids);
@property void (^completionHandler)(NSArray *bids, NSError *error);
@property (nonatomic, strong) NSArray *adUnits;
@end

Expand All @@ -91,21 +91,22 @@ - (void)tearDown {
#pragma mark - PBServerAdapter Delegate
- (void)didCompleteWithError:(nonnull NSError *)error {
if (self.completionHandler) {
self.completionHandler(nil);
self.completionHandler(nil, error);
}

}

- (void)didReceiveSuccessResponse:(nonnull NSArray<PBBidResponse *> *)bid {
if (self.completionHandler) {
self.completionHandler(bid);
self.completionHandler(bid, nil);
}
}

#pragma mark - Tests
-(void)testOnlySaveBidsWithTargetingKeysFromServer
{
testResponse = @"{\"id\":\"3dc76667-a500-4e01-a43b-368e36d6c7cc\",\"seatbid\":[{\"bid\":[{\"id\":\"3829649260126183529\",\"impid\":\"Banner_300x250\",\"price\":15,\"adm\":\"hello\",\"adid\":\"68501584\",\"adomain\":[\"peugeot.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=68501584\",\"cid\":\"958\",\"crid\":\"68501584\",\"cat\":[\"IAB2-3\"],\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"targeting\":{\"hb_bidder\":\"appnexus\",\"hb_bidder_appnexus\":\"appnexus\",\"hb_creative_loadtype\":\"html\",\"hb_env\":\"mobile-app\",\"hb_env_appnexus\":\"mobile-app\",\"hb_pb\":\"15.00\",\"hb_pb_appnexus\":\"15.00\",\"hb_size\":\"300x250\",\"hb_size_appnexus\":\"300x250\"},\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":3264,\"auction_id\":8160292782530908000,\"bidder_id\":2,\"bid_ad_type\":0}}}},{\"id\":\"1389685956420146597\",\"impid\":\"Banner_300x250\",\"price\":3.21,\"adm\":\"hello\",\"adid\":\"28477710\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=28477710\",\"cid\":\"958\",\"crid\":\"28477710\",\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":1,\"auction_id\":8160292782530908000,\"bidder_id\":2,\"bid_ad_type\":0}}}},{\"id\":\"1106673435110511367\",\"impid\":\"Banner_300x250\",\"price\":0.033505,\"adm\":\"hello\",\"adid\":\"103077040\",\"adomain\":[\"audible.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=103077040\",\"cid\":\"1437\",\"crid\":\"103077040\",\"cat\":[\"IAB22-4\",\"IAB22\"],\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":12,\"auction_id\":8160292782530908000,\"bidder_id\":101,\"bid_ad_type\":0}}}}],\"seat\":\"appnexus\"},{\"bid\":[{\"id\":\"3829649260126183529\",\"impid\":\"Banner_300x250\",\"price\":14,\"adm\":\"hello\",\"adid\":\"68501584\",\"adomain\":[\"peugeot.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=68501584\",\"cid\":\"958\",\"crid\":\"68501584\",\"cat\":[\"IAB2-3\"],\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"targeting\":{\"hb_bidder_rubicon\":\"rubicon\",\"hb_creative_loadtype\":\"html\",\"hb_env_rubicon\":\"mobile-app\",\"hb_pb_rubicon\":\"14.00\",\"hb_size_rubicon\":\"300x250\"},\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":3264,\"auction_id\":8160292782530908000,\"bidder_id\":2,\"bid_ad_type\":0}}}}],\"seat\":\"rubicon\"}],\"ext\":{\"responsetimemillis\":{\"appnexus\":258}}}";
// This test response contains 3 bids, two top ones from each bidder has targeting keys, the lower bid does not
testResponse = @"{\"id\":\"3dc76667-a500-4e01-a43b-368e36d6c7cc\",\"seatbid\":[{\"bid\":[{\"id\":\"3829649260126183529\",\"impid\":\"Banner_300x250\",\"price\":15,\"adm\":\"hello\",\"adid\":\"68501584\",\"adomain\":[\"peugeot.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=68501584\",\"cid\":\"958\",\"crid\":\"68501584\",\"cat\":[\"IAB2-3\"],\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"targeting\":{\"hb_bidder\":\"appnexus\",\"hb_bidder_appnexus\":\"appnexus\",\"hb_cache_id\":\"123\",\"hb_cache_id_appnexus\":\"123\",\"hb_creative_loadtype\":\"html\",\"hb_env\":\"mobile-app\",\"hb_env_appnexus\":\"mobile-app\",\"hb_pb\":\"15.00\",\"hb_pb_appnexus\":\"15.00\",\"hb_size\":\"300x250\",\"hb_size_appnexus\":\"300x250\"},\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":3264,\"auction_id\":8160292782530908000,\"bidder_id\":2,\"bid_ad_type\":0}}}},{\"id\":\"1389685956420146597\",\"impid\":\"Banner_300x250\",\"price\":3.21,\"adm\":\"hello\",\"adid\":\"28477710\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=28477710\",\"cid\":\"958\",\"crid\":\"28477710\",\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":1,\"auction_id\":8160292782530908000,\"bidder_id\":2,\"bid_ad_type\":0}}}},{\"id\":\"1106673435110511367\",\"impid\":\"Banner_300x250\",\"price\":0.033505,\"adm\":\"hello\",\"adid\":\"103077040\",\"adomain\":[\"audible.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=103077040\",\"cid\":\"1437\",\"crid\":\"103077040\",\"cat\":[\"IAB22-4\",\"IAB22\"],\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":12,\"auction_id\":8160292782530908000,\"bidder_id\":101,\"bid_ad_type\":0}}}}],\"seat\":\"appnexus\"},{\"bid\":[{\"id\":\"3829649260126183529\",\"impid\":\"Banner_300x250\",\"price\":14,\"adm\":\"hello\",\"adid\":\"68501584\",\"adomain\":[\"peugeot.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=68501584\",\"cid\":\"958\",\"crid\":\"68501584\",\"cat\":[\"IAB2-3\"],\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"targeting\":{\"hb_bidder_rubicon\":\"rubicon\",\"hb_cache_id_rubicon\":\"456\",\"hb_creative_loadtype\":\"html\",\"hb_env_rubicon\":\"mobile-app\",\"hb_pb_rubicon\":\"14.00\",\"hb_size_rubicon\":\"300x250\"},\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":3264,\"auction_id\":8160292782530908000,\"bidder_id\":2,\"bid_ad_type\":0}}}}],\"seat\":\"rubicon\"}],\"ext\":{\"responsetimemillis\":{\"appnexus\":258}}}";
[NSURLProtocol registerClass:[PBTestProtocol class]];
XCTestExpectation *expectation = [self expectationWithDescription:@"Dummy Expectation"];
PBAdUnit *adUnit1 = [[PBAdUnit alloc] initWithIdentifier:@"ad1" andAdType:PBAdUnitTypeBanner andConfigId:@"test_config_id1"];
Expand All @@ -116,7 +117,11 @@ -(void)testOnlySaveBidsWithTargetingKeysFromServer
PBServerAdapter *serverAdapter = [[PBServerAdapter alloc] initWithAccountId:@"test_account_id" andHost:PBServerHostAppNexus andAdServer:PBPrimaryAdServerDFP];
[serverAdapter requestBidsWithAdUnits:self.adUnits withDelegate:self];
__weak PBServerAdapterTests *weakSelf = self;
weakSelf.completionHandler = ^(NSArray *bids){
weakSelf.completionHandler = ^(NSArray *bids, NSError *error){
if (error) {
XCTFail(@"This should never happen.");
[expectation fulfill];
}
// veryfy that all bids has a cache id
// veryfy that only top bid has hb_cache_id
// verify cache_id is truncated after 20 characters
Expand Down Expand Up @@ -144,9 +149,10 @@ -(void)testOnlySaveBidsWithTargetingKeysFromServer
[self waitForExpectationsWithTimeout:20.0 handler:nil];
}

-(void)testAllBidsAreCached
-(void)testNoCacheIdFromServer
{
testResponse = @"{\"id\":\"3dc76667-a500-4e01-a43b-368e36d6c7cc\",\"seatbid\":[{\"bid\":[{\"id\":\"4009307468250838284\",\"impid\":\"Banner_300x250\",\"price\":0.5,\"adm\":\"<script><\/script>\",\"adid\":\"73501515\",\"adomain\":[\"appnexus.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=73501515\",\"cid\":\"958\",\"crid\":\"73501515\",\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"targeting\":{\"hb_bidder\":\"appnexus\",\"hb_bidder_appnexus\":\"appnexus\",\"hb_creative_loadtype\":\"html\",\"hb_env\":\"mobile-app\",\"hb_env_appnexus\":\"mobile-app\",\"hb_pb\":\"0.50\",\"hb_pb_appnexus\":\"0.50\",\"hb_size\":\"300x250\",\"hb_size_appnexus\":\"300x250\"},\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":1,\"auction_id\":7466795334738195000,\"bidder_id\":2,\"bid_ad_type\":0}}}}],\"seat\":\"appnexus\"},{\"bid\":[{\"id\":\"4009307468250838284\",\"impid\":\"Banner_300x250\",\"price\":0.5,\"adm\":\"<script><\/script>\",\"adid\":\"73501515\",\"adomain\":[\"rubicon.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=73501515\",\"cid\":\"958\",\"crid\":\"73501515\",\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"targeting\":{\"hb_bidder_rubicon\":\"rubicon\",\"hb_creative_loadtype\":\"html\",\"hb_env_rubicon\":\"mobile-app\",\"hb_pb_rubicon\":\"0.50\",\"hb_size_rubicon\":\"300x250\"},\"type\":\"banner\"}}}],\"seat\":\"rubicon\"},{\"bid\":[{\"id\":\"4009307468250838284\",\"impid\":\"Banner_300x250\",\"price\":0.5,\"adm\":\"<script><\/script>\",\"adid\":\"73501515\",\"adomain\":[\"superlongnamethatshouldbecropped.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=73501515\",\"cid\":\"958\",\"crid\":\"73501515\",\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"targeting\":{\"hb_bidder_superlongnamet\":\"superlongnamethatshouldbecropped\",\"hb_creative_loadtype\":\"html\",\"hb_env_superlongnamethat\":\"mobile-app\",\"hb_pb_superlongnamethats\":\"0.50\",\"hb_size_superlongnametha\":\"300x250\"},\"type\":\"banner\"}}}],\"seat\":\"superlongnamethatshouldbecropped\"}],\"ext\":{\"responsetimemillis\":{\"appnexus\":19}}}";
// This test response contains 1 bid, but no cache id is in the response
testResponse = @"{\"id\":\"3dc76667-a500-4e01-a43b-368e36d6c7cc\",\"seatbid\":[{\"bid\":[{\"id\":\"3829649260126183529\",\"impid\":\"Banner_300x250\",\"price\":15,\"adm\":\"hello\",\"adid\":\"68501584\",\"adomain\":[\"peugeot.com\"],\"iurl\":\"https:\/\/nym1-ib.adnxs.com\/cr?id=68501584\",\"cid\":\"958\",\"crid\":\"68501584\",\"cat\":[\"IAB2-3\"],\"w\":300,\"h\":250,\"ext\":{\"prebid\":{\"targeting\":{\"hb_bidder\":\"appnexus\",\"hb_bidder_appnexus\":\"appnexus\",\"hb_creative_loadtype\":\"html\",\"hb_env\":\"mobile-app\",\"hb_env_appnexus\":\"mobile-app\",\"hb_pb\":\"15.00\",\"hb_pb_appnexus\":\"15.00\",\"hb_size\":\"300x250\",\"hb_size_appnexus\":\"300x250\"},\"type\":\"banner\"},\"bidder\":{\"appnexus\":{\"brand_id\":3264,\"auction_id\":8160292782530908000,\"bidder_id\":2,\"bid_ad_type\":0}}}}],\"seat\":\"appnexus\"}],\"ext\":{\"responsetimemillis\":{\"appnexus\":258}}}";
[NSURLProtocol registerClass:[PBTestProtocol class]];
XCTestExpectation *expectation = [self expectationWithDescription:@"Dummy Expectation"];
PBAdUnit *adUnit1 = [[PBAdUnit alloc] initWithIdentifier:@"ad1" andAdType:PBAdUnitTypeBanner andConfigId:@"test_config_id1"];
Expand All @@ -157,47 +163,16 @@ -(void)testAllBidsAreCached
PBServerAdapter *serverAdapter = [[PBServerAdapter alloc] initWithAccountId:@"test_account_id" andHost:PBServerHostAppNexus andAdServer:PBPrimaryAdServerDFP];
[serverAdapter requestBidsWithAdUnits:self.adUnits withDelegate:self];
__weak PBServerAdapterTests *weakSelf = self;
weakSelf.completionHandler = ^(NSArray *bids){
// veryfy that all bids has a cache id
// veryfy that only top bid has hb_cache_id
// verify cache_id is truncated after 20 characters
XCTAssertTrue(bids.count == 3);
BOOL cacheIdHasBeenSeen = NO;
for(PBBidResponse *bid in bids){
BOOL isCacheIdPresent = NO;
BOOL isTopBid = NO;
NSString *cacheKey = @"";
NSLog(@"Bid keywords: %@", bid.customKeywords);
for (NSString *key in bid.customKeywords.allKeys) {
if ([key containsString:@"hb_cache_id_"]) {
isCacheIdPresent = YES;
cacheKey = key;
XCTAssertTrue(key.length <=20);
}
if ([key isEqualToString:@"hb_bidder"]) {
isTopBid = YES;
}
if ([key isEqualToString:@"hb_cache_id"]) {
if (cacheIdHasBeenSeen) {
XCTFail(@"should not be setting hb_cache_id twice");
} else {
cacheIdHasBeenSeen = YES;
}
}

}
if (isTopBid) {
XCTAssertTrue([bid.customKeywords.allKeys containsObject:@"hb_cache_id"]);
XCTAssertEqual([bid.customKeywords objectForKey:@"hb_cache_id"], [bid.customKeywords objectForKey:cacheKey]);
} else {
XCTAssertTrue(![bid.customKeywords.allKeys containsObject:@"hb_cahce_id"]);
}
XCTAssertTrue(isCacheIdPresent);
}
weakSelf.completionHandler = ^(NSArray *bids, NSError *error){
XCTAssertNil(bids);
XCTAssertNotNil(error);
XCTAssertEqual(@"prebid.org", error.domain);
XCTAssertEqual(0, error.code);
[expectation fulfill];
};
[self waitForExpectationsWithTimeout:20.0 handler:nil];
}

- (void)testRequestBodyForAdUnit {

[[PBTargetingParams sharedInstance] setUserKeywords:@"targeting1" withValue:@"value1"];
Expand All @@ -223,6 +198,11 @@ - (void)testRequestBodyForAdUnit {
XCTAssertEqualObjects(requestBody[@"ext"][@"prebid"][@"storedrequest"][@"id"], @"account_id");
NSDictionary *targeting = requestBody[@"ext"][@"prebid"][@"targeting"];
XCTAssertNotNil(targeting);
NSDictionary *cache = requestBody[@"ext"][@"prebid"][@"cache"];
XCTAssertNotNil(cache);
NSDictionary *cacheBids = cache[@"bids"];
XCTAssertNotNil(cacheBids);
XCTAssertTrue(cacheBids.count == 0);

NSDictionary *app = requestBody[@"app"][@"ext"][@"prebid"];
XCTAssertNotNil(app[@"version"]);
Expand Down
39 changes: 18 additions & 21 deletions sdk/PrebidServerAdapter/PBServerAdapter.m
Original file line number Diff line number Diff line change
Expand Up @@ -100,33 +100,30 @@ - (void)requestBidsWithAdUnits:(nullable NSArray<PBAdUnit *> *)adUnits
NSString *escapedBid = [self escapeJsonString:[self jsonStringFromDictionary:bid]];
[contentsToCache addObject:escapedBid];
}

[[PrebidCache globalCache] cacheContents:contentsToCache forAdserver:self.primaryAdServer withCompletionBlock:^(NSArray *cacheIds) {

for (int i = 0; i< bidsArray.count; i++) {
NSMutableDictionary *adServerTargetingCopy = [bidsArray[i][@"ext"][@"prebid"][@"targeting"] mutableCopy];
if (adServerTargetingCopy != nil) {
if (i == 0) {
NSString *cacheId = cacheIds[i];
adServerTargetingCopy[kAPNAdServerCacheIdKey] = cacheId;
for (int i = 0; i< bidsArray.count; i++) {
NSMutableDictionary *adServerTargetingCopy = [bidsArray[i][@"ext"][@"prebid"][@"targeting"] mutableCopy];
if (adServerTargetingCopy != nil) {
// Check if resposne has cache id, since prebid server cache would fail for some reason and not set cache id on the response
// If cache id is not present, we do not pass the bid back
bool hasCacheID = NO;
for (NSString *key in adServerTargetingCopy.allKeys) {
if ([key containsString:@"hb_cache_id"]) {
hasCacheID = YES;
}
NSString *bidderCacheId = cacheIds[i];
NSString *cacheIdkey =[ NSString stringWithFormat:@"%@_%@", kAPNAdServerCacheIdKey, bidsArray[i][@"seat"]];
cacheIdkey = cacheIdkey.length > 20 ? [cacheIdkey substringToIndex:20] : cacheIdkey;
adServerTargetingCopy[cacheIdkey] = bidderCacheId;
}
if (hasCacheID) {
PBBidResponse *bidResponse = [PBBidResponse bidResponseWithAdUnitId:adUnitId adServerTargeting:adServerTargetingCopy];
PBLogDebug(@"Bid Successful with rounded bid targeting keys are %@ for adUnit id is %@", [bidResponse.customKeywords description], adUnitId);
[bidResponsesArray addObject:bidResponse];
}
}
if (bidResponsesArray.count == 0) {
// use code 0 to represent the no bid case for now
[delegate didCompleteWithError:[NSError errorWithDomain:@"prebid.org" code:0 userInfo:nil] ];
} else {
[delegate didReceiveSuccessResponse:bidResponsesArray];
}

}];
}
if (bidResponsesArray.count == 0) {
// use code 0 to represent the no bid case for now
[delegate didCompleteWithError:[NSError errorWithDomain:@"prebid.org" code:0 userInfo:nil] ];
} else {
[delegate didReceiveSuccessResponse:bidResponsesArray];
}
}
}];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ - (NSDictionary *)openrtbRequestExtension: (NSString *)accountId
NSMutableDictionary *requestPrebidExt = [[NSMutableDictionary alloc] init];
requestPrebidExt[@"targeting"] = @{};
requestPrebidExt[@"storedrequest"] = @{@"id" :accountId};

requestPrebidExt[@"cache"] = @{@"bids" : [[NSMutableDictionary alloc] init]};
NSMutableDictionary *requestExt = [[NSMutableDictionary alloc] init];
requestExt[@"prebid"] = requestPrebidExt;
return [requestExt copy];
Expand Down

0 comments on commit 3f0d566

Please sign in to comment.