Проблема с совместной работой node js и серверной базы данных postgresql

у меня есть программа, встроенная в node js. Цель этой программы - получить информацию из pos-системы кафе через api и отфильтровать ее по нужным параметрам и записать в бд. Затем веб-страница должна вывести отложенные и выполненные ордера. Когда я запускаю эту программу со своего локального компьютера и подключаюсь к базе данных postgresql на своем компьютере, программа работает отлично, но когда я загружаю ее на железнодорожный сервер, то она иногда очень поздно отображает подготовленные и готовые заказы на веб-страницу, а иногда и очень поздно. это даже не показывает. Я впервые создаю такую программу на nodejs. Пожалуйста, просмотрите код и помогите мне исправить его, если есть какие-то неправильные части. Я думаю, что код в целом правильный, но есть небольшие проблемы в коде, который добавляет, удаляет, обновляет новые данные в базе данных postgresql и сортирует заказы на веб-странице, пожалуйста, помогите мне это исправить.

Мой код:

    const express = require('express');
const http = require('http');
const axios = require('axios');
const { Pool } = require('pg');
const { DateTime } = require('luxon');
const { env } = require('process');
const cors = require('cors');

const app = express();
const port = 3000;

app.use(express.static('public'));

// Add cors middleware here
app.use(cors());



// const pool = new Pool({
//   user: 'postgres',
//   host: 'localhost', // Typically 'localhost' or '127.0.0.1' for local development
//   database: 'db',
//   password: 'password',
//   port: 5432,
// });

const pool = new Pool({
  user: 'user here',
  host: 'host here',
  database: 'database here',
  password: 'password here',
  // port: 26243,
});

const apiEndpoint = 'https://joinposter.com/api/dash.getTransactions';
const accessToken = "token_here";
const waitingMinutes = 3;

async function createTableWithRetry() {
  const maxRetries = 3; // Set the maximum number of retries
  let retryCount = 0;

  while (retryCount < maxRetries) {
    const client = await pool.connect();

    try {
      await client.query(`
        CREATE TABLE IF NOT EXISTS orders (
          id BIGSERIAL PRIMARY KEY,
          transaction_id VARCHAR(355) UNIQUE,
          product_id_count INT,
          finishedcooking_count INT,
          is_printed BOOLEAN DEFAULT FALSE,
          finished_at TIMESTAMP DEFAULT NULL,
          created_at TIMESTAMP DEFAULT NOW()
        );
      `);
      // If the operation is successful, break out of the loop
      break;
    } catch (error) {
      // Handle the error gracefully
      if (error.code === 'ENOTFOUND' || error.code === 'EAI_AGAIN') {
        console.error(`Error: Could not resolve hostname. Check your PostgreSQL host configuration.`);
      } else {
        console.error(`Error creating table. Attempt ${retryCount + 1}/${maxRetries}:`, error.message);
        // Retry the operation after a delay
        await new Promise(resolve => setTimeout(resolve, 1000)); // Add a delay (1 second in this example)
      }

      // Increment the retry count
      retryCount++;
    } finally {
      client.release();
    }
  }

  if (retryCount === maxRetries) {
    console.error(`Maximum number of retries reached. Operation failed.`);
  }
}

async function fetchOrders() {
  const client = await pool.connect();

  try {
    const result = await client.query(`
      SELECT * FROM orders
      WHERE NOW() - created_at <= INTERVAL '80 minutes'
      AND NOW() - created_at >= INTERVAL '0 minutes'
      ORDER BY transaction_id DESC;
    `);

    return result.rows;
  } finally {
    client.release();
  }
}

async function fetchData() {
  try {
    const today = DateTime.now().toFormat('yyyyMMdd');
    const url = `${apiEndpoint}?token=${accessToken}&dateFrom=${today}&dateTo=${today}&include_history=true`;
    const response = await axios.get(url, { timeout: 20000 });
    const data = response.data;

    return data;

  } catch (error) {
    console.error('Error fetching data:', error);
    return null;
  }
}

async function insertOrUpdateData(data) {
  const client = await pool.connect();

  try {
    await client.query('BEGIN');

    for (const transaction of data.response) {
      const transactionId = transaction.transaction_id;
      const productIdCount = transaction.history
        .filter((history) => history.type_history === 'sendtokitchen')
        .flatMap((history) => history.value_text)
        .filter((entry) => 'product_id' in entry)
        .length;
      const finishedcookingCount = transaction.history
        .filter((history) => history.type_history === 'finishedcooking')
        .length;

      await client.query(
        `
        INSERT INTO orders (transaction_id, product_id_count, finishedcooking_count)
        VALUES ($1, $2, $3)
        ON CONFLICT (transaction_id) DO UPDATE
        SET product_id_count = $2, finishedcooking_count = $3;
        `,
        [transactionId, productIdCount, finishedcookingCount]
      );
    }

    await client.query('COMMIT');
  } catch (error) {
    await client.query('ROLLBACK');
    console.error('Error inserting/updating data:', error);
  } finally {
    client.release();
  }
}

async function markOrdersPrinted() {
  const client = await pool.connect();

  try {
    await client.query('BEGIN');

    await client.query(`
      UPDATE orders
      SET is_printed = TRUE,
          finished_at = CASE
            WHEN finished_at IS NULL THEN NOW()
            ELSE finished_at
          END
      WHERE product_id_count = finishedcooking_count
      AND product_id_count != 0;
    `);

    await client.query('COMMIT');

  } catch (error) {
    await client.query('ROLLBACK');
    console.error('Error marking orders as printed:', error);
  } finally {
    client.release();
  }
}

async function deleteOldFinishedOrders() {
  const client = await pool.connect();

  try {
    const currentTime = DateTime.now();

    if (currentTime.hour === 4 && currentTime.minute === 10) {
      await client.query('DROP TABLE IF EXISTS orders;');
      console.log("Table 'orders' dropped at 4:10 AM");

      await new Promise(resolve => setTimeout(resolve, 5000));

      await client.query(`
        CREATE TABLE IF NOT EXISTS orders (
          id SERIAL PRIMARY KEY,
          transaction_id VARCHAR(255) UNIQUE,
          product_id_count INT,
          finishedcooking_count INT,
          is_printed BOOLEAN DEFAULT FALSE,
          finished_at TIMESTAMP DEFAULT NULL,
          created_at TIMESTAMP DEFAULT NOW()
        );
      `);
      console.log("Table 'orders' recreated.");
    }
    await new Promise((resolve) => setTimeout(resolve, 1000));

  } catch (error) {
    console.error('Error deleting old finished orders:', error);

  } finally {
    client.release();
  }
}

async function main() {
  while (true) {
    const apiData = await fetchData();

    if (apiData) {
      await insertOrUpdateData(apiData);
      await new Promise((resolve) => setTimeout(resolve, 1000));
      await markOrdersPrinted();
      await new Promise((resolve) => setTimeout(resolve, 1000));
      await deleteOldFinishedOrders();
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }

    await new Promise((resolve) => setTimeout(resolve, 5000));
  }
}

app.get('/', async (req, res) => {
  const orders = await fetchOrders();
  const preparingOrders = orders.filter(
    (order) => order.product_id_count > 0 && order.finishedcooking_count < order.product_id_count
  );
  const readyOrders = orders.filter(
    (order) =>
      order.product_id_count === order.finishedcooking_count &&
      order.product_id_count !== 0 &&
      DateTime.now().diff(DateTime.fromJSDate(order.finished_at), 'minutes').minutes < parseInt(waitingMinutes)
  );

app.get('/fetch_data', async (req, res) => {
  const orders = await fetchOrders(); // Implement fetchOrders function
  res.json({
    preparingOrders: orders.filter(order => order.product_id_count > 0 && order.finishedcooking_count < order.product_id_count),
    readyOrders: orders.filter(order => order.product_id_count === order.finishedcooking_count &&
      order.product_id_count !== 0 &&
      DateTime.now().diff(DateTime.fromJSDate(order.finished_at), 'minutes').minutes < parseInt(waitingMinutes))
  });
});

  const htmlResponse = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Order Status</title>
      <link rel="icon" href="public/awlogo.png" type="image/png">
      <style>
          body {
            margin: 0;
            font-family: Arial, sans-serif;
          }
          .container {
            display: flex;
            margin: 0 auto; /* markazga joylashgan */
            padding: 0px; /* tepa, chap, past va o'ng yonida 20 px ichki padding */
            box-sizing: border-box; /* padding va borderni ichki qismini qo'shadi */
          }
          .yellow-side {
            flex: 1;
            background-color: yellow;
            padding: 0px;
            height: 1000vh;
          }
          .green-side {
            flex: 1;
            background-color: green;
            padding: 0px;
            height: 1000vh;
          }
          ul {
            list-style-type: none;
            padding: 0;
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-start;
            margin-left: 5px;
            margin-right: -44px;
          }

        li {
          background-color: rgba(128, 128, 128, 0.5);
          margin: 7px;
          padding: 0px;
          padding-right: 1px;
          padding-left: 1px;
          border-radius: 99px;
          flex: 1 0 200px;
          max-width: calc(12%);
          text-align: center;
          font-size: 45px;
          font-weight: bold;
          line-height: 0px;
        }

        .bolim{
            text-align: center;
            font-size: 28px;
        }

        .tana {
          width: 1920;
          height: 1080;
        }

    </style>
    </head>
    <body class="tana">
      <div class="container">
        <div class="yellow-side">
          <h1 class="bolim">ГОТОВИТСЯ</h1>
          <ul id="preparingOrdersList">
            ${preparingOrders.map((order) => `<li><p>${order.transaction_id.slice(-2)}</p></li>`).join('')}
          </ul>
        </div>
        <div class="green-side">
          <h1 class="bolim">ГОТОВЫЙ</h1>
          <ul id="readyOrdersList">
            ${readyOrders.map((order) => `<li><p>${order.transaction_id.slice(-2)}</p></li>`).join('')}
          </ul>
        </div>
      </div>
      <script>
      async function fetchDataAndUpdate() {
        try {
          const response = await fetch('/fetch_data');
          if (response.ok) {
            const data = await response.json();
            updateOrdersList(data.preparingOrders, 'preparingOrdersList');
            updateOrdersList(data.readyOrders, 'readyOrdersList');
          }
        } catch (error) {
          console.error('Error fetching data:', error);
        }
      }

        function updateOrdersList(orders, listId) {
          const list = document.getElementById(listId);
          list.innerHTML = orders.map(order => \`<li><h3>\${order.transaction_id.slice(-2)}</h3></li>\`).join('');
        }
        setInterval(fetchDataAndUpdate, 8000);
      </script>
    </body>
    </html>
  `;

  res.send(htmlResponse);
});

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});


(async () => {
  await createTableWithRetry();
  await main();
})();

Вот некоторые ошибки, возникшие в ходе тестирования после загрузки приложения на железнодорожный сервер:

    2024-02-19 21:20:50.698 UTC [8] LOG:  listening on IPv4 address "0.0.0.0", port 5432

2024-02-19 21:20:50.698 UTC [8] LOG:  listening on IPv6 address "::", port 5432

2024-02-19 21:20:50.712 UTC [8] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"

2024-02-19 21:20:50.718 UTC [78] LOG:  database system was shut down at 2024-02-19 21:20:50 UTC

2024-02-19 21:20:50.724 UTC [8] LOG:  database system is ready to accept connections

2024-02-19 21:25:50.815 UTC [76] LOG:  checkpoint starting: time

2024-02-19 21:25:55.047 UTC [76] LOG:  checkpoint complete: wrote 45 buffers (0.3%); 0 WAL file(s) added, 0 removed, 0 recycled; write=4.221 s, sync=0.005 s, total=4.233 s; sync files=12, longest=0.003 s, average=0.001 s; distance=261 kB, estimate=261 kB; lsn=0/1954508, redo lsn=0/19544D0

2024-02-19 21:29:29.138 UTC [105] ERROR:  deadlock detected

2024-02-19 21:29:29.138 UTC [105] DETAIL:  Process 105 waits for ShareLock on transaction 757; blocked by process 119.

Process 119 waits for ShareLock on transaction 755; blocked by process 105.

Process 105:

INSERT INTO orders (transaction_id, product_id_count, finishedcooking_count)

VALUES ($1, $2, $3)

ON CONFLICT (transaction_id) DO UPDATE

Это ошибка в журнале базы данных postgresql в railway:

    2024-02-19 21:35:50.983 UTC [76] LOG:  checkpoint starting: time

2024-02-19 21:35:52.503 UTC [76] LOG:  checkpoint complete: wrote 16 buffers (0.1%); 0 WAL file(s) added, 0 removed, 0 recycled; write=1.506 s, sync=0.003 s, total=1.521 s; sync files=10, longest=0.003 s, average=0.001 s; distance=508 kB, estimate=508 kB; lsn=0/1A334A8, redo lsn=0/1A33470

2024-02-19 21:40:50.603 UTC [76] LOG:  checkpoint starting: time

2024-02-19 21:40:51.717 UTC [76] LOG:  checkpoint complete: wrote 12 buffers (0.1%); 0 WAL file(s) added, 0 removed, 0 recycled; write=1.105 s, sync=0.004 s, total=1.115 s; sync files=7, longest=0.003 s, average=0.001 s; distance=244 kB, estimate=482 kB; lsn=0/1A70838, redo lsn=0/1A707F8

2024-02-19 21:45:50.817 UTC [76] LOG:  checkpoint starting: time

2024-02-19 21:45:51.731 UTC [76] LOG:  checkpoint complete: wrote 10 buffers (0.1%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.904 s, sync=0.003 s, total=0.914 s; sync files=6, longest=0.003 s, average=0.001 s; distance=25 kB, estimate=436 kB; lsn=0/1A76DE0, redo lsn=0/1A76D98

2024-02-19 21:55:16.358 UTC [244] LOG:  unexpected EOF on client connection with an open transaction

2024-02-19 21:55:16.358 UTC [119] LOG:  unexpected EOF on client connection with an open transaction

2024-02-19 21:55:16.368 UTC [302] LOG:  unexpected EOF on client connection with an open transaction

Когда программа работает правильно, она должна отображаться вот так, но иногда она вообще не отображается.

Когда программа работает правильно, она должна отображаться вот так ?, но иногда она вообще не отображается.

Я думал, что причина сбоя программы в времени функций, работающих с базой данных postgresql, и всячески пытался изменить их время, но не получилось.

Я думаю, проблема в этой части кода:

async function main() {
  while (true) {
    const apiData = await fetchData();

    if (apiData) {
      await insertOrUpdateData(apiData);
      await new Promise((resolve) => setTimeout(resolve, 1000));
      await markOrdersPrinted();
      await new Promise((resolve) => setTimeout(resolve, 1000));
      await deleteOldFinishedOrders();
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }

    await new Promise((resolve) => setTimeout(resolve, 5000));
  }
}

Ответы (0 шт):