summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/src/controllers/getRobots.ts56
-rw-r--r--backend/src/routes/router.ts4
-rw-r--r--backend/src/types/error.ts4
-rw-r--r--backend/src/types/robot.ts20
-rw-r--r--backend/src/types/user.ts6
5 files changed, 87 insertions, 3 deletions
diff --git a/backend/src/controllers/getRobots.ts b/backend/src/controllers/getRobots.ts
new file mode 100644
index 0000000..b634306
--- /dev/null
+++ b/backend/src/controllers/getRobots.ts
@@ -0,0 +1,56 @@
+import { Request, Response } from "express";
+import { QueryResult } from "pg";
+import db from "../database/postgres.js";
+import redisClient from "../database/redis.js";
+import { ErrorResponse } from "../types/error.js";
+import { Robot, RobotsResponse } from "../types/robot.js";
+
+const CACHE_TTL = 10;
+const ROBOTS_CACHE_KEY = "allMyRobots";
+
+async function getRobots(_req: Request, res: Response) {
+ try {
+ // Check if Redis has cached data to send to frontend
+ const cachedData = await redisClient.get(ROBOTS_CACHE_KEY);
+
+ if (cachedData) {
+ console.log("Data served from Redis cache.");
+ const robots: Robot[] = JSON.parse(cachedData);
+
+ const response: RobotsResponse = {
+ source: "cache",
+ data: robots,
+ };
+
+ return res.status(200).json(response);
+ }
+
+ // Else query database, then save in Redis cache and send to frontend
+ const robotsQuery: QueryResult<Robot> = await db.query(
+ "SELECT * FROM robots ORDER BY id;"
+ );
+ const robots = robotsQuery.rows;
+
+ await redisClient.set(ROBOTS_CACHE_KEY, JSON.stringify(robots), {
+ EX: CACHE_TTL,
+ });
+
+ console.log("Cache miss: data queried from PostgreSQL.");
+ const response: RobotsResponse = {
+ source: "database",
+ data: robots,
+ };
+
+ return res.status(200).json(response);
+ } catch (error) {
+ console.error("Failed to load the robots: ", error);
+ const errorResponse: ErrorResponse = {
+ message: "Internal server error while loading the robots.",
+ error,
+ };
+
+ return res.status(500).json(errorResponse);
+ }
+}
+
+export default getRobots;
diff --git a/backend/src/routes/router.ts b/backend/src/routes/router.ts
index 325b08a..e67a64b 100644
--- a/backend/src/routes/router.ts
+++ b/backend/src/routes/router.ts
@@ -1,6 +1,8 @@
import { Router } from "express";
import generateAdmin from "../controllers/generateAdmin.js";
+import getRobots from "../controllers/getRobots.js";
import loginUser from "../controllers/loginUser.js";
+import authenticateUser from "../middleware/authCheck.js";
const router = Router();
@@ -8,5 +10,7 @@ const router = Router();
router.get("/admin-generation", generateAdmin);
// Login for registered users
router.post("/auth/login", loginUser);
+// Get robots from database; protected route
+router.get("/robots", authenticateUser, getRobots);
export default router;
diff --git a/backend/src/types/error.ts b/backend/src/types/error.ts
new file mode 100644
index 0000000..c848e34
--- /dev/null
+++ b/backend/src/types/error.ts
@@ -0,0 +1,4 @@
+export type ErrorResponse = {
+ message: string;
+ error?: unknown;
+};
diff --git a/backend/src/types/robot.ts b/backend/src/types/robot.ts
new file mode 100644
index 0000000..40ce282
--- /dev/null
+++ b/backend/src/types/robot.ts
@@ -0,0 +1,20 @@
+export type RobotPosition = {
+ lat: number;
+ lon: number;
+};
+
+export type Robot = {
+ id: number;
+ name: string;
+ status: "idle" | "moving";
+ lat: number;
+ lon: number;
+ robot_positions: RobotPosition[];
+ created_at: string;
+ updated_at: string;
+};
+
+export type RobotsResponse = {
+ source: "cache" | "database";
+ data: Robot[];
+};
diff --git a/backend/src/types/user.ts b/backend/src/types/user.ts
index 875072c..b2c7ffc 100644
--- a/backend/src/types/user.ts
+++ b/backend/src/types/user.ts
@@ -1,18 +1,18 @@
export type AdminCreationResult = {
id: string;
email: string;
- created_at: Date;
+ created_at: string;
};
export type AuthorizedUser = {
id: string;
email: string;
- createdAt: Date;
+ createdAt: string;
};
export type DatabaseUser = {
id: string;
email: string;
password_hash: string;
- created_at: Date;
+ created_at: string;
};