What is the recommended way to handle data upon retrieval from a Trino database?

My goal is to retrieve data from a Trino database. Upon sending my initial query to the database, I receive a NextURI. Subsequently, in a while loop, I check the NextURI to obtain portions of the data until the Trino connection completes sending the entire dataset.

The problem arises when I receive no data and am stuck in an infinite loop of receiving NextURIs.

The code snippet below outlines this process, mentioning that it commences with acquiring an authentication token for Trino.


app.get("/getOpenskyData", async (req: Request, res: Response) => {
  var startTime = new Date().getTime();
  console.log("Server | getHistoricalADSBData | Called");
  try {
    const startTimeEPOCHMS = Number(req.query.startTimeEPOCHMS);
    const endTimeEPOCHMS = Number(req.query.endTimeEPOCHMS);

    interface TokenPayload {
      access_token: string;
      exp: number;
    }

    // Get the token from OpenSky Network
    const result = await axios.post(
      "https://auth.opensky-network.org/auth/realms/opensky-network/protocol/openid-connect/token",
      new URLSearchParams({
        client_id: "trino-client",
        grant_type: "password",
        username: process.env.OPENSKY_USERNAME + "",
        password: process.env.OPENSKY_PASSWORD + ""
      }).toString(),
      {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        }
      }
    );

    const payload = result.data;
    const decoded: TokenPayload = jwtDecode(payload.access_token);

    // Ensure the token has an exp property
    if (!decoded.exp) {
      throw new Error("Token does not have an expiration time");
    }

    console.log("Server | getHistoricalADSBData | Got Token");

    const queryString = `SELECT * FROM minio.osky.state_vectors_data4 WHERE time BETWEEN ${startTimeEPOCHMS / 1000} AND ${endTimeEPOCHMS / 1000}`;

    // Execute the query on Trino
    const response = await axios.post(
      'https://trino.opensky-network.org/v1/statement',
      queryString,
      {
        headers: {
          Authorization: `Bearer ${payload.access_token}`,
          'Content-Type': 'text/plain',
          'X-Trino-Buffer': 'true',
        },
      }
    );

    if (response && response.status === 200) {
      const body = response.data;
      const results: any[] = [];

      let nextUri = body.nextUri; // Initialize nextUri

      // Loop to handle pagination
      while (nextUri) {
        const fetchResponse = await axios.get(nextUri, {
          headers: {
            Authorization: `Bearer ${payload.access_token}`,
          },
        });

        if (fetchResponse && fetchResponse.status === 200) {
          const fetchBody = fetchResponse.data;

          if (fetchBody.data && fetchBody.data.length > 0) {
            results.push(...fetchBody.columns); // Push data to results array
          }

          console.log(fetchBody.columns)

          nextUri = fetchBody.nextUri; // Update nextUri
          console.log(fetchBody.nextUri)
        } else {
          throw new Error('Unokay response whilst fetching data from OpenSky');
        }
      }

      console.log("Server | getHistoricalADSBData | Results:", results);
      res.status(200).json(results);
    } else {
      throw new Error('Unokay response whilst querying OpenSky');
    }

    console.log("Server | getHistoricalADSBData | Took " + (new Date().getTime() - startTime) + " ms");
  } catch (error) {
    console.error('Server | getHistoricalADSBData | Error of: ', (error as unknown as Error).message);
    return res.status(500).json({ message: 'Internal server error while fetching historical ADSB.' });
  }
});

Upon printing the fetchResponse.columns field, the output shows an array missing crucial data, only containing a single ICAO24 value. The expected output should consist of hundreds of thousands of data pieces, given that it should retrieve global ADSB data for one second.

[
  {
    name: 'time',
    type: 'integer',
    typeSignature: { rawType: 'integer', arguments: [] }
  },
  {
    name: 'icao24',
    type: 'varchar',
    typeSignature: { rawType: 'varchar', arguments: [Array] }
  },
  ...
]

The NextURI appears as:

https://trino.opensky-network.org/v1/statement/executing/20240619_210740_88003_jtdt5/y2e8bb6c86212fff8d50ab161a4300917292bc401/278

After 278 NextURIs (equivalent to 278 seconds of processing), I am still unable to retrieve any data.

I have searched but found no relevant documentation on how Trino formats data when sending it or how to parse this data in JavaScript.

The query should not take 278 seconds to complete or return no data.

How can I correctly process Trino data in Typescript?

Edit: Here is the JSON.stringify of the response:

Fetched data: {
  ...
  <details of the fetched data>
  ...
}

After running for 20 minutes, no output rows are retrieved.

https://i.sstatic.net/4aT57eDL.png

Answer №1

Please give this code a shot:

app.get("/fetchOpenskyData", async (req: Request, res: Response) => {
  const start = new Date().getTime();
  console.log("Server | gatherHistoricalADSBData | Invoked");
  try {
    const startEpoch = Number(req.query.startEpoch);
    const endEpoch = Number(req.query.endEpoch);

    interface TokenPayload {
      access_token: string;
      exp: number;
    }

    // Request token from OpenSky Network
    const result = await axios.post(
      "https://auth.opensky-network.org/auth/realms/opensky-network/protocol/openid-connect/token",
      new URLSearchParams({
        client_id: "trino-client",
        grant_type: "password",
        username: process.env.OPENSKY_USERNAME + "",
        password: process.env.OPENSKY_PASSWORD + ""
      }).toString(),
      {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        }
      }
    );

    const payload = result.data;
    const decoded: TokenPayload = jwtDecode(payload.access_token);

    // Confirm token has exp property
    if (!decoded.exp) {
      throw new Error("Token lacks expiration time");
    }

    console.log("Server | gatherHistoricalADSBData | Received Token");

    const queryStr = `SELECT * FROM minio.osky.state_vectors_data4 WHERE time BETWEEN ${startEpoch / 1000} AND ${endEpoch / 1000}`;

    // Execute query on Trino
    const response = await axios.post(
      'https://trino.opensky-network.org/v1/statement',
      queryStr,
      {
        headers: {
          Authorization: `Bearer ${payload.access_token}`,
          'Content-Type': 'text/plain',
          'X-Trino-Buffer': 'true',
        },
      }
    );

    if (response && response.status === 200) {
      const body = response.data;
      const results: any[] = [];

      let nextUri = body.nextUri; // Initiate nextUri

      // Handle pagination loop
      while (nextUri) {
        const fetchResponse = await axios.get(nextUri, {
          headers: {
            Authorization: `Bearer ${payload.access_token}`,
          },
        });

        if (fetchResponse && fetchResponse.status === 200) {
          const fetchBody = fetchResponse.data;

          // Verify data existence and non-emptiness
          if (fetchBody.data && fetchBody.data.length > 0) {
            results.push(...fetchBody.data); // Push data to results array
          }

          console.log('Retrieved data: ', fetchBody.data); // Log fetched data

          nextUri = fetchBody.nextUri; // Update nextUri
          console.log('Next URI: ', nextUri); // Log next URI
        } else {
          throw new Error('Problematic response during data retrieval from OpenSky');
        }
      }

      console.log("Server | gatherHistoricalADSBData | Results:", results);
      res.status(200).json(results);
    } else {
      throw new Error('Problematic response during OpenSky query');
    }

    console.log("Server | gatherHistoricalADSBData | Duration: " + (new Date().getTime() - start) + " ms");
  } catch (error) {
    console.error('Server | gatherHistoricalADSBData | Issue: ', (error as unknown as Error).message);
    return res.status(500).json({ message: 'Server error while fetching historical ADSB.' });
  }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What might be the reason why the custom markers on the HERE map are not displaying in Angular?

I'm having trouble displaying custom icons on HERE maps. Despite not receiving any errors, the icons are not showing up as expected. I have created a demo at the following link for reference: https://stackblitz.com/edit/angular-ivy-zp8fy5?file=src%2Fa ...

Reconfigure an ancestral item into a designated key

I have a single object with an array of roles inside, and I need to transform the roles into an array of objects. See example below: Current Object: displayConfiguration: { widgetList: { widgetName: 'widget title', entityType: 'As ...

Mastering Typescript Inversify: The Ultimate Guide to Binding Interfaces with Type Parameters

I am trying to figure out how to bind an interface with a type parameter, but I am unsure of the correct way to do it. Here is the Interface: ... export interface ITestHelper<Entity extends ObjectLiteral> { doSomething(builder: SelectQueryBuilder& ...

Creating valuable properties in TypeScript is a skill that requires knowledge and practice

In TypeScript, there is a unique feature available for defining properties with values using the `value` keyword. class Test { constructor(private value: number = 123) { } public MyValueProperty: number = 5; } Here is how you can define such ...

"Capture input value changes and display the previous value when submitting a post. See an example of

Hi there! I'm facing 2 issues with my code, you can find a DEMO here When adding a product to the sale form, the input field for `description` changes for all products. Changing the input product in the sale does not reflect the change. I have shar ...

Does Apollo Federation provide support for a code-first development approach?

I have declarations using 'code-first' approach in my project, but now I want to utilize them as microservices. How can I separate my 'typeDefs' and 'resolvers' following Apollo's 'schema-first' methodology? Is ...

Setting a value in Ionic 3 HTML template

Attempting to assign a value in an Ionic 3 template from the ts file while also adding css properties but encountered an issue. PROBLEM Error: Uncaught (in promise): Error: No value accessor for form control with name: 'image' Error: No va ...

What is the best way to iterate over JSON data from an endpoint that contains multiple nested arrays using the .map() method?

Seeking to showcase weather API data from: () import Image from "next/image" interface Hour { time_epoch: number time: string temp_c: number temp_f: number is_day: number wind_mph: number wind_kph: number wind_deg ...

Screen multiple designs

Imagine I have three models that I need to return as JSON: Car: id, name, age, color, brand, created_at Bike: id, name, size, tire, created_at Bus: id, ps, consumption created_at I am looking to sort these three models by created at: ( ...

Retrieve exclusively the entries that have been verified against a reference index

I'm running into a slight issue with MySQL that I can't seem to solve on my own. While I can accomplish what I need using PHP and multiple queries, I believe there must be a way to achieve the same result with just one query :) Let me explain th ...

Create type declarations using the Typescript compiler by running the command:

After generating my definition file ".d.ts" using tsc --declaration or setting declaration as true in the tsconfig.json, I noticed that the generated files are missing declare module "mymodule" {... } This appears to be causing issues with "tslint" which ...

Creating a web application with a RESTful API

Currently, I am developing a web application using node.js and express along with a Restful API. For individuals to access my web application, they must first log in. Failure to do so will result in them being redirected back to the login page. I recentl ...

Utilizing RavenDB with NodeJS to fetch associated documents and generate a nested outcome within a query

My index is returning data in the following format: Company_All { name : string; id : string; agentDocumentId : string } I am wondering if it's possible to load the related agent document and then construct a nested result using selectFie ...

Tips for creating a console.log wrapper specifically designed for Angular2 using Typescript

Is there a way to create a custom global logging function in Angular 2 TypeScript project that can be used instead of console.log for services and components? I envision the function looking like this: mylogger.ts function mylogger(msg){ console.log ...

Merging Date Columns with Aggregation and Concatenation

I am working with two tables that contain data on actual invoices and budget numbers. Both tables have a date column, but the budget date column extends through the end of the year. My current aggregate query only displays sales and budget numbers up to ...

Vue 4 and TypeScript: Dealing with the error message 'No overload matches this call'

In my Vue-Router 4 setup, I am trying to combine multiple file.ts files with the main vue-router (index.ts) using TypeScript. However, it throws an error that says "TS2769: No overload matches this call. Overload 1 of 2, '(...items: ConcatArray[]): ne ...

A guide on how to identify the return type of a callback function in TypeScript

Looking at this function I've created function computedLastOf<T>(cb: () => T[]) : Readonly<Ref<T | undefined>> { return computed(() => { const collection = cb(); return collection[collection.length - 1]; }); } Thi ...

TS-2304 Error - 'Iterable' not found in TypeScript when trying to import 'jquery' into a '.ts' file

Currently, I am utilizing TypeScript version 2.4 in Visual Studio Code for development. My approach involved installing jQuery via NPM using the given command: npm install --save @types/jquery Subsequently, I obtained the source code for the jquery modul ...

The LinkedIn API encountered an error when attempting to retrieve historical follower data, resulting in a HTTP

I've scoured the depths of the internet in search of a solution to my problem, but none seem to fit what I need. My goal is to retrieve historical follower data from LinkedIn's API using this call: ${companyId}/historical-follow-statistics?time- ...

I am curious about the types of props for the methods within the 'components' object in react-markdown

Having some trouble using 'react-markdown' in NextJs 13 with typescript. TypeScript is showing errors related to the props of the 'code' method, and after searching online, I found a solution that involves importing 'CodeProps&apos ...