peterszombati / xapi-node

xStation5 Trading API for NodeJS/JS
https://peterszombati.github.io/xapi-node/
Other
58 stars 19 forks source link

GetTickPrices stream hang up #34

Closed IonCimpoiesu closed 1 year ago

IonCimpoiesu commented 1 year ago

Hi, I recently upgraded the library from the version 2.5.4 to the latest and I noticed that some times streaming socket for the tick prices might hang up, it will stop streaming and will not output any error.

This behavior will trigger at random intervals, I couldn't trace it back to any specific maintenance or market opening/closure, etc...

Once I downgraded back to the version 2.5.4 I was able to run it without interruption for a week.

This is my current code and you can safely assume the errors are handled at higher levels and there is a try-catch that will handle unhandled exceptions that might have slipped at any level.

try {
    EnvLogger.debug(`Preparing feed stream listener...`, DEFAULT_LOG_CONTEXT);
    SiemLogger.debug("", Object.assign({
      content: {
        description: `Preparing feed stream listener...`
      }
    }, DEFAULT_LOG_CONTEXT));

    xapiClient.Stream.listen.getTickPrices(async data => {
      SiemLogger.info("", Object.assign({
        content: {
          description: `Received: ${JSON.stringify(data)}`
        }
      }, DEFAULT_LOG_CONTEXT));

      let date = new Date(data.timestamp),
        year = date.getUTCFullYear(),
        month = date.getUTCMonth() + 1,
        day = date.getDate(),
        tmp = new Object({
          timestamp: date,
          year: year,
          month: month,
          day: day,
          ymj: Number(`${year}${month < 10 ? "0" + month : month}`),
          ymdj: Number(`${year}${month < 10 ? "0" + month : month}${day < 10 ? "0" + day : day}`),
          provider: "XTB",
          level: data.level,
          quote: data.quoteId,
          price: {
            ask: data.ask,
            mid: (data.ask + data.bid) / 2,
            bid: data.bid
          },
          volume: {
            ask: data.askVolume,
            bid: data.bidVolume
          },
          spread: {
            raw: data.spreadRaw,
            table: data.spreadTable
          }
        }),
        symbol = data.symbol.toUpperCase();

      if (Object.keys(insertProjection).length === 0 || (Object.keys(insertProjection).length > 0 && isContainedIn(insertProjection, tmp))) {
        EnvLogger.debug(`Datapoint ${JSON.stringify(tmp)} matched insert projection ${JSON.stringify(insertProjection)}`, DEFAULT_LOG_CONTEXT);
        SiemLogger.debug("", Object.assign({
          content: {
            description: `Datapoint ${JSON.stringify(tmp)} matched insert projection ${JSON.stringify(insertProjection)}`
          }
        }, DEFAULT_LOG_CONTEXT));

        mongodbUtils.insertOne(dbClient, dbName, symbol, tmp).then(err => {
      date = null
          month = null
      day = null
      tmp = null
      data = null
          if (err !== null) {
            EnvLogger.error(`Couldn't upload ${err.stack}`, DEFAULT_LOG_CONTEXT);
            SiemLogger.error("", Object.assign({
              content: {
                description: `Couldn't upload ${err.message}`
              }
            }, DEFAULT_LOG_CONTEXT));
          } else {
            EnvLogger.debug(`Uploded ${JSON.stringify(tmp)} to '${symbol}' successfully`, DEFAULT_LOG_CONTEXT);
            SiemLogger.debug("", Object.assign({
              content: {
                description: `Uploded ${JSON.stringify(tmp)} to '${symbol}' successfully`
              }
            }, DEFAULT_LOG_CONTEXT));
          }
        });
      }
    });

    EnvLogger.debug(`Subscribing to ${tickers.length} tickers...`, DEFAULT_LOG_CONTEXT);
    SiemLogger.debug("", Object.assign({
      content: {
        description: `Subscribing to ${tickers.length} tickers...`
      }
    }, DEFAULT_LOG_CONTEXT));

    for (let i = 0; i < tickers.length; i += 1) {
      xapiClient.Stream.subscribe.getTickPrices(tickers[i], 0);
      EnvLogger.info(`Subscribed to ${tickers[i]}`, DEFAULT_LOG_CONTEXT);
      SiemLogger.info("", Object.assign({
        content: {
          description: `Subscribed to ${tickers[i]}`
        }
      }, DEFAULT_LOG_CONTEXT));
    }

  } catch (err) {
    EnvLogger.error(`Unhandled exception: ${err.stack}`, DEFAULT_LOG_CONTEXT);
    SiemLogger.error("", Object.assign({
      status: "KO",
      elapsed: new Date().getTime() - startTime,
      content: {
        description: `Unhandled exception: ${err.message}`
      }
    }, DEFAULT_LOG_CONTEXT));
    resolve(null);
  }
peterszombati commented 1 year ago

what you use v1 or v2? also try to add to logs when socket/stream closing this code is like nothing

IonCimpoiesu commented 1 year ago

Sorry for the late feedback. I updated to the latest version (used the V1 as before) , added the Event Listener for the connection change to my code and yesterday the socket hung up ending the log file with the following messages:

|TIMESTAMP=2023-10-10T22:44:30.010Z|TYPE=ENV|LEVEL=DEBUG|RUNTIME_ID=f39362da-fd8d-4508-91fe-648fcee1aee8|ID=22d58be3-1c48-4877-9476-0d1298ecfac7|METHOD=streamTickPrices
|>> Uploded {"timestamp":"2023-10-10T22:44:29.939Z","year":2023,"month":10,"day":10,"ymj":202310,"ymdj":20231010,"provider":"XTB","level":0,"quote":5,"price":{"ask":27490.2,"mid":27457.15,"bid":27424.1},"volume":{"ask":1,"bid":0},"spread":{"raw":66.1,"table":66.1},"_id":"6525d3cd2c0993ea35f40b33"} to 'BITCOIN' successfully
|TIMESTAMP=2023-10-10T22:44:30.013Z|TYPE=ENV|LEVEL=DEBUG|RUNTIME_ID=f39362da-fd8d-4508-91fe-648fcee1aee8|ID=22d58be3-1c48-4877-9476-0d1298ecfac7|METHOD=streamTickPrices
|>> Uploded {"timestamp":"2023-10-10T22:44:29.939Z","year":2023,"month":10,"day":10,"ymj":202310,"ymdj":20231010,"provider":"XTB","level":2,"quote":5,"price":{"ask":27494.4,"mid":27457.6,"bid":27420.8},"volume":{"ask":0,"bid":5},"spread":{"raw":73.6,"table":73.6},"_id":"6525d3cd2c0993ea35f40b35"} to 'BITCOIN' successfully
|TIMESTAMP=2023-10-10T22:44:30.013Z|TYPE=ENV|LEVEL=DEBUG|RUNTIME_ID=f39362da-fd8d-4508-91fe-648fcee1aee8|ID=22d58be3-1c48-4877-9476-0d1298ecfac7|METHOD=streamTickPrices
|>> Uploded {"timestamp":"2023-10-10T22:44:29.939Z","year":2023,"month":10,"day":10,"ymj":202310,"ymdj":20231010,"provider":"XTB","level":3,"quote":5,"price":{"ask":27495.15,"mid":27457.6,"bid":27420.05},"volume":{"ask":1,"bid":10},"spread":{"raw":75.1,"table":75.1},"_id":"6525d3cd2c0993ea35f40b36"} to 'BITCOIN' successfully
|TIMESTAMP=2023-10-10T22:44:30.013Z|TYPE=ENV|LEVEL=DEBUG|RUNTIME_ID=f39362da-fd8d-4508-91fe-648fcee1aee8|ID=22d58be3-1c48-4877-9476-0d1298ecfac7|METHOD=streamTickPrices
|>> Uploded {"timestamp":"2023-10-10T22:44:29.939Z","year":2023,"month":10,"day":10,"ymj":202310,"ymdj":20231010,"provider":"XTB","level":1,"quote":5,"price":{"ask":27492.9,"mid":27457.6,"bid":27422.3},"volume":{"ask":5,"bid":1},"spread":{"raw":70.6,"table":70.6},"_id":"6525d3cd2c0993ea35f40b34"} to 'BITCOIN' successfully
|TIMESTAMP=2023-10-10T22:44:30.014Z|TYPE=ENV|LEVEL=DEBUG|RUNTIME_ID=f39362da-fd8d-4508-91fe-648fcee1aee8|ID=22d58be3-1c48-4877-9476-0d1298ecfac7|METHOD=streamTickPrices
|>> Uploded {"timestamp":"2023-10-10T22:44:29.939Z","year":2023,"month":10,"day":10,"ymj":202310,"ymdj":20231010,"provider":"XTB","level":4,"quote":5,"price":{"ask":27496.15,"mid":27457.6,"bid":27419.05},"volume":{"ask":10,"bid":0},"spread":{"raw":77.1,"table":77.1},"_id":"6525d3cd2c0993ea35f40b37"} to 'BITCOIN' successfully
|TIMESTAMP=2023-10-10T22:44:30.428Z|TYPE=ENV|LEVEL=INFO|RUNTIME_ID=f39362da-fd8d-4508-91fe-648fcee1aee8|ID=f39362da-fd8d-4508-91fe-648fcee1aee8|METHOD=main
|>> Connection status updated to 0
|TIMESTAMP=2023-10-10T22:44:34.587Z|TYPE=ENV|LEVEL=INFO|RUNTIME_ID=f39362da-fd8d-4508-91fe-648fcee1aee8|ID=f39362da-fd8d-4508-91fe-648fcee1aee8|METHOD=main
|>> Connection status updated to 2
peterszombati commented 1 year ago

I cant help in this

peterszombati commented 1 year ago

if you need help in programming message me in private I have a hourly rate and then I can help

IonCimpoiesu commented 1 year ago

No problem, I already implemented a fix, thanks for your quick reply.