From 237f8ae6c29bbf485c312b2fed4d5ab4f99a4eff Mon Sep 17 00:00:00 2001 From: Arne Rief Date: Sat, 20 Dec 2025 14:09:20 +0100 Subject: Map and loading robots --- backend/src/controllers/getRobots.ts | 56 ++++++++++++++++++++++++++++++++++++ backend/src/routes/router.ts | 4 +++ backend/src/types/error.ts | 4 +++ backend/src/types/robot.ts | 20 +++++++++++++ backend/src/types/user.ts | 6 ++-- 5 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 backend/src/controllers/getRobots.ts create mode 100644 backend/src/types/error.ts create mode 100644 backend/src/types/robot.ts (limited to 'backend/src') 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 = 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; }; -- cgit v1.2.3