Code cleanup and optimization - removed debug logs and comments

This commit is contained in:
Lam Hoi Fung
2025-11-12 16:34:03 +08:00
parent 1e2947f58c
commit d8a6075fc8
2 changed files with 275 additions and 61 deletions

195
README.md
View File

@@ -0,0 +1,195 @@
# Dashboard Backend
Real-time cryptocurrency price streaming server built with Express.js and Socket.IO
## 🎯 Features
- ✅ Real-time cryptocurrency prices via WebSocket
- ✅ CoinGecko API integration (free, no API key needed)
- ✅ Automatic data refresh every 5 seconds
- ✅ CORS enabled for cross-origin requests
- ✅ Connection tracking and client count broadcasting
- ✅ Graceful error handling
- ✅ Automatic reconnection support
## 🛠 Tech Stack
- **Framework**: Express.js v4.18+
- **Real-time**: Socket.IO v4.5+
- **HTTP Client**: Axios v1.5+
- **Environment**: Dotenv v16+
- **CORS**: CORS middleware v2.8+
## 📋 Prerequisites
- Node.js v16.0.0 or higher
- npm v8.0.0 or higher
## 🚀 Quick Start
### 1. Installation
```bash
npm install
```
### 2. Environment Setup
Create a `.env` file:
```env
PORT=5000
NODE_ENV=development
CORS_ORIGIN=http://localhost:3000
```
### 3. Start Development Server
```bash
npm run dev
```
Server will run on `http://localhost:5000`
### 4. Start Production Server
```bash
npm start
```
## 📡 WebSocket Events
### Client → Server
**requestData**
- Payload: `{ dataType: 'crypto' }`
- Description: Client requests crypto data
### Server → Client
**data**
- Payload: Real-time cryptocurrency data
- Emitted: Every 5 seconds
**clientCount**
- Payload: `{ count: number }`
- Description: Total connected clients
**error**
- Payload: `{ message: string, details: string }`
- Description: Error occurred
## 📊 Data Response Format
```json
{
"type": "crypto",
"timestamp": "2025-10-28T12:00:00.000Z",
"prices": {
"bitcoin": {
"usd": 42500.50,
"usd_market_cap": 850000000000,
"usd_24h_vol": 25000000000,
"usd_24h_change": 2.5
},
"ethereum": {
"usd": 2300.75,
"usd_market_cap": 280000000000,
"usd_24h_vol": 15000000000,
"usd_24h_change": 1.8
}
}
}
```
## 🔄 Supported Cryptocurrencies
- Bitcoin (BTC)
- Ethereum (ETH)
- Cardano (ADA)
- Solana (SOL)
- Ripple (XRP)
## 🔒 Security
- Environment variables for sensitive data
- CORS restrictions configurable
- Input validation on events
- Error messages sanitized
- No sensitive data exposed
## 🐛 Debugging
### Enable Verbose Logging
The server logs all important events:
- Client connections/disconnections
- Data requests
- API calls
- Errors
Check console output for troubleshooting
### Common Issues
**Port Already in Use**
```bash
# Mac/Linux
lsof -i :5000
# Windows
netstat -ano | findstr :5000
```
**CORS Errors**
- Check CORS_ORIGIN in .env matches frontend URL
- Verify frontend is running on http://localhost:3000
**API Not Responding**
- Check internet connection
- CoinGecko API may be rate-limited
- Server will auto-retry
## 📈 Performance
- Lightweight and fast
- Handles multiple concurrent connections
- Efficient data updates (5-second intervals)
- Minimal bandwidth usage
## 🚀 Deployment Ready
Tested and ready for deployment on:
- Railway.app ✅
- Render.com ✅
- Heroku ✅
- DigitalOcean ✅
- AWS ✅
## 📝 API Health Check
```bash
curl http://localhost:5000/health
```
Response:
```json
{
"status": "OK",
"message": "Server is running",
"timestamp": "2025-10-28T12:00:00.000Z"
}
```
## 📄 License
ISC
## 👤 Author
CloudForge Dev Team
---
**Status**: Production Ready
**Last Updated**: 2025-10-28

141
server.js
View File

@@ -9,6 +9,10 @@ const app = express();
const server = http.createServer(app); const server = http.createServer(app);
let cachedPrices = null;
let lastFetchTime = 0;
const CACHE_DURATION = 30000;
const io = socketIo(server, { const io = socketIo(server, {
cors: { cors: {
origin: process.env.CORS_ORIGIN || "*", origin: process.env.CORS_ORIGIN || "*",
@@ -34,63 +38,69 @@ app.get("/health", (req, res) => {
// ========== Socket.IO Logic ========== // ========== Socket.IO Logic ==========
// 用於追蹤連接的客戶端數量 // Number of clients
let connectedClients = 0; let connectedClients = 0;
// 當客戶端連接時觸發 // Trigger when client connected
io.on("connection", (socket) => { io.on("connection", (socket) => {
// 增加客戶端計數
connectedClients++; connectedClients++;
console.log(`客戶端已連接: ${socket.id}`); console.log(`Client Connected: ${socket.id}`);
console.log(`📊 當前連接數: ${connectedClients}`); console.log(`📊 Current Number of Clients: ${connectedClients}`);
// 向所有客戶端廣播當前連接數 // Broadcast to all clients
io.emit("clientCount", connectedClients); io.emit("clientCount", connectedClients);
// ========== 監聽客戶端事件 ========== // ========== Monitoring client side events ==========
// 當客戶端要求數據時 // Request Data
socket.on("requestData", async (dataType) => { socket.on("requestData", async (dataType) => {
console.log(`📤 數據請求: ${dataType}`); console.log(`📤 Request Data: ${dataType}`);
const now = new Date();
try { try {
let data; let data;
if (dataType === "crypto") { if (dataType === "crypto") {
// 從 CoinGecko API 獲取加密貨幣數據 if (cachedPrices && now - lastFetchTime < CACHE_DURATION) {
const response = await axios.get( console.log("📦 Use caching data");
"https://api.coingecko.com/api/v3/simple/price", data = cachedPrices;
{ } else {
params: { // Get data from "CoinGecko API"
// 要查詢的加密貨幣 const response = await axios.get(
ids: "bitcoin,ethereum,cardano,solana,ripple", "https://api.coingecko.com/api/v3/simple/price",
// 使用 USD 幣種 {
vs_currencies: "usd", params: {
// 包含市值 // list of crypto requested to be shown
include_market_cap: true, ids: "bitcoin,ethereum,cardano,solana,ripple",
// 包含24小時交易量 vs_currencies: "usd",
include_24hr_vol: true, include_market_cap: true,
// 包含24小時漲跌幅 include_24hr_vol: true,
include_24hr_change: true, include_24hr_change: true,
}, },
} }
); );
// 組織數據格式 // Construct data format
data = { data = {
type: "crypto", type: "crypto",
timestamp: new Date(), timestamp: new Date(),
prices: response.data, prices: response.data,
}; };
// Update Caches
cachedPrices = data;
lastFetchTime = now;
console.log("✅ Cached New Data");
}
} }
// 發送數據給要求的客戶端 // Emit data to client side
socket.emit("data", data); socket.emit("data", data);
console.log(`數據已發送給客戶端: ${socket.id}`); console.log(`Data sent to client: ${socket.id}`);
} catch (error) { } catch (error) {
console.error("❌ 獲取數據出錯:", error.message); console.error("❌ Error on Getting Data:", error.message);
// 發送錯誤信息給客戶端 // Emit Error message to client side
socket.emit("error", { socket.emit("error", {
message: "Failed to fetch data", message: "Failed to fetch data",
details: error.message, details: error.message,
@@ -98,12 +108,19 @@ io.on("connection", (socket) => {
} }
}); });
// ========== 定期推送數據 ========== // ========== Push Data by interval ==========
// 創建定時器每5秒推送一次數據給該客戶端 // Push every 5 seconds
const dataInterval = setInterval(async () => { const dataInterval = setInterval(async () => {
try { try {
// 獲取最新的加密貨幣數據 const now = new Date();
if (cachedPrices && now - lastFetchTime < CACHE_DURATION) {
socket.emit("data", cachedPrices);
console.log(`[${now.toISOString()}]📦 Push Cached Data`);
return;
}
// Get latest data
const response = await axios.get( const response = await axios.get(
"https://api.coingecko.com/api/v3/simple/price", "https://api.coingecko.com/api/v3/simple/price",
{ {
@@ -117,57 +134,59 @@ io.on("connection", (socket) => {
} }
); );
// 向該客戶端發送數據(實時更新) const data = {
socket.emit("data", {
type: "crypto", type: "crypto",
timestamp: new Date(), timestamp: new Date(),
prices: response.data, prices: response.data,
}); };
cachedPrices = data;
lastFetchTime = now;
socket.emit("data", data);
} catch (error) { } catch (error) {
console.error("❌ 定時推送出錯:", error.message); console.error("❌ Error on pushing:", error.message);
} }
}, 5000); // 每5000毫秒5秒執行一次 }, CACHE_DURATION); // run every 30 seconds
// ========== 客戶端斷開連接 ========== // ========== Client Disconnected ==========
// 當客戶端斷開連接時觸發 // Trigger when client disconnected
socket.on("disconnect", () => { socket.on("disconnect", () => {
connectedClients--; connectedClients--;
console.log(`客戶端已斷開: ${socket.id}`); console.log(`Client Disconnected: ${socket.id}`);
console.log(`📊 當前連接數: ${connectedClients}`); console.log(`📊 Current Number of Clients: ${connectedClients}`);
// 向所有客戶端廣播更新的連接數 // Broadcast number of clients
io.emit("clientCount", connectedClients); io.emit("clientCount", connectedClients);
// 清除該客戶端的定時器 // Clear client's interval
clearInterval(dataInterval); clearInterval(dataInterval);
}); });
}); });
// ========== 啟動服務器 ========== // ========== Start service ==========
// 從環境變數獲取端口或使用默認5000
const PORT = process.env.PORT || 5000; const PORT = process.env.PORT || 5000;
// 啟動伺服器
server.listen(PORT, () => { server.listen(PORT, () => {
console.log(""); console.log("");
console.log("═══════════════════════════════════════"); console.log("═══════════════════════════════════════");
console.log(`服務器運行在: http://localhost:${PORT}`); console.log(`Server running on: http://localhost:${PORT}`);
console.log("📡 WebSocket 已準備接收連接"); console.log("📡 WebSocket ready to connect");
console.log("🔗 CORS 來源:", process.env.CORS_ORIGIN || "*"); console.log("🔗 CORS Source:", process.env.CORS_ORIGIN || "*");
console.log("═══════════════════════════════════════"); console.log("═══════════════════════════════════════");
console.log(""); console.log("");
}); });
// ========== 錯誤處理 ========== // ========== Error Handling ==========
// 處理未捕獲的異常 // Exception Handling
process.on("unhandledRejection", (err) => { process.on("unhandledRejection", (err) => {
console.error("❌ 未捕獲的異常:", err); console.error("❌ Exceptions:", err);
}); });
process.on("uncaughtException", (err) => { process.on("uncaughtException", (err) => {
console.error("❌ 未捕獲的異常:", err); console.error("❌ Exceptions:", err);
process.exit(1); process.exit(1);
}); });