diff --git a/backend/db/schema/printers.schema.ts b/backend/db/schema/printers.schema.ts new file mode 100644 index 0000000..406e498 --- /dev/null +++ b/backend/db/schema/printers.schema.ts @@ -0,0 +1,44 @@ +import { + boolean, + integer, + jsonb, + pgTable, + text, + timestamp, + uniqueIndex, + uuid, +} from "drizzle-orm/pg-core"; +import { createInsertSchema, createSelectSchema } from "drizzle-zod"; +import type z from "zod"; + +export const printerData = pgTable( + "printer_data", + { + id: uuid("id").defaultRandom().primaryKey(), + humanReadableId: text("humanReadable_id").unique().notNull(), + name: text("name").notNull(), + ipAddress: text("ipAddress"), + port: integer("port"), + status: text("status"), + statusText: text("statusText"), + printerSN: text("printer_sn"), + lastTimePrinted: timestamp("last_time_printed").notNull().defaultNow(), + assigned: boolean("assigned").default(false), + remark: text("remark"), + printDelay: integer("printDelay").default(90), + processes: jsonb("processes").default([]), + printDelayOverride: boolean("print_delay_override").default(false), // this will be more for if we have the lot time active but want to over ride this single line for some reason + add_Date: timestamp("add_Date").defaultNow(), + upd_date: timestamp("upd_date").defaultNow(), + }, + (table) => [ + //uniqueIndex("emailUniqueIndex").on(sql`lower(${table.email})`), + uniqueIndex("printer_id").on(table.humanReadableId), + ], +); + +export const printerSchema = createSelectSchema(printerData); +export const newPrinterSchema = createInsertSchema(printerData); + +export type Printer = z.infer; +export type NewPrinter = z.infer; diff --git a/backend/gpSql/gpSqlConnection.controller.ts b/backend/gpSql/gpSqlConnection.controller.ts index 3ee01be..2396d6b 100644 --- a/backend/gpSql/gpSqlConnection.controller.ts +++ b/backend/gpSql/gpSqlConnection.controller.ts @@ -7,12 +7,17 @@ import { returnFunc } from "../utils/returnHelper.utils.js"; export let pool2: sql.ConnectionPool; export let connected: boolean = false; export let reconnecting = false; +// start the delay out as 2 seconds +let delayStart = 2000; +let attempt = 0; +const maxAttempts = 10; export const connectGPSql = async () => { const serverUp = await checkHostnamePort(`USMCD1VMS011:1433`); if (!serverUp) { // we will try to reconnect connected = false; + reconnectToSql; return returnFunc({ success: false, level: "error", @@ -48,6 +53,7 @@ export const connectGPSql = async () => { notify: false, }); } catch (error) { + reconnectToSql; return returnFunc({ success: false, level: "error", @@ -104,11 +110,6 @@ export const reconnectToSql = async () => { //set reconnecting to true while we try to reconnect reconnecting = true; - // start the delay out as 2 seconds - let delayStart = 2000; - let attempt = 0; - const maxAttempts = 10; - while (!connected && attempt < maxAttempts) { attempt++; log.info( @@ -121,7 +122,7 @@ export const reconnectToSql = async () => { if (!serverUp) { delayStart = Math.min(delayStart * 2, 30000); // exponential backoff until up to 30000 - return; + continue; } try { @@ -131,19 +132,11 @@ export const reconnectToSql = async () => { log.info(`${gpSqlConfig.server} is connected to ${gpSqlConfig.database}`); } catch (error) { delayStart = Math.min(delayStart * 2, 30000); - return returnFunc({ - success: false, - level: "error", - module: "system", - subModule: "db", - message: "Failed to reconnect to the prod sql server.", - data: [error], - notify: false, - }); + log.error({ error }, "Failed to reconnect to the prod sql server."); } } - if (!connected) { + if (!connected && attempt >= maxAttempts) { log.error( { notify: true }, "Max reconnect attempts reached on the prodSql server. Stopping retries.", diff --git a/backend/gpSql/gpSqlQuery.controller.ts b/backend/gpSql/gpSqlQuery.controller.ts index f8509db..7ee204e 100644 --- a/backend/gpSql/gpSqlQuery.controller.ts +++ b/backend/gpSql/gpSqlQuery.controller.ts @@ -1,10 +1,5 @@ import { returnFunc } from "../utils/returnHelper.utils.js"; -import { - connected, - pool2, - reconnecting, - reconnectToSql, -} from "./gpSqlConnection.controller.js"; +import { connected, pool2 } from "./gpSqlConnection.controller.js"; interface SqlError extends Error { code?: string; @@ -22,29 +17,15 @@ interface SqlError extends Error { */ export const gpQuery = async (queryToRun: string, name: string) => { if (!connected) { - reconnectToSql(); - - if (reconnecting) { - return returnFunc({ - success: false, - level: "error", - module: "system", - subModule: "gpSql", - message: `The sql ${process.env.PROD_PLANT_TOKEN} is trying to reconnect already`, - data: [], - notify: false, - }); - } else { - return returnFunc({ - success: false, - level: "error", - module: "system", - subModule: "gpSql", - message: `${process.env.PROD_PLANT_TOKEN} is not connected, and failed to connect.`, - data: [], - notify: true, - }); - } + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "gpSql", + message: `${process.env.PROD_PLANT_TOKEN} is offline or attempting to reconnect`, + data: [], + notify: false, + }); } //change to the correct server diff --git a/backend/prodSql/prodSqlConnection.controller.ts b/backend/prodSql/prodSqlConnection.controller.ts index f93182f..57e2bde 100644 --- a/backend/prodSql/prodSqlConnection.controller.ts +++ b/backend/prodSql/prodSqlConnection.controller.ts @@ -7,12 +7,17 @@ import { returnFunc } from "../utils/returnHelper.utils.js"; export let pool: sql.ConnectionPool; export let connected: boolean = false; export let reconnecting = false; +// start the delay out as 2 seconds +let delayStart = 2000; +let attempt = 0; +const maxAttempts = 10; export const connectProdSql = async () => { const serverUp = await checkHostnamePort(`${process.env.PROD_SERVER}:1433`); if (!serverUp) { // we will try to reconnect connected = false; + reconnectToSql(); return returnFunc({ success: false, level: "error", @@ -48,6 +53,7 @@ export const connectProdSql = async () => { notify: false, }); } catch (error) { + reconnectToSql(); return returnFunc({ success: false, level: "error", @@ -104,11 +110,6 @@ export const reconnectToSql = async () => { //set reconnecting to true while we try to reconnect reconnecting = true; - // start the delay out as 2 seconds - let delayStart = 2000; - let attempt = 0; - const maxAttempts = 10; - while (!connected && attempt < maxAttempts) { attempt++; log.info( @@ -121,7 +122,7 @@ export const reconnectToSql = async () => { if (!serverUp) { delayStart = Math.min(delayStart * 2, 30000); // exponential backoff until up to 30000 - return; + continue; } try { @@ -133,19 +134,12 @@ export const reconnectToSql = async () => { ); } catch (error) { delayStart = Math.min(delayStart * 2, 30000); - return returnFunc({ - success: false, - level: "error", - module: "system", - subModule: "db", - message: "Failed to reconnect to the prod sql server.", - data: [error], - notify: false, - }); + delayStart = Math.min(delayStart * 2, 30000); + log.error({ error }, "Failed to reconnect to the prod sql server."); } } - if (!connected) { + if (!connected && attempt >= maxAttempts) { log.error( { notify: true }, "Max reconnect attempts reached on the prodSql server. Stopping retries.", diff --git a/backend/prodSql/prodSqlQuery.controller.ts b/backend/prodSql/prodSqlQuery.controller.ts index fb492ae..46e76b2 100644 --- a/backend/prodSql/prodSqlQuery.controller.ts +++ b/backend/prodSql/prodSqlQuery.controller.ts @@ -1,10 +1,5 @@ import { returnFunc } from "../utils/returnHelper.utils.js"; -import { - connected, - pool, - reconnecting, - reconnectToSql, -} from "./prodSqlConnection.controller.js"; +import { connected, pool } from "./prodSqlConnection.controller.js"; interface SqlError extends Error { code?: string; @@ -22,29 +17,15 @@ interface SqlError extends Error { */ export const prodQuery = async (queryToRun: string, name: string) => { if (!connected) { - reconnectToSql(); - - if (reconnecting) { - return returnFunc({ - success: false, - level: "error", - module: "system", - subModule: "prodSql", - message: `The sql ${process.env.PROD_PLANT_TOKEN} is trying to reconnect already`, - data: [], - notify: false, - }); - } else { - return returnFunc({ - success: false, - level: "error", - module: "system", - subModule: "prodSql", - message: `${process.env.PROD_PLANT_TOKEN} is not connected, and failed to connect.`, - data: [], - notify: true, - }); - } + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "prodSql", + message: `${process.env.PROD_PLANT_TOKEN} is offline or attempting to reconnect`, + data: [], + notify: false, + }); } //change to the correct server diff --git a/backend/utils/prodEndpoint.utils.ts b/backend/utils/prodEndpoint.utils.ts new file mode 100644 index 0000000..e082a0b --- /dev/null +++ b/backend/utils/prodEndpoint.utils.ts @@ -0,0 +1,124 @@ +import https from "node:https"; +import axios from "axios"; +import { returnFunc } from "./returnHelper.utils.js"; +import { tryCatch } from "./trycatch.utils.js"; + +type bodyData = any; + +type Data = { + endpoint: string; + data?: bodyData[]; + method: "post" | "get" | "delete" | "patch"; +}; + +// type ApiResponse = { +// status: number; +// statusText: string; +// data: T; +// }; + +// create the test server stuff +const testServers = [ + { token: "test1", port: 8940 }, + { token: "test2", port: 8941 }, + { token: "test3", port: 8942 }, +]; + +const agent = new https.Agent({ + rejectUnauthorized: false, +}); + +export const prodEndpointCreation = async (endpoint: string) => { + let url = ""; + //get the plant token + const plantToken = process.env.PROD_PLANT_TOKEN ?? "test1"; + + // check if we are a test server + const testServer = testServers.some((server) => server.token === plantToken); + + // await db + // .select() + // .from(settings) + // .where(eq(settings.name, "dbServer")); + + if (testServer) { + //filter out what testserver we are + const test = testServers.filter((t) => t.token === plantToken); + // "https://usmcd1vms036.alpla.net:8942/application/public/v1.0/DemandManagement/ORDERS" + url = `https://${process.env.PROD_SERVER}.alpla.net:${test[0]?.port}/application${endpoint}`; + return url; + } else { + url = `https://${plantToken}prod.alpla.net/application${endpoint}`; + return url; + } +}; + +/** + * + * @param data + * @param timeoutDelay + * @returns + */ +export const runProdApi = async (data: Data) => { + const url = await prodEndpointCreation(data.endpoint); + + const { data: d, error } = await tryCatch( + axios({ + method: data.method as string, + url, + data: data.data ? data.data[0] : undefined, + headers: { + "X-API-Key": process.env.TEC_API_KEY || "", + "Content-Type": "application/json", + }, + validateStatus: () => true, + httpsAgent: agent, + }), + ); + + switch (d?.status) { + case 200: + return returnFunc({ + success: true, + level: "info", + module: "utils", + subModule: "prodEndpoint", + message: "Data from prod endpoint", + data: d.data, + notify: false, + }); + + case 401: + return returnFunc({ + success: false, + level: "error", + module: "utils", + subModule: "prodEndpoint", + message: "Data from prod endpoint", + data: d.data, + notify: false, + }); + case 400: + return returnFunc({ + success: false, + level: "error", + module: "utils", + subModule: "prodEndpoint", + message: "Data from prod endpoint", + data: d.data, + notify: false, + }); + } + + if (error) { + return returnFunc({ + success: true, + level: "error", + module: "utils", + subModule: "prodEndpoint", + message: "Failed to get data from the prod endpoint", + data: error as any, + notify: true, + }); + } +}; diff --git a/brunoApi/environments/lstv3.bru b/brunoApi/environments/lstv3.bru index b05fb6c..671cac1 100644 --- a/brunoApi/environments/lstv3.bru +++ b/brunoApi/environments/lstv3.bru @@ -1,5 +1,5 @@ vars { - url: http://localhost:3000/lst + url: http://uslim1vms006:3100/lst readerIp: 10.44.14.215 } vars:secret [