RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
js/bidding_agent_js.cc
00001 /* bidding_agent_js.cc                                              -*- C++ -*-
00002    Rémi Attab, 14 December 2011
00003    Copyright (c) 2011 Datacratic.  All rights reserved.
00004 
00005    Provides the JS bindings for the router proxy.
00006 */
00007 
00008 #define BOOST_FUNCTION_MAX_ARGS 20
00009 
00010 #include "bidding_agent_js.h"
00011 #include "bid_request_js.h"
00012 #include "currency_js.h"
00013 #include "bids_js.h"
00014 #include "soa/service/js/service_base_js.h"
00015 #include "soa/service/js/opstats_js.h"
00016 
00017 #include "v8.h"
00018 #include "node.h"
00019 
00020 #include "soa/js/js_call.h"
00021 #include "soa/js/js_value.h"
00022 #include "soa/js/js_utils.h"
00023 #include "soa/js/js_wrapped.h"
00024 #include "soa/js/js_registry.h"
00025 #include "soa/sigslot/slot.h"
00026 
00027 #include "jml/utils/smart_ptr_utils.h"
00028 #include "soa/types/js/id_js.h"
00029 
00030 using namespace std;
00031 using namespace v8;
00032 using namespace node;
00033 
00034 
00035 namespace Datacratic {
00036 namespace JS {
00037 
00038 
00039 
00040 /******************************************************************************/
00041 /* RESULT CB OPS                                                              */
00042 /******************************************************************************/
00043 
00048 struct ResultCbOps:
00049     public JS::JsOpsBase<ResultCbOps, RTBKIT::BiddingAgent::ResultCb>
00050 {
00051     static v8::Handle<v8::Value>
00052     callBoost(const Function & fn,
00053               const JS::JSArgs & args)
00054     {
00055         throw ML::Exception("callBoost for resultCB");
00056     }
00057 
00058     struct Forwarder : public calltojsbase {
00059 
00060         Forwarder(v8::Handle<v8::Function> fn,
00061                   v8::Handle<v8::Object> This)
00062             : calltojsbase(fn, This)
00063         {
00064         }
00065 
00066         void operator () (const RTBKIT::BidResult & args)
00067         {
00068             v8::HandleScope scope;
00069             JSValue result;
00070             {
00071                 v8::TryCatch tc;
00072                 v8::Handle<v8::Value> argv[9];
00073                 argv[0] = JS::toJS(args.timestamp);
00074                 argv[1] = JS::toJS(args.confidence);
00075                 argv[2] = JS::toJS(args.auctionId);
00076                 argv[3] = JS::toJS(args.spotNum);
00077                 argv[4] = JS::toJS(static_cast<int64_t>(MicroUSD(args.secondPrice)));
00078                 if (args.request)
00079                     argv[5] = JS::toJS(args.request);
00080                 else argv[5] = v8::Null();
00081                 argv[6] = JS::toJS(args.ourBid);
00082                 argv[7] = JS::toJS(args.metadata);
00083                 argv[8] = JS::toJS(args.augmentations);
00084 
00085                 result = params->fn->Call(params->This, 9, argv);
00086 
00087                 if (result.IsEmpty()) {
00088                     if(tc.HasCaught()) {
00089                         // Print JS error and stack trace
00090                         char msg[256];
00091                         tc.Message()->Get()->WriteAscii(msg, 0, 256);
00092                         cout << msg << endl;
00093                         char st_msg[2500];
00094                         tc.StackTrace()->ToString()->WriteAscii(st_msg, 0, 2500);
00095                         cout << st_msg << endl;
00096 
00097                         tc.ReThrow();
00098                         throw JSPassException();
00099                     }
00100                     throw ML::Exception("didn't return anything");
00101                 }
00102             }
00103         }
00104     };
00105 
00106     static Function
00107     asBoost(const v8::Handle<v8::Function> & fn,
00108             const v8::Handle<v8::Object> * This)
00109     {
00110         v8::Handle<v8::Object> This2;
00111         if (!This)
00112             This2 = v8::Object::New();
00113         return Forwarder(fn, This ? *This : This2);
00114     }
00115 };
00116 
00117 RegisterJsOps<RTBKIT::BiddingAgent::ResultCb> reg_resultCb(ResultCbOps::op);
00118 
00119 
00120 /******************************************************************************/
00121 /* DELIVERY CB OPS                                                            */
00122 /******************************************************************************/
00123 
00124 struct DeliveryCbOps :
00125     public JS::JsOpsBase<DeliveryCbOps, RTBKIT::BiddingAgent::DeliveryCb>
00126 {
00127 
00128     static v8::Handle<v8::Value>
00129     callBoost(const Function & fn,
00130               const JS::JSArgs & args)
00131     {
00132         throw ML::Exception("callBoost for resultCB");
00133     }
00134 
00135     struct Forwarder : public calltojsbase {
00136 
00137         Forwarder(v8::Handle<v8::Function> fn,
00138                   v8::Handle<v8::Object> This)
00139             : calltojsbase(fn, This)
00140         {
00141         }
00142 
00143         void operator () (const RTBKIT::DeliveryEvent & args)
00144         {
00145             v8::HandleScope scope;
00146             JSValue result;
00147             {
00148                 v8::TryCatch tc;
00149                 v8::Handle<v8::Value> argv[11];
00150 
00151                 argv[0] = JS::toJS(args.timestamp);
00152                 argv[1] = JS::toJS(args.auctionId);
00153                 argv[2] = JS::toJS(args.spotId);
00154                 argv[3] = JS::toJS(args.spotIndex);
00155                 argv[4] = JS::toJS(args.bidRequest);
00156                 argv[5] = JS::toJS(args.bid.toJson());
00157                 argv[6] = JS::toJS(args.win.toJson());
00158                 argv[7] = JS::toJS(args.impressionToJson());
00159                 argv[8] = JS::toJS(args.clickToJson());
00160                 argv[9] = JS::toJS(args.augmentations);
00161                 argv[10] = JS::toJS(args.visitsToJson());
00162 
00163                 result = params->fn->Call(params->This, 11, argv);
00164 
00165                 if (result.IsEmpty()) {
00166                     if(tc.HasCaught()) {
00167                         // Print JS error and stack trace
00168                         char msg[256];
00169                         tc.Message()->Get()->WriteAscii(msg, 0, 256);
00170                         cout << msg << endl;
00171                         char st_msg[2500];
00172                         tc.StackTrace()->ToString()->WriteAscii(st_msg, 0, 2500);
00173                         cout << st_msg << endl;
00174 
00175                         tc.ReThrow();
00176                         throw JSPassException();
00177                     }
00178                     throw ML::Exception("didn't return anything");
00179                 }
00180             }
00181         }
00182     };
00183 
00184     static Function
00185     asBoost(const v8::Handle<v8::Function> & fn,
00186             const v8::Handle<v8::Object> * This)
00187     {
00188         v8::Handle<v8::Object> This2;
00189         if (!This)
00190             This2 = v8::Object::New();
00191         return Forwarder(fn, This ? *This : This2);
00192     }
00193 };
00194 
00195 RegisterJsOps<RTBKIT::BiddingAgent::DeliveryCb> reg_deliveryCb(DeliveryCbOps::op);
00196 
00197 
00198 /******************************************************************************/
00199 /* BIDDING AGENT JS                                                           */
00200 /******************************************************************************/
00201 
00202 const char* BiddingAgentName = "BiddingAgent";
00203 
00204 RegisterJsOps<RTBKIT::BiddingAgent::BidRequestCb> reg_bidRequestCb;
00205 RegisterJsOps<RTBKIT::BiddingAgent::PingCb> reg_pingCb;
00206 RegisterJsOps<RTBKIT::BiddingAgent::ErrorCb> reg_errorCb;
00207 
00208 struct BiddingAgentJS :
00209     public JSWrapped2<
00210         RTBKIT::BiddingAgent,
00211         BiddingAgentJS,
00212         BiddingAgentName,
00213         rtbModule>
00214 {
00215 
00216     BiddingAgentJS(
00217             v8::Handle<v8::Object> This,
00218             const std::shared_ptr<RTBKIT::BiddingAgent>& routerProxy =
00219                 std::shared_ptr<RTBKIT::BiddingAgent>())
00220     {
00221         HandleScope scope;
00222         wrap(This, routerProxy);
00223     }
00224 
00225     static Handle<v8::Value> New(const Arguments& args)
00226     {
00227         try {
00228             string name = getArg(args, 0, "", "serviceName");
00229             auto proxies = getArg(
00230                     args, 1, std::make_shared<ServiceProxies>(), "proxies");
00231 
00232             auto routerProxy = ML::make_std_sp(new RTBKIT::BiddingAgent(proxies, name));
00233             new BiddingAgentJS(args.This(), routerProxy);
00234 
00235             return args.This();
00236         }
00237         HANDLE_JS_EXCEPTIONS;
00238     }
00239 
00240     static void Initialize () {
00241         Persistent<FunctionTemplate> t = Register(New);
00242 
00243         registerMemberFn(&RTBKIT::BiddingAgent::doBid, "doBid");
00244         registerMemberFn(&RTBKIT::BiddingAgent::doPong, "doPong");
00245         registerMemberFn(&RTBKIT::BiddingAgent::doConfigJson, "doConfig");
00246         registerMemberFn(&RTBKIT::BiddingAgent::init, "init");
00247         registerMemberFn(&RTBKIT::BiddingAgent::start, "start");
00248         registerMemberFn(&RTBKIT::BiddingAgent::shutdown, "close");
00249         registerMemberFn(&RTBKIT::BiddingAgent::strictMode, "strictMode");
00250 
00251         registerAsyncCallback(&RTBKIT::BiddingAgent::onBidRequest, "onBidRequest");
00252 
00253         registerAsyncCallback(&RTBKIT::BiddingAgent::onWin, "onWin");
00254         registerAsyncCallback(&RTBKIT::BiddingAgent::onLoss, "onLoss");
00255         registerAsyncCallback(&RTBKIT::BiddingAgent::onNoBudget, "onNoBudget");
00256         registerAsyncCallback(&RTBKIT::BiddingAgent::onTooLate, "onTooLate");
00257         registerAsyncCallback(&RTBKIT::BiddingAgent::onInvalidBid, "onInvalidBid");
00258         registerAsyncCallback(&RTBKIT::BiddingAgent::onDroppedBid, "onDroppedBid");
00259 
00260         registerAsyncCallback(&RTBKIT::BiddingAgent::onImpression, "onImpression");
00261         registerAsyncCallback(&RTBKIT::BiddingAgent::onClick, "onClick");
00262         registerAsyncCallback(&RTBKIT::BiddingAgent::onVisit, "onVisit");
00263 
00264         registerAsyncCallback(&RTBKIT::BiddingAgent::onPing, "onPing");
00265         registerAsyncCallback(&RTBKIT::BiddingAgent::onError, "onError");
00266     }
00267 };
00268 
00269 std::shared_ptr<RTBKIT::BiddingAgent>
00270 from_js (const JSValue& value, std::shared_ptr<RTBKIT::BiddingAgent>*)
00271 {
00272     return BiddingAgentJS::fromJS(value);
00273 }
00274 
00275 RTBKIT::BiddingAgent*
00276 from_js (const JSValue& value, RTBKIT::BiddingAgent**)
00277 {
00278     return BiddingAgentJS::fromJS(value).get();
00279 }
00280 
00281 
00282 
00283 } // namespace JS
00284 } // namespace Datacratic
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator