perf: complete industry-standard optimization for frontend & backend

This commit is contained in:
Shanmuga Krishnan S M
2026-08-20 10:18:55 +05:30
parent 128e033a9a
commit 95c97e81fa
6 changed files with 253 additions and 84 deletions

View File

@@ -45,8 +45,17 @@ public class BusLocationService {
public List<BusLocation> getActiveLocations() { public List<BusLocation> getActiveLocations() {
Instant threshold = Instant.now().minus(STALE_DURATION); Instant threshold = Instant.now().minus(STALE_DURATION);
// Clean up stale entries on read return locationCache.values().stream()
.filter(loc -> !loc.getLastUpdated().isBefore(threshold))
.toList();
}
/**
* Periodic background eviction of stale GPS coordinates every 5 minutes
*/
@org.springframework.scheduling.annotation.Scheduled(fixedRate = 300000)
public void evictStaleLocations() {
Instant threshold = Instant.now().minus(STALE_DURATION);
locationCache.entrySet().removeIf(entry -> entry.getValue().getLastUpdated().isBefore(threshold)); locationCache.entrySet().removeIf(entry -> entry.getValue().getLastUpdated().isBefore(threshold));
return List.copyOf(locationCache.values());
} }
} }

View File

@@ -3,14 +3,24 @@ spring.datasource.url=jdbc:postgresql://localhost:5432/rit_freshers_hub?sslmode=
spring.datasource.username=postgres spring.datasource.username=postgres
spring.datasource.password=${DB_PASSWORD:Amudiesh22@.} spring.datasource.password=${DB_PASSWORD:Amudiesh22@.}
# ─── HIKARICP CONNECTION POOL OPTIMIZATIONS ───
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=1200000
spring.datasource.hikari.connection-timeout=20000
# ─── JPA / HIBERNATE SETTINGS ─── # ─── JPA / HIBERNATE SETTINGS ───
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.format_sql=false
# ─── SERVER PORT ─── # ─── SERVER PORT & HTTP GZIP COMPRESSION ───
server.port=8085 server.port=8085
server.compression.enabled=true
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css
server.compression.min-response-size=1024
# ─── GOOGLE OAUTH2 CONFIGURATION ─── # ─── GOOGLE OAUTH2 CONFIGURATION ───
google.client.id=${GOOGLE_CLIENT_ID:81935488244-vmab5t8fipfof1n6l7di7eg4fve6k8lf.apps.googleusercontent.com} google.client.id=${GOOGLE_CLIENT_ID:81935488244-vmab5t8fipfof1n6l7di7eg4fve6k8lf.apps.googleusercontent.com}
@@ -23,10 +33,8 @@ admin.super.password=${SUPER_ADMIN_PASSWORD:RIT@2026}
admin.username=${ADMIN_USERNAME:ritadmin} admin.username=${ADMIN_USERNAME:ritadmin}
admin.password=${ADMIN_PASSWORD:ritadmin2026} admin.password=${ADMIN_PASSWORD:ritadmin2026}
# ─── IMS INTEGRATION CONFIGURATION ─── # ─── IMS INTEGRATION CONFIGURATION ───
# Options: "mock" (active now for testing & simulation) | "real" (for live college IMS) # Options: "mock" (active now for testing & simulation) | "real" (for live college IMS)
ims.client.type=mock ims.client.type=mock
ims.base-url=${IMS_BASE_URL:https://api.ims.ritchennai.edu.in} ims.base-url=${IMS_BASE_URL:https://api.ims.ritchennai.edu.in}
ims.api-key=${IMS_API_KEY:rit_nexus_vps_secret_key_2026} ims.api-key=${IMS_API_KEY:rit_nexus_vps_secret_key_2026}

View File

@@ -1,29 +1,35 @@
import { useEffect } from 'react'; import { useEffect, lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom'; import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { AuthProvider } from '@/context/AuthContext'; import { AuthProvider } from '@/context/AuthContext';
import ProtectedRoute from '@/components/Auth/ProtectedRoute'; import ProtectedRoute from '@/components/Auth/ProtectedRoute';
import MainLayout from '@/layouts/MainLayout'; import MainLayout from '@/layouts/MainLayout';
import Home from '@/pages/Home/Home'; import PageLoader from '@/components/PageLoader/PageLoader';
import Notes from '@/pages/Notes/Notes'; import ErrorBoundary from '@/components/ErrorBoundary/ErrorBoundary';
import Toolkit from '@/pages/Toolkit/Toolkit';
import AIAssistant from '@/pages/AIAssistant/AIAssistant'; // Code-split route components with dynamic imports for minimal initial bundle size
import Campus from '@/pages/Campus/Campus'; const Home = lazy(() => import('@/pages/Home/Home'));
import Events from '@/pages/Events/Events'; const Notes = lazy(() => import('@/pages/Notes/Notes'));
import Community from '@/pages/Community/Community'; const Toolkit = lazy(() => import('@/pages/Toolkit/Toolkit'));
import BusRoutes from '@/pages/BusRoutes/BusRoutes'; const AIAssistant = lazy(() => import('@/pages/AIAssistant/AIAssistant'));
import Faculty from '@/pages/Faculty/Faculty'; const Campus = lazy(() => import('@/pages/Campus/Campus'));
import DevCollab from '@/pages/DevCollab/DevCollab'; const Events = lazy(() => import('@/pages/Events/Events'));
import LeetcodeLeaderboard from '@/pages/LeetcodeLeaderboard/LeetcodeLeaderboard'; const Community = lazy(() => import('@/pages/Community/Community'));
import AdminDashboard from '@/pages/Admin/AdminDashboard'; const BusRoutes = lazy(() => import('@/pages/BusRoutes/BusRoutes'));
import Raise from '@/pages/Raise/Raise'; const Faculty = lazy(() => import('@/pages/Faculty/Faculty'));
import StudentDashboard from '@/pages/StudentDashboard/StudentDashboard'; const DevCollab = lazy(() => import('@/pages/DevCollab/DevCollab'));
const LeetcodeLeaderboard = lazy(() => import('@/pages/LeetcodeLeaderboard/LeetcodeLeaderboard'));
const AdminDashboard = lazy(() => import('@/pages/Admin/AdminDashboard'));
const Raise = lazy(() => import('@/pages/Raise/Raise'));
const StudentDashboard = lazy(() => import('@/pages/StudentDashboard/StudentDashboard'));
const queryClient = new QueryClient({ const queryClient = new QueryClient({
defaultOptions: { defaultOptions: {
queries: { queries: {
staleTime: 5 * 60 * 1000, staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000, gcTime: 10 * 60 * 1000,
refetchOnWindowFocus: false,
retry: 1,
}, },
}, },
}); });
@@ -40,72 +46,76 @@ function ScrollToTop() {
function App() { function App() {
return ( return (
<QueryClientProvider client={queryClient}> <ErrorBoundary>
<BrowserRouter> <QueryClientProvider client={queryClient}>
<AuthProvider> <BrowserRouter>
<ScrollToTop /> <AuthProvider>
<Routes> <ScrollToTop />
{/* Standalone Admin Route */} <Suspense fallback={<PageLoader />}>
<Route path="/admin" element={<AdminDashboard />} /> <Routes>
<Route path="/admin/*" element={<AdminDashboard />} /> {/* Standalone Admin Route */}
<Route path="/admin" element={<AdminDashboard />} />
<Route path="/admin/*" element={<AdminDashboard />} />
{/* Standalone RAISE Route */} {/* Standalone RAISE Route */}
<Route path="/raise" element={<Raise />} /> <Route path="/raise" element={<Raise />} />
<Route element={<MainLayout />}> <Route element={<MainLayout />}>
<Route path="/" element={<Home />} /> <Route path="/" element={<Home />} />
<Route path="/notes" element={<Notes />} /> <Route path="/notes" element={<Notes />} />
<Route path="/toolkit" element={<Toolkit />} /> <Route path="/toolkit" element={<Toolkit />} />
<Route path="/ai-assistant" element={<AIAssistant />} /> <Route path="/ai-assistant" element={<AIAssistant />} />
<Route path="/campus" element={<Campus />} /> <Route path="/campus" element={<Campus />} />
<Route path="/bus-routes" element={<BusRoutes />} /> <Route path="/bus-routes" element={<BusRoutes />} />
<Route path="/faculty" element={<Faculty />} /> <Route path="/faculty" element={<Faculty />} />
<Route path="/events" element={<Events />} /> <Route path="/events" element={<Events />} />
{/* Student Dashboard & Timetable — Real IMS Reg No & Password */} {/* Student Dashboard & Timetable — Real IMS Reg No & Password */}
<Route path="/dashboard" element={<StudentDashboard />} /> <Route path="/dashboard" element={<StudentDashboard />} />
<Route path="/timetable" element={<StudentDashboard />} /> <Route path="/timetable" element={<StudentDashboard />} />
{/* Protected Routes — Require Google Sign-In */} {/* Protected Routes — Require Google Sign-In */}
<Route <Route
path="/community" path="/community"
element={ element={
<ProtectedRoute <ProtectedRoute
title="RIT Q&A Community" title="RIT Q&A Community"
description="Connect with fellow RIT students and ask senior helpers any question about campus life and academics." description="Connect with fellow RIT students and ask senior helpers any question about campus life and academics."
> >
<Community /> <Community />
</ProtectedRoute> </ProtectedRoute>
} }
/> />
<Route <Route
path="/collab" path="/collab"
element={ element={
<ProtectedRoute <ProtectedRoute
title="Developer Collab Hub" title="Developer Collab Hub"
description="Post open-source projects, search for co-developers, and connect with fellow programmers." description="Post open-source projects, search for co-developers, and connect with fellow programmers."
requireVerifiedStudent={true} requireVerifiedStudent={true}
> >
<DevCollab /> <DevCollab />
</ProtectedRoute> </ProtectedRoute>
} }
/> />
<Route <Route
path="/leetcode" path="/leetcode"
element={ element={
<ProtectedRoute <ProtectedRoute
title="RIT LeetCode Leaderboard" title="RIT LeetCode Leaderboard"
description="Track campus competitive programming rankings and see top RIT coders." description="Track campus competitive programming rankings and see top RIT coders."
> >
<LeetcodeLeaderboard /> <LeetcodeLeaderboard />
</ProtectedRoute> </ProtectedRoute>
} }
/> />
</Route> </Route>
</Routes> </Routes>
</AuthProvider> </Suspense>
</BrowserRouter> </AuthProvider>
</QueryClientProvider> </BrowserRouter>
</QueryClientProvider>
</ErrorBoundary>
); );
} }

View File

@@ -0,0 +1,91 @@
import { Component, type ErrorInfo, type ReactNode } from 'react';
import { AlertTriangle, RefreshCw, Home } from 'lucide-react';
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error: Error | null;
}
export class ErrorBoundary extends Component<Props, State> {
public state: State = {
hasError: false,
error: null,
};
public static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('[ErrorBoundary caught error]:', error, errorInfo);
}
private handleReset = () => {
this.setState({ hasError: false, error: null });
window.location.reload();
};
private handleGoHome = () => {
this.setState({ hasError: false, error: null });
window.location.href = '/';
};
public render() {
if (this.state.hasError) {
if (this.props.fallback) {
return this.props.fallback;
}
return (
<div className="min-h-[70vh] flex items-center justify-center p-6">
<div className="max-w-md w-full bg-card/80 backdrop-blur-xl border border-destructive/20 rounded-2xl p-8 shadow-2xl text-center space-y-6">
<div className="w-16 h-16 mx-auto rounded-2xl bg-destructive/10 border border-destructive/20 flex items-center justify-center text-destructive shadow-inner">
<AlertTriangle className="w-8 h-8 animate-bounce" />
</div>
<div className="space-y-2">
<h2 className="text-xl font-bold tracking-tight text-foreground">
Something went wrong
</h2>
<p className="text-sm text-muted-foreground leading-relaxed">
An unexpected error occurred while rendering this section. You can try refreshing the page or navigating back home.
</p>
</div>
{this.state.error && (
<div className="p-3 rounded-lg bg-muted/50 border border-border text-left overflow-x-auto text-xs font-mono text-muted-foreground max-h-24">
{this.state.error.message}
</div>
)}
<div className="flex flex-col sm:flex-row items-center justify-center gap-3 pt-2">
<button
onClick={this.handleReset}
className="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl bg-orange-600 hover:bg-orange-700 text-white text-sm font-medium transition-all shadow-lg shadow-orange-600/25 hover:shadow-orange-600/40 active:scale-95 cursor-pointer"
>
<RefreshCw className="w-4 h-4" />
Try Again
</button>
<button
onClick={this.handleGoHome}
className="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl bg-secondary hover:bg-secondary/80 text-foreground text-sm font-medium transition-all active:scale-95 border border-border cursor-pointer"
>
<Home className="w-4 h-4" />
Go to Home
</button>
</div>
</div>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;

View File

@@ -0,0 +1,24 @@
import React from 'react';
const PageLoader: React.FC = () => {
return (
<div className="min-h-[60vh] flex flex-col items-center justify-center p-6 space-y-4">
<div className="relative flex items-center justify-center">
{/* Outer glowing ripple */}
<div className="absolute w-16 h-16 rounded-full bg-orange-500/20 animate-ping" />
{/* Spinning gradient ring */}
<div className="w-12 h-12 rounded-full border-3 border-transparent border-t-orange-500 border-r-orange-400 animate-spin" />
{/* Center dot */}
<div className="absolute w-4 h-4 rounded-full bg-gradient-to-tr from-orange-600 to-amber-400 shadow-lg shadow-orange-500/50" />
</div>
<div className="flex flex-col items-center space-y-1">
<p className="text-sm font-semibold tracking-wide bg-gradient-to-r from-orange-600 via-amber-500 to-orange-400 bg-clip-text text-transparent animate-pulse">
Loading Freshers Hub
</p>
<p className="text-xs text-muted-foreground">Preparing your campus experience...</p>
</div>
</div>
);
};
export default PageLoader;

View File

@@ -50,6 +50,33 @@ export default defineConfig({
} }
}) })
], ],
build: {
target: 'esnext',
chunkSizeWarningLimit: 800,
rollupOptions: {
output: {
manualChunks(id: string) {
if (id.includes('node_modules')) {
if (id.includes('react') || id.includes('react-dom') || id.includes('react-router-dom')) {
return 'vendor-react';
}
if (id.includes('framer-motion') || id.includes('lucide-react')) {
return 'vendor-ui';
}
if (id.includes('@radix-ui')) {
return 'vendor-radix';
}
if (id.includes('@tanstack')) {
return 'vendor-tanstack';
}
if (id.includes('leaflet') || id.includes('react-leaflet')) {
return 'vendor-map';
}
}
}
}
}
},
server: { server: {
host: true, host: true,
proxy: { proxy: {