Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace usePrebidCache with cache:url and remove default #1904

Merged
merged 7 commits into from
Dec 6, 2017
2 changes: 1 addition & 1 deletion modules/dfpAdServerVideo.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function buildUrlFromAdserverUrlComponents(components, bid) {
* @return {string | undefined} The encoded vast url if it exists, or undefined
*/
function getDescriptionUrl(bid, components, prop) {
if (config.getConfig('usePrebidCache')) { return; }
if (config.getConfig('video.cacheUrl')) { return; }

if (!deepAccess(components, `${prop}.description_url`)) {
const vastUrl = bid && bid.vastUrl;
Expand Down
2 changes: 1 addition & 1 deletion src/auction.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@snapwich Not sure if I did something wrong when checking this branch out locally but I see one remaining reference to usePrebidCache in this file on line 155. Everything else lgtm

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No you are correct. It looks like Jaimin added a new call to usePrebidCache after the creation of this pull-request which I got with the latest merge update. Just fixed and updated, as well as removed a call to it in one of the bid adapters.

// Video bids may fail if the cache is down, or there's trouble on the network.
function tryAddVideoBid(bidResponse) {
if (config.getConfig('usePrebidCache')) {
if (config.getConfig('video.cacheUrl')) {
store([bidResponse], function(error, cacheIds) {
if (error) {
utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`);
Expand Down
231 changes: 118 additions & 113 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,128 +46,130 @@ const ALL_TOPICS = '*';
/**
* @typedef {object} PrebidConfig
*
* @property {bool} usePrebidCache True if we should use prebid-cache to store video bids before adding
* bids to the auction, and false otherwise. **NOTE** This must be true if you want to use the
* dfpAdServerVideo module.
* @property {bool} config.cacheUrl Set a url if we should use prebid-cache to store video bids before adding
Copy link
Contributor

@dbemiller dbemiller Dec 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this should be a {string}, in your current code.

Just so you're aware, we'll be building some cache features into prebid-server sometime fairly soon. If s2s is enabled, the JS code might want to take advantage of it. Since PBS and PBC will often be hosted in the same data center, you should get much better performance by asking PBS to cache things, rather than doing it client-side.

To give you some idea, this is (roughly) the API I'm planning for PBS:

{
  "cache": {
    "vastxml": {
      "winners": true,
      "deals": true,
      "all": true,
      "minCPM": 0.01
    }
  }
}

If you have feedback on this, feel free to discuss it over on prebid/prebid-server#216. For this PR, though: It might be better to make a cache: object with a url: string property. When PBS catches up, you'll be able to add support for these features without breaking the API.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm cool with that. I'll update it to be cache.url

* bids to the auction. **NOTE** This must be set if you want to use the dfpAdServerVideo module.
*/

export function newConfig() {
let listeners = [];

let defaults = {};

let config = {
// `debug` is equivalent to legacy `pbjs.logging` property
_debug: DEFAULT_DEBUG,
get debug() {
return this._debug;
},
set debug(val) {
this._debug = val;
},

// default timeout for all bids
_bidderTimeout: DEFAULT_BIDDER_TIMEOUT,
get bidderTimeout() {
return this._bidderTimeout;
},
set bidderTimeout(val) {
this._bidderTimeout = val;
},

// domain where prebid is running for cross domain iframe communication
_publisherDomain: DEFAULT_PUBLISHER_DOMAIN,
get publisherDomain() {
return this._publisherDomain;
},
set publisherDomain(val) {
this._publisherDomain = val;
},

// delay to request cookie sync to stay out of critical path
_cookieSyncDelay: DEFAULT_COOKIESYNC_DELAY,
get cookieSyncDelay() {
return $$PREBID_GLOBAL$$.cookieSyncDelay || this._cookieSyncDelay;
},
set cookieSyncDelay(val) {
this._cookieSyncDelay = val;
},

// calls existing function which may be moved after deprecation
_priceGranularity: GRANULARITY_OPTIONS.MEDIUM,
set priceGranularity(val) {
if (validatePriceGranularity(val)) {
if (typeof val === 'string') {
this._priceGranularity = (hasGranularity(val)) ? val : GRANULARITY_OPTIONS.MEDIUM;
} else if (typeof val === 'object') {
this._customPriceBucket = val;
this._priceGranularity = GRANULARITY_OPTIONS.CUSTOM;
utils.logMessage('Using custom price granularity');
let defaults;
let config;

function resetConfig() {
defaults = {};
config = {
// `debug` is equivalent to legacy `pbjs.logging` property
_debug: DEFAULT_DEBUG,
get debug() {
return this._debug;
},
set debug(val) {
this._debug = val;
},

// default timeout for all bids
_bidderTimeout: DEFAULT_BIDDER_TIMEOUT,
get bidderTimeout() {
return this._bidderTimeout;
},
set bidderTimeout(val) {
this._bidderTimeout = val;
},

// domain where prebid is running for cross domain iframe communication
_publisherDomain: DEFAULT_PUBLISHER_DOMAIN,
get publisherDomain() {
return this._publisherDomain;
},
set publisherDomain(val) {
this._publisherDomain = val;
},

// delay to request cookie sync to stay out of critical path
_cookieSyncDelay: DEFAULT_COOKIESYNC_DELAY,
get cookieSyncDelay() {
return $$PREBID_GLOBAL$$.cookieSyncDelay || this._cookieSyncDelay;
},
set cookieSyncDelay(val) {
this._cookieSyncDelay = val;
},

// calls existing function which may be moved after deprecation
_priceGranularity: GRANULARITY_OPTIONS.MEDIUM,
set priceGranularity(val) {
if (validatePriceGranularity(val)) {
if (typeof val === 'string') {
this._priceGranularity = (hasGranularity(val)) ? val : GRANULARITY_OPTIONS.MEDIUM;
} else if (typeof val === 'object') {
this._customPriceBucket = val;
this._priceGranularity = GRANULARITY_OPTIONS.CUSTOM;
utils.logMessage('Using custom price granularity');
}
}
}
},
get priceGranularity() {
return this._priceGranularity;
},

_customPriceBucket: {},
get customPriceBucket() {
return this._customPriceBucket;
},

_sendAllBids: DEFAULT_ENABLE_SEND_ALL_BIDS,
get enableSendAllBids() {
return this._sendAllBids;
},
set enableSendAllBids(val) {
this._sendAllBids = val;
},

_bidderSequence: DEFAULT_BIDDER_SEQUENCE,
get bidderSequence() {
return this._bidderSequence;
},
set bidderSequence(val) {
if (VALID_ORDERS[val]) {
this._bidderSequence = val;
} else {
utils.logWarn(`Invalid order: ${val}. Bidder Sequence was not set.`);
}
},

// timeout buffer to adjust for bidder CDN latency
_timoutBuffer: DEFAULT_TIMEOUTBUFFER,
get timeoutBuffer() {
return this._timoutBuffer;
},
set timeoutBuffer(val) {
this._timoutBuffer = val;
},

// userSync defaults
userSync: DEFAULT_USERSYNC
};

function hasGranularity(val) {
return Object.keys(GRANULARITY_OPTIONS).find(option => val === GRANULARITY_OPTIONS[option]);
}
},
get priceGranularity() {
return this._priceGranularity;
},

_customPriceBucket: {},
get customPriceBucket() {
return this._customPriceBucket;
},

_sendAllBids: DEFAULT_ENABLE_SEND_ALL_BIDS,
get enableSendAllBids() {
return this._sendAllBids;
},
set enableSendAllBids(val) {
this._sendAllBids = val;
},

_bidderSequence: DEFAULT_BIDDER_SEQUENCE,
get bidderSequence() {
return this._bidderSequence;
},
set bidderSequence(val) {
if (VALID_ORDERS[val]) {
this._bidderSequence = val;
} else {
utils.logWarn(`Invalid order: ${val}. Bidder Sequence was not set.`);
}
},

// timeout buffer to adjust for bidder CDN latency
_timoutBuffer: DEFAULT_TIMEOUTBUFFER,
get timeoutBuffer() {
return this._timoutBuffer;
},
set timeoutBuffer(val) {
this._timoutBuffer = val;
},

// userSync defaults
userSync: DEFAULT_USERSYNC
};

function validatePriceGranularity(val) {
if (!val) {
utils.logError('Prebid Error: no value passed to `setPriceGranularity()`');
return false;
function hasGranularity(val) {
return Object.keys(GRANULARITY_OPTIONS).find(option => val === GRANULARITY_OPTIONS[option]);
}
if (typeof val === 'string') {
if (!hasGranularity(val)) {
utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using `medium` as default.');
}
} else if (typeof val === 'object') {
if (!isValidPriceConfig(val)) {
utils.logError('Invalid custom price value passed to `setPriceGranularity()`');

function validatePriceGranularity(val) {
if (!val) {
utils.logError('Prebid Error: no value passed to `setPriceGranularity()`');
return false;
}
if (typeof val === 'string') {
if (!hasGranularity(val)) {
utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using `medium` as default.');
}
} else if (typeof val === 'object') {
if (!isValidPriceConfig(val)) {
utils.logError('Invalid custom price value passed to `setPriceGranularity()`');
return false;
}
}
return true;
}
return true;
}

/*
Expand Down Expand Up @@ -289,10 +291,13 @@ export function newConfig() {
.forEach(listener => listener.callback(options));
}

resetConfig();

return {
getConfig,
setConfig,
setDefaults
setDefaults,
resetConfig
};
}

Expand Down
8 changes: 4 additions & 4 deletions src/video.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ export function isValidVideoBid(bid, bidRequests) {
// if context not defined assume default 'instream' for video bids
// instream bids require a vast url or vast xml content
if (!bidRequest || (videoMediaType && context !== OUTSTREAM)) {
// xml-only video bids require prebid-cache to be enabled
if (!config.getConfig('usePrebidCache') && bid.vastXml && !bid.vastUrl) {
// xml-only video bids require a prebid cache url
if (!config.getConfig('video.cacheUrl') && bid.vastXml && !bid.vastUrl) {
logError(`
This bid contains only vastXml and will not work when prebid-cache is disabled.
Try enabling prebid-cache with pbjs.setConfig({ usePrebidCache: true });
This bid contains only vastXml and will not work when a prebid cache url is not specified.
Try enabling prebid cache with pbjs.setConfig({ video: {cacheUrl: "..."} });
`);
return false;
}
Expand Down
7 changes: 3 additions & 4 deletions src/videoCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
*/

import { ajax } from './ajax';

const BASE_URL = 'https://prebid.adnxs.com/pbc/v1/cache'
import { config } from '../src/config';

/**
* @typedef {object} CacheableUrlBid
Expand Down Expand Up @@ -119,12 +118,12 @@ export function store(bids, done) {
puts: bids.map(toStorageRequest)
};

ajax(BASE_URL, shimStorageCallback(done), JSON.stringify(requestData), {
ajax(config.getConfig('video.cacheUrl'), shimStorageCallback(done), JSON.stringify(requestData), {
contentType: 'text/plain',
withCredentials: true
});
}

export function getCacheUrl(id) {
return `${BASE_URL}?uuid=${id}`;
return `${config.getConfig('video.cacheUrl')}?uuid=${id}`;
}
6 changes: 5 additions & 1 deletion test/spec/modules/dfpAdServerVideo_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ describe('The DFP video support module', () => {

it('should not overwrite an existing description_url for object input and cache disabled', () => {
const config = newConfig();
config.setConfig({ usePrebidCache: true });
config.setConfig({
video: {
cacheUrl: 'https://prebid.adnxs.com/pbc/v1/cache'
}
});

const bidCopy = Object.assign({}, bid);
bidCopy.vastUrl = 'vastUrl.example';
Expand Down
23 changes: 22 additions & 1 deletion test/spec/videoCache_spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'mocha';
import chai from 'chai';
import { getCacheUrl, store } from 'src/videoCache';
import { config } from 'src/config';

const should = chai.should();

Expand Down Expand Up @@ -48,9 +49,17 @@ describe('The video cache', () => {
xhr = sinon.useFakeXMLHttpRequest();
requests = [];
xhr.onCreate = (request) => requests.push(request);
config.setConfig({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why wouldn't you just use newConfig() here? Like dfpAdServerVideo_spec.js does.

It cuts down on the changes you need to make for this PR by quite a bit.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that newConfig is working as you are intending it to. For instance, I just removed it from dfpAdServerVideo_spec.js file and the tests still pass. The actual dfpAdServerVideo.js module is operating on the config object in in config.js, not the new config object created with newConfig(), so unless you change these modules to dependency injection where you inject the config object, using newConfig doesn't do anything.

video: {
cacheUrl: 'https://prebid.adnxs.com/pbc/v1/cache'
}
})
});

afterEach(() => xhr.restore());
afterEach(() => {
xhr.restore();
config.resetConfig();
});

it('should execute the callback with a successful result when store() is called', () => {
const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371';
Expand Down Expand Up @@ -128,6 +137,18 @@ describe('The video cache', () => {
});

describe('The getCache function', () => {
beforeEach(() => {
config.setConfig({
video: {
cacheUrl: 'https://prebid.adnxs.com/pbc/v1/cache'
}
})
});

afterEach(() => {
config.resetConfig();
});

it('should return the expected URL', () => {
const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371';
const url = getCacheUrl(uuid);
Expand Down
5 changes: 0 additions & 5 deletions test/spec/video_spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { isValidVideoBid } from 'src/video';
import { newConfig } from 'src/config';
import * as utils from 'src/utils';

describe('video.js', () => {
it('validates valid instream bids', () => {
Expand Down Expand Up @@ -46,9 +44,6 @@ describe('video.js', () => {
}]
}];

const config = newConfig();
config.setConfig({ usePrebidCache: false });

const valid = isValidVideoBid({ vastXml: '<xml>vast</xml>' }, bidRequests);

expect(valid).to.be(false);
Expand Down