You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
const{ Sender }=require("@questdb/nodejs-client");asyncfunctionrun(){// create a sender with a 4k buffer// it is important to size the buffer correctly so messages can fitconstsender=newSender({bufferSize: 4096});// connect to QuestDB// host and port are required in connect optionsawaitsender.connect({port: 9009,host: "localhost"});// add rows to the buffer of the sendersender.table("prices").symbol("instrument","EURUSD").floatColumn("bid",1.0195).floatColumn("ask",1.0221).atNow();sender.table("prices").symbol("instrument","GBPUSD").floatColumn("bid",1.2076).floatColumn("ask",1.2082).atNow();// flush the buffer of the sender, sending the data to QuestDB// the buffer is cleared after the data is sent and the sender is ready to accept new dataawaitsender.flush();// add rows to the buffer again and send it to the serversender.table("prices").symbol("instrument","EURUSD").floatColumn("bid",1.0197).floatColumn("ask",1.0224).atNow();awaitsender.flush();// close the connection after all rows ingestedawaitsender.close();returnnewPromise(resolve=>resolve(0));}run().then(value=>console.log(value)).catch(err=>console.log(err));
Authentication and secure connection
const{ Sender }=require("@questdb/nodejs-client");asyncfunctionrun(){// construct a JsonWebKeyconstCLIENT_ID="testapp";constPRIVATE_KEY="9b9x5WhJywDEuo1KGQWSPNxtX-6X6R2BRCKhYMMY6n8";constPUBLIC_KEY={x: "aultdA0PjhD_cWViqKKyL5chm6H1n-BiZBo_48T-uqc",y: "__ptaol41JWSpTTL525yVEfzmY8A6Vi_QrW1FjKcHMg"};constJWK={
...PUBLIC_KEY,d: PRIVATE_KEY,kid: CLIENT_ID,kty: "EC",crv: "P-256",};// pass the JsonWebKey to the sender// will use it for authenticationconstsender=newSender({bufferSize: 4096,jwk: JWK});// connect() takes an optional second argument// if 'true' passed the connection is secured with TLS encryptionawaitsender.connect({port: 9009,host: "localhost"},true);// send the data over the authenticated and secure connectionsender.table("prices").symbol("instrument","EURUSD").floatColumn("bid",1.0197).floatColumn("ask",1.0224).atNow();awaitsender.flush();// close the connection after all rows ingestedawaitsender.close();returnnewPromise(resolve=>resolve(0));}run().then(value=>console.log(value)).catch(err=>console.log(err));
TypeScript example
import{Sender}from"@questdb/nodejs-client";asyncfunctionrun(): Promise<number>{// construct a JsonWebKeyconstCLIENT_ID: string="testapp";constPRIVATE_KEY: string="9b9x5WhJywDEuo1KGQWSPNxtX-6X6R2BRCKhYMMY6n8";constPUBLIC_KEY: {x: string,y: string}={x: "aultdA0PjhD_cWViqKKyL5chm6H1n-BiZBo_48T-uqc",y: "__ptaol41JWSpTTL525yVEfzmY8A6Vi_QrW1FjKcHMg"};constJWK: {x: string,y: string,kid: string,kty: string,d: string,crv: string}={
...PUBLIC_KEY,d: PRIVATE_KEY,kid: CLIENT_ID,kty: "EC",crv: "P-256",};// pass the JsonWebKey to the sender// will use it for authenticationconstsender: Sender=newSender({bufferSize: 4096,jwk: JWK});// connect() takes an optional second argument// if 'true' passed the connection is secured with TLS encryptionawaitsender.connect({port: 9009,host: "localhost"},true);// send the data over the authenticated and secure connectionsender.table("prices").symbol("instrument","EURUSD").floatColumn("bid",1.0197).floatColumn("ask",1.0224).atNow();awaitsender.flush();// close the connection after all rows ingestedawaitsender.close();returnnewPromise(resolve=>resolve(0));}run().then(value=>console.log(value)).catch(err=>console.log(err));
Worker threads example
const{ Sender }=require("@questdb/nodejs-client");const{ Worker, isMainThread, parentPort, workerData }=require('worker_threads');// fake venue// generates random prices for a ticker for max 5 seconds, then the feed closesfunction*venue(ticker){letend=false;setTimeout(()=>{end=true;},rndInt(5000));while(!end){yield{"ticker": ticker,"price": Math.random()};}}// market data feed simulator// uses the fake venue to deliver price updates to the feed handler (onTick() callback)asyncfunctionsubscribe(ticker,onTick){constfeed=venue(workerData.ticker);lettick;while(tick=feed.next().value){awaitonTick(tick);awaitsleep(rndInt(30));}}asyncfunctionrun(){if(isMainThread){consttickers=["t1","t2","t3","t4"];// main thread to start a worker thread for each tickerfor(lettickerintickers){constworker=newWorker(__filename,{workerData: {ticker: ticker}}).on('error',(err)=>{throwerr;}).on('exit',()=>{console.log(`${ticker} thread exiting...`);}).on('message',(msg)=>{console.log("Ingested "+msg.count+" prices for ticker "+msg.ticker);});}}else{// it is important that each worker has a dedicated sender object// threads cannot share the sender because they would write into the same bufferconstsender=newSender({bufferSize: 4096});awaitsender.connect({port: 9009,host: "localhost"});// subscribe for the market data of the ticker assigned to the worker// ingest each price update into the database using the senderletcount=0;awaitsubscribe(workerData.ticker,async(tick)=>{sender.table("prices").symbol("ticker",tick.ticker).floatColumn("price",tick.price).atNow();awaitsender.flush();count++;});// let the main thread know how many prices were ingestedparentPort.postMessage({"ticker": workerData.ticker,"count": count});// close the connection to the databaseawaitsender.close();}}functionsleep(ms){returnnewPromise(resolve=>setTimeout(resolve,ms));}functionrndInt(limit){returnMath.floor((Math.random()*limit)+1);}run().catch((err)=>console.log(err));