Skip to content

Commit

Permalink
removed multithreading for the sake of my own sanity rn
Browse files Browse the repository at this point in the history
  • Loading branch information
LordFarquaadtheCreator committed Jun 25, 2024
1 parent 34fbe46 commit 7db7839
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 166 deletions.
1 change: 1 addition & 0 deletions database/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import client from './db.config';
// if no connection can be made, return null
const getDB = async () => {
console.log("Connecting to Database ...");
if(client._connected) return client;
try{
await client.connect()
console.log("Connected to Database");
Expand Down
23 changes: 11 additions & 12 deletions database/dbCheck.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
import getDB from "./db";
import client from "./db.config";

async function getDB() {
await client.connect();
}

function runWithTimeout(fn: () => void, timeout: number, interval: number = 100) {
return new Promise<void>((resolve, reject) => {
const startTime = Date.now();

fn();

const handle = setInterval(() => {
const elapsedTime = Date.now() - startTime;

if (elapsedTime >= timeout) {
clearInterval(handle);
resolve();
} else {
try {
fn();
} catch (error) {
clearInterval(handle);
reject(error);
}
// } else {
// try {
// fn();
// } catch (error) {
// clearInterval(handle);
// reject(error);
// }
}
}, interval);
});
Expand All @@ -30,4 +29,4 @@ function runWithTimeout(fn: () => void, timeout: number, interval: number = 100)
const args: string[] = process.argv;
const timeout: number = parseInt(args[2]);

await runWithTimeout(getDB, timeout);
await runWithTimeout(getDB, timeout);
37 changes: 8 additions & 29 deletions database/dbChecker.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,13 @@
import { spawn } from "child_process";
import getDB from "./db";

export function secondsToMs(d: number) {
return d * 1000;
}

// threading should happen at top level of server "setInterval"
async function checkDB(TIMEOUT: number): Promise<boolean> {
return new Promise((resolve, reject) => {
let dbAval: boolean = false;

const database = spawn("bun", ["dbCheck.ts", TIMEOUT.toString()]);

database.stdout.on("data", (data) => {
console.log("Output from dbCheck.ts:", data.toString());
});

database.on("exit", (code) => {
if (code === 0) {
dbAval = true;
} else {
dbAval = false;
}
resolve(dbAval);
});
async function checkDB(){
const db = await getDB();

database.on("error", (error) => {
console.error(error);
reject(error);
});
});
if(db) {
await db.end();
return true;
}
return false;
}

export default checkDB;
4 changes: 2 additions & 2 deletions middlewares/authorize.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { queryDatabase } from "routes/databaseFunctions";
import { Client } from "pg";

const authorize = function (client: Client) {
const authorize = function () {
return async (req: any, res: any, next: any) => {
const name = req.headers.name.toLowerCase();
const key = req.headers.authorization?.split(" ")[1];
Expand All @@ -15,7 +15,7 @@ const authorize = function (client: Client) {
}

try {
const result = await queryDatabase(client, query.text, query.values);
const result = await queryDatabase(req.client, query.text, query.values);
if (result.rows.length === 0) {
return res.status(401).json({ message: "Invalid name or key!" });
}
Expand Down
223 changes: 108 additions & 115 deletions routes/projectsDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,130 +7,123 @@ import validate from "../middlewares/validate";
import getDB from "../database/db";
import synchronizeLocal from "../utils/synchronize";
import authorize from "middlewares/authorize";
import connectDB from "middlewares/connectDB";

const router: Router = Router();

router.use(express.json());

async function startServer() {
const client: Client = await getDB();

router.use((req: any, res: any, next: any) => {
logger.info(`Received ${req.url} request for database projects`);
next();
});

router.get("/", async (req: any, res: any) => {
try {
return res.status(200).json({ message: "API is operational." });
} catch (err: any) {
return res.status(500).json({ message: err.message });
}
});

router.get("/get", async (req: any, res: any) => {
let baseQuery = "SELECT * FROM projects";
const filters: string[] = [];
const values: (string | number)[] = [];
router.use(connectDB);

// if the name filter was provided
if (req.query.name) {
filters.push(`name ILIKE $${filters.length + 1}`);
values.push(`%${req.query.name}%`);
}

// if the cohort filter was provided
if (req.query.cohort) {
filters.push(`cohort ILIKE $${filters.length + 1}`);
values.push(`%${req.query.cohort}%`);
}
// if the team filter was provided
if (req.query.team) {
filters.push(`team ILIKE $${filters.length + 1}`);
values.push(`%${req.query.team}%`);
}

// combine all the filters into a single query
if (filters.length > 0) {
baseQuery += " WHERE " + filters.join(" AND ");
}

// execute the query, making sure to provide the values for the filters
try {
const data: QueryResult = await queryDatabase(
client,
baseQuery,
values,
);
return res.status(200).send(data.rows);
} catch {
return res.status(500).json({ message: "Error retrieving data" });
}
});

router.post("/add", authorize(client), validate, async (req: any, res: any) => {
router.use((req: any, res: any, next: any) => {
logger.info(`Received ${req.url} request for database projects`);
next();
});

router.get("/", async (req: any, res: any) => {
try {
return res.status(200).json({ message: "API is operational." });
} catch (err: any) {
return res.status(500).json({ message: err.message });
}
});

router.get("/get", async (req: any, res: any) => {
let baseQuery = "SELECT * FROM projects";
const filters: string[] = [];
const values: (string | number)[] = [];

// if the name filter was provided
if (req.query.name) {
filters.push(`name ILIKE $${filters.length + 1}`);
values.push(`%${req.query.name}%`);
}

// if the cohort filter was provided
if (req.query.cohort) {
filters.push(`cohort ILIKE $${filters.length + 1}`);
values.push(`%${req.query.cohort}%`);
}
// if the team filter was provided
if (req.query.team) {
filters.push(`team ILIKE $${filters.length + 1}`);
values.push(`%${req.query.team}%`);
}

// combine all the filters into a single query
if (filters.length > 0) {
baseQuery += " WHERE " + filters.join(" AND ");
}

// execute the query, making sure to provide the values for the filters
try {
const data: QueryResult = await queryDatabase(
req.client,
baseQuery,
values,
);
return res.status(200).send(data.rows);
} catch {
return res.status(500).json({ message: "Error retrieving data" });
}
});

router.post("/add", authorize(), validate, async (req: any, res: any) => {
const values: Array<any> = Object.values(req.body);
const query = `
INSERT INTO projects (name, "short-desc", "long-desc", team, link, image, "tech-stack", cohort, topic)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`;
try {
const values: Array<any> = Object.values(req.body);
const query = `
INSERT INTO projects (name, "short-desc", "long-desc", team, link, image, "tech-stack", cohort, topic)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`;
try {
const values: Array<any> = Object.values(req.body);
await queryDatabase(client, query, values);
await synchronizeLocal(client);
return res.status(200).json({ message: "Project added successfully" });
} catch (err: any) {
return res.status(400).json({ message: err.message });
}
await queryDatabase(req.client, query, values);
await synchronizeLocal(req.client);
return res.status(200).json({ message: "Project added successfully" });
} catch (err: any) {
return res.status(400).json({ message: err.message });
}
});

router.put("/update", authorize(), validate, async (req: any, res: any) => {
const projectName = req.query.name;

if (!projectName) {
return res.status(400).json({ message: "Project name is required" });
}

const fields = req.body;
if (!fields || Object.keys(fields).length === 0) {
return res
.status(400)
.json({ message: "No fields to update provided" });
}

const setClauses: string[] = [];
const values: (string | number)[] = [];

// Construct the set clauses and values array
Object.keys(fields).forEach((key, index) => {
setClauses.push(`"${key}" = $${index + 1}`);
values.push(fields[key]);
});

router.put("/update", authorize(client), validate, async (req: any, res: any) => {
const projectName = req.query.name;

if (!projectName) {
return res.status(400).json({ message: "Project name is required" });
}

const fields = req.body;
if (!fields || Object.keys(fields).length === 0) {
return res
.status(400)
.json({ message: "No fields to update provided" });
}

const setClauses: string[] = [];
const values: (string | number)[] = [];

// Construct the set clauses and values array
Object.keys(fields).forEach((key, index) => {
setClauses.push(`"${key}" = $${index + 1}`);
values.push(fields[key]);
});

// Add the project name to the values array for the WHERE clause
values.push(projectName);

const query = `
UPDATE projects
SET ${setClauses.join(", ")}
WHERE name = $${values.length}`;
try {
const result = await queryDatabase(client, query, values);
await synchronizeLocal(client);

if (result.rowCount === 0) {
return res.status(404).json({ message: "Project not found" });
}

return res.status(200).send("Project updated successfully");
} catch (err: any) {
return res.status(400).json({ message: err.message });

// Add the project name to the values array for the WHERE clause
values.push(projectName);

const query = `
UPDATE projects
SET ${setClauses.join(", ")}
WHERE name = $${values.length}`;
try {
const result = await queryDatabase(req.client, query, values);
await synchronizeLocal(req.client);

if (result.rowCount === 0) {
return res.status(404).json({ message: "Project not found" });
}
});
}

startServer().catch((err) => {
logger.error(err);
console.log("Failed to start server");
return res.status(200).send("Project updated successfully");
} catch (err: any) {
return res.status(400).json({ message: err.message });
}
});

export default router;
16 changes: 8 additions & 8 deletions server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import logger from "./utils/logger";
import projectsLocal from "./routes/projectsLocal";
import projectsDB from "./routes/projectsDB";
import express from "express";
import checkDB, { secondsToMs } from "./database/dbChecker";
import checkDB from "./database/dbChecker";
import cors from "cors";
import http from 'http';
import https from 'https';
Expand All @@ -13,17 +13,17 @@ import fs from 'fs';
// const credentials = {key: privateKey, cert: certificate};

const PORT = 3000;
const INTERVAL = secondsToMs(60 * 60); // 1 hr
const TIMEOUT = secondsToMs(10);
// const INTERVAL = secondsToMs(10); // 1 hr
// const TIMEOUT = secondsToMs(10);
const app = express();
let dbAval: boolean = true;

// initial check
(async () => {
try {
logger.info(`Please wait ${TIMEOUT / 1000}s for the database to connect`);
dbAval = await checkDB(TIMEOUT);
logger.info("Server is up");
// logger.info(`Please wait ${TIMEOUT / 1000}s for the database to connect`);
dbAval = await checkDB();
logger.info(`Server is up, database is ${dbAval ? "up" : "not up"}`);
} catch (e: any) {
dbAval = false;
}
Expand All @@ -32,13 +32,13 @@ let dbAval: boolean = true;
// routine
setInterval(async () => {
try {
dbAval = await checkDB(TIMEOUT);
dbAval = await checkDB();
} catch (e: any) {
console.error("Error:", e.message);
dbAval = false;
}
logger.info(`Database is ${dbAval ? "available" : "not available"}`);
}, INTERVAL);
}, 100000);

app.use(cors());
app.use((req: any, res: any, next: any) => {
Expand Down

0 comments on commit 7db7839

Please sign in to comment.