@mediarithmics/plugins-nodejs-sdk
Version:
This is the mediarithmics nodejs to help plugin developers bootstrapping their plugin without having to deal with most of the plugin boilerplate
119 lines • 5.93 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BidOptimizerPlugin = void 0;
const lodash_1 = __importDefault(require("lodash"));
const common_1 = require("../common");
class BidOptimizerPlugin extends common_1.BasePlugin {
constructor(enableThrottling = false) {
super(enableThrottling);
this.initBidDecisions();
this.setErrorHandler();
}
/**
*
* @param bidOptimizerId
*/
async fetchBidOptimizer(bidOptimizerId) {
const bidOptimizerResponse = await super.requestGatewayHelper('GET', `${this.outboundPlatformUrl}/v1/bid_optimizers/${bidOptimizerId}`);
this.logger.debug(`Fetched Bid Optimizer: ${bidOptimizerId} - ${JSON.stringify(bidOptimizerResponse.data)}`);
return bidOptimizerResponse.data;
}
/**
*
* @param bidOptimizerId
*/
async fetchBidOptimizerProperties(bidOptimizerId) {
const bidOptimizerPropertyResponse = await super.requestGatewayHelper('GET', `${this.outboundPlatformUrl}/v1/bid_optimizers/${bidOptimizerId}/properties`);
this.logger.debug(`Fetched BidOptimizer Properties: ${bidOptimizerId} - ${JSON.stringify(bidOptimizerPropertyResponse.data)}`);
return bidOptimizerPropertyResponse.data;
}
findBestSalesConditions(bidPrice, salesConditions) {
// Optimization, we only do the stringify if we are really on debug / silly mode
if (this.logger.level === 'debug' || this.logger.level === 'silly') {
this.logger.debug(`Looking to find the best sale condition for CPM: ${bidPrice} in: ${JSON.stringify(salesConditions, null, 4)}`);
}
const eligibleSalesConditions = salesConditions.filter((sc) => {
return sc.floor_price <= bidPrice;
});
// Optimization, we only do the stringify if we are really on debug / silly mode
if (this.logger.level === 'debug' || this.logger.level === 'silly') {
this.logger.debug(`Found eligible sales condition for CPM: ${bidPrice} in: ${JSON.stringify(eligibleSalesConditions, null, 4)}`);
}
const sortedEligibleSalesConditions = eligibleSalesConditions.sort((a, b) => {
return a.floor_price - b.floor_price;
});
// Optimization, we only do the stringify if we are really on debug / silly mode
if (this.logger.level === 'debug' || this.logger.level === 'silly') {
this.logger.debug(`Sorted eligible sales condition for CPM: ${bidPrice} in: ${JSON.stringify(sortedEligibleSalesConditions, null, 4)}`);
}
return sortedEligibleSalesConditions[0];
}
/**
* Method to build an instance context
* To be overriden to get a cutom behavior
* This is a default provided implementation
* @param bidOptimizerId
*/
async instanceContextBuilder(bidOptimizerId) {
const bidOptimizerP = this.fetchBidOptimizer(bidOptimizerId);
const bidOptimizerPropsP = this.fetchBidOptimizerProperties(bidOptimizerId);
const results = await Promise.all([bidOptimizerP, bidOptimizerPropsP]);
const bidOptimizer = results[0];
const bidOptimizerProps = results[1];
const context = {
bidOptimizer: bidOptimizer,
properties: new common_1.PropertiesWrapper(bidOptimizerProps),
};
return context;
}
async getInstanceContext(bidOptimizerId) {
if (!this.pluginCache.get(bidOptimizerId)) {
void this.pluginCache.put(bidOptimizerId, this.instanceContextBuilder(bidOptimizerId).catch((err) => {
this.logger.error(`Error while caching instance context: ${err.message}`);
this.pluginCache.del(bidOptimizerId);
throw err;
}), this.getInstanceContextCacheExpiration());
}
return this.pluginCache.get(bidOptimizerId);
}
initBidDecisions() {
this.app.post('/v1/bid_decisions', this.asyncMiddleware(async (req, res) => {
if (!this.httpIsReady()) {
const msg = {
error: 'Plugin not initialized',
};
this.logger.error('POST /v1/bid_decisions : %s', JSON.stringify(msg));
return res.status(500).json(msg);
}
else if (!req.body || lodash_1.default.isEmpty(req.body)) {
const msg = {
error: 'Missing request body',
};
this.logger.error('POST /v1/bid_decisions : %s', JSON.stringify(msg));
return res.status(500).json(msg);
}
else {
if (this.logger.level === 'debug' || this.logger.level === 'silly') {
this.logger.debug(`POST /v1/bid_decisions ${JSON.stringify(req.body)}`);
}
const bidOptimizerRequest = req.body;
if (!this.onBidDecisions) {
const errMsg = 'No BidOptimizer listener registered!';
this.logger.error(errMsg);
return res.status(500).json({ error: errMsg });
}
const instanceContext = await this.getInstanceContext(bidOptimizerRequest.campaign_info.bid_optimizer_id);
const bidOptimizerResponse = await this.onBidDecisions(bidOptimizerRequest, instanceContext);
if (this.logger.level === 'debug' || this.logger.level === 'silly') {
this.logger.debug(`Returning: ${JSON.stringify(bidOptimizerResponse)}`);
}
return res.status(200).send(JSON.stringify(bidOptimizerResponse));
}
}));
}
}
exports.BidOptimizerPlugin = BidOptimizerPlugin;
//# sourceMappingURL=BidOptimizerBasePlugin.js.map