追踪简化
This commit is contained in:
+49
-41
@@ -1,7 +1,7 @@
|
||||
import { Router, RequestHandler } from 'express';
|
||||
import { redis } from '../services/redis';
|
||||
import * as roomService from '../services/room';
|
||||
import { ReferrerTrack, LogMessage } from '../types/room';
|
||||
import { Router, RequestHandler } from "express";
|
||||
import { redis } from "../services/redis";
|
||||
import * as roomService from "../services/room";
|
||||
import { ReferrerTrack, LogMessage } from "../types/room";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -15,10 +15,13 @@ interface CheckRoomRequest {
|
||||
}
|
||||
|
||||
// 创建房间的路由处理函数
|
||||
const createRoomHandler: RequestHandler<{}, any, CreateRoomRequest> = async (req, res) => {
|
||||
const createRoomHandler: RequestHandler<{}, any, CreateRoomRequest> = async (
|
||||
req,
|
||||
res
|
||||
) => {
|
||||
const { roomId } = req.body;
|
||||
if (!roomId) {
|
||||
res.status(400).json({ error: 'Room ID is required' });
|
||||
res.status(400).json({ error: "Room ID is required" });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -26,7 +29,7 @@ const createRoomHandler: RequestHandler<{}, any, CreateRoomRequest> = async (req
|
||||
const exists = await roomService.isRoomExist(roomId);
|
||||
const response = {
|
||||
success: !exists,
|
||||
message: exists ? 'roomId is already exists' : 'create room success'
|
||||
message: exists ? "roomId is already exists" : "create room success",
|
||||
};
|
||||
|
||||
if (!exists) {
|
||||
@@ -35,8 +38,8 @@ const createRoomHandler: RequestHandler<{}, any, CreateRoomRequest> = async (req
|
||||
|
||||
res.json(response);
|
||||
} catch (error) {
|
||||
console.error('Error checking room:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
console.error("Error checking room:", error);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -47,16 +50,19 @@ const getRoomHandler: RequestHandler = async (req, res) => {
|
||||
await roomService.createRoom(roomId);
|
||||
res.json({ roomId });
|
||||
} catch (error) {
|
||||
console.error('Error getting room:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
console.error("Error getting room:", error);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
};
|
||||
|
||||
// 检查房间的路由处理函数
|
||||
const checkRoomHandler: RequestHandler<{}, any, CheckRoomRequest> = async (req, res) => {
|
||||
const checkRoomHandler: RequestHandler<{}, any, CheckRoomRequest> = async (
|
||||
req,
|
||||
res
|
||||
) => {
|
||||
const { roomId } = req.body;
|
||||
if (!roomId) {
|
||||
res.status(400).json({ error: 'Room ID is required' });
|
||||
res.status(400).json({ error: "Room ID is required" });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -64,60 +70,62 @@ const checkRoomHandler: RequestHandler<{}, any, CheckRoomRequest> = async (req,
|
||||
const exists = await roomService.isRoomExist(roomId);
|
||||
res.json({ available: !exists });
|
||||
} catch (error) {
|
||||
console.error('Error checking room:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
console.error("Error checking room:", error);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
};
|
||||
|
||||
// 设置跟踪的路由处理函数
|
||||
const setTrackHandler: RequestHandler<{}, any, ReferrerTrack> = async (req, res) => {
|
||||
if (req.method !== 'POST') {
|
||||
res.status(405).json({ message: 'Method not allowed' });
|
||||
const setTrackHandler: RequestHandler<{}, any, ReferrerTrack> = async (
|
||||
req,
|
||||
res
|
||||
) => {
|
||||
if (req.method !== "POST") {
|
||||
res.status(405).json({ message: "Method not allowed" });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { ref, timestamp, path } = req.body;
|
||||
// 按日期统计
|
||||
const date = new Date(timestamp).toISOString().split('T')[0];
|
||||
//"referrers:daily:2024-01-20" : { "producthunt": "5", "twitter": "3" }
|
||||
const date = new Date(timestamp).toISOString().split("T")[0];
|
||||
const dailyKey = `referrers:daily:${date}`;
|
||||
const thirtyDaysInSeconds = 30 * 24 * 60 * 60;
|
||||
|
||||
// 使用MULTI确保hincrby和expire的原子性
|
||||
await redis.multi()
|
||||
.hincrby(dailyKey, ref, 1) // \"referrers:daily:2024-01-20\" : { \"producthunt\": \"5\", \"twitter\": \"3\" }
|
||||
.expire(dailyKey, thirtyDaysInSeconds) // 设置30天过期
|
||||
.exec();
|
||||
|
||||
await redis.hincrby(`referrers:daily:${date}`, ref, 1);
|
||||
//"referrers:sources" : ["producthunt", "twitter", ...] // 来源集合
|
||||
await redis.sadd('referrers:sources', ref);
|
||||
|
||||
// 使用MULTI确保hincrby和expire的原子性
|
||||
await redis
|
||||
.multi()
|
||||
.hincrby(dailyKey, ref, 1) // \"referrers:daily:2024-01-20\" : { \"producthunt\": \"5\", \"twitter\": \"3\" }
|
||||
.expire(dailyKey, thirtyDaysInSeconds) // 设置30天过期
|
||||
.exec();
|
||||
|
||||
res.status(200).json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Track API Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Failed to track referrer' });
|
||||
console.error("Track API Error:", error);
|
||||
res.status(500).json({ success: false, error: "Failed to track referrer" });
|
||||
}
|
||||
};
|
||||
|
||||
// 日志调试的路由处理函数
|
||||
const logsDebugHandler: RequestHandler<{}, any, LogMessage> = async (req, res) => {
|
||||
const logsDebugHandler: RequestHandler<{}, any, LogMessage> = async (
|
||||
req,
|
||||
res
|
||||
) => {
|
||||
try {
|
||||
const { message, timestamp } = req.body;
|
||||
console.log(`logs----timestamp:${timestamp} message:${message}`);
|
||||
res.status(200).json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Error checking room:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
console.error("Error checking room:", error);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
};
|
||||
|
||||
// 注册路由
|
||||
router.post('/api/creat_room', createRoomHandler);
|
||||
router.get('/api/get_room', getRoomHandler);
|
||||
router.post('/api/check_room', checkRoomHandler);
|
||||
router.post('/api/set_track', setTrackHandler);
|
||||
router.post('/api/logs_debug', logsDebugHandler);
|
||||
router.post("/api/creat_room", createRoomHandler);
|
||||
router.get("/api/get_room", getRoomHandler);
|
||||
router.post("/api/check_room", checkRoomHandler);
|
||||
router.post("/api/set_track", setTrackHandler);
|
||||
router.post("/api/logs_debug", logsDebugHandler);
|
||||
|
||||
export default router;
|
||||
export default router;
|
||||
|
||||
+14
-19
@@ -1,21 +1,14 @@
|
||||
import express from 'express';//express: 用于创建一个简洁且灵活的Node.js web应用框架
|
||||
import cors from 'cors';
|
||||
import http from 'http';
|
||||
import { Server } from 'socket.io';//实时通信库,基于WebSocket协议,实现双向通信
|
||||
import { CONFIG } from './config/env';
|
||||
import { corsOptions, corsWSOptions } from './config/server';
|
||||
import { redis } from './services/redis';
|
||||
import { cleanupData } from './utils/dataCleanup';
|
||||
import apiRouter from './routes/api';
|
||||
import { setupSocketHandlers } from './socket/handlers';
|
||||
// 设置定时清理任务,间隔24H
|
||||
const CLEANUP_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours
|
||||
setInterval(() => {
|
||||
cleanupData(redis);
|
||||
}, CLEANUP_INTERVAL);
|
||||
import express from "express"; //express: 用于创建一个简洁且灵活的Node.js web应用框架
|
||||
import cors from "cors";
|
||||
import http from "http";
|
||||
import { Server } from "socket.io"; //实时通信库,基于WebSocket协议,实现双向通信
|
||||
import { CONFIG } from "./config/env";
|
||||
import { corsOptions, corsWSOptions } from "./config/server";
|
||||
import apiRouter from "./routes/api";
|
||||
import { setupSocketHandlers } from "./socket/handlers";
|
||||
|
||||
const app = express();//创建一个Express应用
|
||||
app.use(cors(corsOptions));// 添加 CORS 中间件
|
||||
const app = express(); //创建一个Express应用
|
||||
app.use(cors(corsOptions)); // 添加 CORS 中间件
|
||||
app.use(express.json());
|
||||
app.use(apiRouter);
|
||||
|
||||
@@ -25,5 +18,7 @@ const io = new Server(server, { cors: corsWSOptions });
|
||||
setupSocketHandlers(io);
|
||||
|
||||
server.listen(CONFIG.PORT, () => {
|
||||
console.log(`Signaling server running in ${CONFIG.NODE_ENV} mode on port ${CONFIG.PORT}`);
|
||||
});
|
||||
console.log(
|
||||
`Signaling server running in ${CONFIG.NODE_ENV} mode on port ${CONFIG.PORT}`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
//定时任务处理器
|
||||
import { Redis } from 'ioredis';
|
||||
|
||||
export const cleanupData = async (redis: Redis): Promise<void> => {
|
||||
try {
|
||||
// 1. 找出30天以前(过期)的每日统计数据
|
||||
const today = new Date();
|
||||
const thirtyDaysAgo = new Date(today.setDate(today.getDate() - 30));
|
||||
|
||||
// 获取所有 daily 统计 key
|
||||
const dailyKeys = await redis.keys('referrers:daily:*');
|
||||
|
||||
for (const key of dailyKeys) {
|
||||
const keyDate = key.split(':')[2];
|
||||
if (new Date(keyDate) < thirtyDaysAgo) {
|
||||
await redis.del(key);
|
||||
} else {
|
||||
// 为未过期的 key 重新设置过期时间
|
||||
await redis.expire(key, 60 * 60 * 24 * 30); // 30天
|
||||
}
|
||||
}
|
||||
console.log('Data cleanup completed successfully');
|
||||
} catch (error) {
|
||||
console.error('Error during data cleanup:', error);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user