Compare commits
10 Commits
49b6f79545
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 011dfdffc6 | |||
| eca7510eb8 | |||
| 05fc2496d7 | |||
| 0f913ee940 | |||
| 730044f0b7 | |||
| cb2f5732eb | |||
| e44a7672d5 | |||
| 84c6d72faf | |||
| 0ee01bc313 | |||
| 14b0a44117 |
@@ -9,19 +9,21 @@ const QUEUE_THRESHOLD = parseInt(process.env.QUEUE_THRESHOLD || "100", 10)
|
||||
const CONCURRENT_ACTIVE = parseInt(process.env.CONCURRENT_ACTIVE || "50", 10)
|
||||
const TOKEN_TTL_SECONDS = parseInt(process.env.TOKEN_TTL_SECONDS || `${15 * 60}`, 10)
|
||||
|
||||
// MySQL kapcsolat
|
||||
let db = null
|
||||
|
||||
// MySQL kapcsolat - minden híváskor új connection
|
||||
async function getDbConnection() {
|
||||
if (!db && process.env.MYSQL_HOST) {
|
||||
db = await mysql.createConnection({
|
||||
if (!process.env.MYSQL_HOST) return null
|
||||
try {
|
||||
const connection = await mysql.createConnection({
|
||||
host: process.env.MYSQL_HOST,
|
||||
user: process.env.MYSQL_USER,
|
||||
password: process.env.MYSQL_PASSWORD,
|
||||
database: process.env.MYSQL_DATABASE,
|
||||
})
|
||||
return connection
|
||||
} catch (error) {
|
||||
console.error('MySQL connection error:', error)
|
||||
return null
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
function ensureEvent(eventId) {
|
||||
@@ -61,12 +63,17 @@ async function evaluateQueue(eventId, io) {
|
||||
const next = ev.queue.shift()
|
||||
if (!next) break
|
||||
|
||||
// sign token
|
||||
const expiresAt = new Date(Date.now() + TOKEN_TTL_SECONDS * 1000)
|
||||
// Get database time for consistency
|
||||
const [timeRows] = await connection.execute('SELECT NOW() as db_time')
|
||||
const dbTime = new Date(timeRows[0].db_time)
|
||||
const expiresAt = new Date(dbTime.getTime() + TOKEN_TTL_SECONDS * 1000)
|
||||
|
||||
const token = jwt.sign({ sid: next, eventId }, process.env.JWT_SECRET || "dev-secret", {
|
||||
expiresIn: TOKEN_TTL_SECONDS,
|
||||
})
|
||||
|
||||
console.log(`Creating queued token for ${next.substring(0, 8)}: DB time ${dbTime.toISOString()}, expires at ${expiresAt.toISOString()}, TTL: ${TOKEN_TTL_SECONDS}s`)
|
||||
|
||||
ev.active.add(next)
|
||||
|
||||
// Save to database
|
||||
@@ -87,14 +94,32 @@ async function evaluateQueue(eventId, io) {
|
||||
// Check for expired tokens in database and notify clients
|
||||
if (connection) {
|
||||
try {
|
||||
// Debug: check current time vs stored times
|
||||
const [allSessions] = await connection.execute(
|
||||
'SELECT socket_id, expires_at, NOW() as server_time FROM active_sessions WHERE event_id = ?',
|
||||
[eventId]
|
||||
)
|
||||
|
||||
console.log(`Event ${eventId} - Current sessions:`, allSessions.map(s => ({
|
||||
socket: s.socket_id.substring(0, 8),
|
||||
expires: s.expires_at,
|
||||
server_time: s.server_time,
|
||||
expired: new Date(s.expires_at) < new Date(s.server_time)
|
||||
})))
|
||||
|
||||
const [expiredSessions] = await connection.execute(
|
||||
'SELECT socket_id FROM active_sessions WHERE event_id = ? AND expires_at < NOW()',
|
||||
[eventId]
|
||||
)
|
||||
|
||||
if (expiredSessions.length > 0) {
|
||||
console.log(`Found ${expiredSessions.length} expired sessions for event ${eventId}`)
|
||||
}
|
||||
|
||||
for (const session of expiredSessions) {
|
||||
const sid = session.socket_id
|
||||
if (ev.active.has(sid)) {
|
||||
console.log(`Sending token_expired to ${sid.substring(0, 8)}`)
|
||||
ev.active.delete(sid)
|
||||
io.to(sid).emit("token_expired")
|
||||
}
|
||||
@@ -102,6 +127,7 @@ async function evaluateQueue(eventId, io) {
|
||||
|
||||
// Clean up expired sessions from database
|
||||
if (expiredSessions.length > 0) {
|
||||
console.log(`Cleaning up ${expiredSessions.length} expired sessions for event ${eventId}`);
|
||||
await connection.execute(
|
||||
'DELETE FROM active_sessions WHERE event_id = ? AND expires_at < NOW()',
|
||||
[eventId]
|
||||
@@ -136,6 +162,15 @@ async function evaluateQueue(eventId, io) {
|
||||
// If queue no longer needed, clear it
|
||||
if (ev.sockets.size < QUEUE_THRESHOLD) ev.queueOn = false
|
||||
|
||||
// Close database connection
|
||||
if (connection) {
|
||||
try {
|
||||
await connection.end()
|
||||
} catch (error) {
|
||||
console.error('Error closing DB connection:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// broadcast
|
||||
broadcastUpdate(eventId, io)
|
||||
}
|
||||
@@ -163,6 +198,18 @@ export async function GET(req) {
|
||||
|
||||
global.io = io
|
||||
|
||||
// Clean up all expired sessions on server start
|
||||
const startupConnection = await getDbConnection()
|
||||
if (startupConnection) {
|
||||
try {
|
||||
const [result] = await startupConnection.execute('DELETE FROM active_sessions WHERE expires_at < NOW()')
|
||||
console.log(`Server startup: Cleaned ${result.affectedRows} expired sessions`)
|
||||
await startupConnection.end()
|
||||
} catch (error) {
|
||||
console.error('Cleanup error on startup:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Periodikus token ellenőrzés minden 5 másodpercben
|
||||
setInterval(async () => {
|
||||
for (const eventId of Object.keys(events)) {
|
||||
@@ -230,8 +277,15 @@ export async function GET(req) {
|
||||
|
||||
// If queue is NOT active and user doesn't have access, grant it immediately
|
||||
if (!ev.queueOn && !ev.active.has(socket.id)) {
|
||||
console.log(`Granting immediate access to ${socket.id} (under threshold)`)
|
||||
const expiresAt = new Date(Date.now() + TOKEN_TTL_SECONDS * 1000)
|
||||
console.log(`Granting immediate access to ${socket.id.substring(0, 8)} (under threshold)`)
|
||||
|
||||
// Get server time from database to ensure consistency
|
||||
const [timeRows] = await connection.execute('SELECT NOW() as db_time')
|
||||
const dbTime = new Date(timeRows[0].db_time)
|
||||
const expiresAt = new Date(dbTime.getTime() + TOKEN_TTL_SECONDS * 1000)
|
||||
|
||||
console.log(`DB time: ${dbTime.toISOString()}, Token expires: ${expiresAt.toISOString()}, TTL: ${TOKEN_TTL_SECONDS}s`)
|
||||
|
||||
const token = jwt.sign({ sid: socket.id, eventId }, process.env.JWT_SECRET || "dev-secret", {
|
||||
expiresIn: TOKEN_TTL_SECONDS,
|
||||
})
|
||||
@@ -263,6 +317,15 @@ export async function GET(req) {
|
||||
position: pos === -1 ? null : pos + 1,
|
||||
estimatedWait: pos === -1 ? null : (ev.active.size + pos) * TOKEN_TTL_SECONDS,
|
||||
})
|
||||
|
||||
// Close database connection
|
||||
if (connection) {
|
||||
try {
|
||||
await connection.end()
|
||||
} catch (error) {
|
||||
console.error('Error closing DB connection:', error)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
socket.on("disconnect", () => {
|
||||
|
||||
@@ -15,6 +15,21 @@ export default function EventPage() {
|
||||
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
// Function to clear all token and queue state
|
||||
const clearAllTokenState = () => {
|
||||
console.log("Clearing all token state");
|
||||
setHasAccess(false);
|
||||
setTokenExpiry(null);
|
||||
setPosition(null);
|
||||
setEstimatedWait(null);
|
||||
try {
|
||||
localStorage.removeItem("event_token");
|
||||
} catch (e) {}
|
||||
if (socketRef.current) {
|
||||
socketRef.current.disconnect();
|
||||
}
|
||||
};
|
||||
|
||||
const [connected, setConnected] = useState(false);
|
||||
const [position, setPosition] = useState<number | null>(null);
|
||||
const [estimatedWait, setEstimatedWait] = useState<number | null>(null);
|
||||
@@ -67,7 +82,8 @@ export default function EventPage() {
|
||||
.then(({ io }) => {
|
||||
if (!mounted) return;
|
||||
const socketPort = process.env.NEXT_PUBLIC_SOCKET_PORT || "4000";
|
||||
const socket = io(`http://10.20.0.188:${socketPort}`, {
|
||||
const socketHost = process.env.NEXT_PUBLIC_SOCKET_HOST || window.location.hostname;
|
||||
const socket = io(`http://${socketHost}:${socketPort}`, {
|
||||
autoConnect: true
|
||||
});
|
||||
socketRef.current = socket;
|
||||
@@ -91,8 +107,18 @@ export default function EventPage() {
|
||||
});
|
||||
|
||||
socket.on("granted", (data: any) => {
|
||||
console.log("Granted event received:", data);
|
||||
const expiryTime = data.expiresAt ? Date.parse(data.expiresAt) : Date.now() + 15 * 60 * 1000;
|
||||
console.log("Setting token expiry:", {
|
||||
raw: data.expiresAt,
|
||||
parsed: new Date(expiryTime),
|
||||
now: new Date(),
|
||||
diffMs: expiryTime - Date.now(),
|
||||
diffMin: Math.round((expiryTime - Date.now()) / 60000)
|
||||
});
|
||||
|
||||
setHasAccess(true);
|
||||
setTokenExpiry(data.expiresAt ? Date.parse(data.expiresAt) : Date.now() + 15 * 60 * 1000);
|
||||
setTokenExpiry(expiryTime);
|
||||
try {
|
||||
localStorage.setItem("event_token", data.token);
|
||||
} catch (e) {}
|
||||
@@ -105,11 +131,11 @@ export default function EventPage() {
|
||||
});
|
||||
|
||||
socket.on("token_expired", () => {
|
||||
setHasAccess(false);
|
||||
setTokenExpiry(null);
|
||||
localStorage.removeItem("event_token");
|
||||
// Redirect to homepage
|
||||
window.location.href = "/";
|
||||
console.log("Token expired received from server");
|
||||
clearAllTokenState();
|
||||
setTimeout(() => {
|
||||
window.location.href = "/";
|
||||
}, 100);
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
@@ -122,17 +148,10 @@ export default function EventPage() {
|
||||
};
|
||||
}, [eventId, loading]);
|
||||
|
||||
// Check for existing token on page load
|
||||
// Check for existing token on page load and clear everything
|
||||
useEffect(() => {
|
||||
try {
|
||||
const existingToken = localStorage.getItem("event_token");
|
||||
if (existingToken) {
|
||||
console.log('Found existing token, clearing it');
|
||||
localStorage.removeItem("event_token");
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('localStorage access error:', e);
|
||||
}
|
||||
console.log('Page loaded, clearing any existing token state');
|
||||
clearAllTokenState();
|
||||
}, []);
|
||||
|
||||
// Token expiry timer - ellenőrzés minden másodpercben
|
||||
@@ -143,15 +162,11 @@ export default function EventPage() {
|
||||
const msLeft = tokenExpiry - Date.now();
|
||||
console.log('Token check - ms left:', msLeft);
|
||||
if (msLeft <= 0) {
|
||||
console.log('Token expired, redirecting to homepage');
|
||||
setHasAccess(false);
|
||||
setTokenExpiry(null);
|
||||
localStorage.removeItem("event_token");
|
||||
// Disconnect socket and redirect to homepage
|
||||
if (socketRef.current) {
|
||||
socketRef.current.disconnect();
|
||||
}
|
||||
window.location.href = "/";
|
||||
console.log('Token expired locally, redirecting to homepage');
|
||||
clearAllTokenState();
|
||||
setTimeout(() => {
|
||||
window.location.href = "/";
|
||||
}, 100);
|
||||
}
|
||||
}, 1000);
|
||||
return () => clearInterval(id);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
allowedDevOrigins: ["10.20.0.188"]
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
Reference in New Issue
Block a user