![]() |
RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
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