Files
crm.clientright.ru/crm_extensions/file_storage/websocket-server/server.js
Fedor 9245768987 🚀 CRM Files Migration & Real-time Features
 Features:
- Migrated ALL files to new S3 structure (Projects, Contacts, Accounts, HelpDesk, Invoice, etc.)
- Added Nextcloud folder buttons to ALL modules
- Fixed Nextcloud editor integration
- WebSocket server for real-time updates
- Redis Pub/Sub integration
- File path manager for organized storage
- Redis caching for performance (Functions.php)

📁 New Structure:
Documents/Project/ProjectName_ID/file_docID.ext
Documents/Contacts/FirstName_LastName_ID/file_docID.ext
Documents/Accounts/AccountName_ID/file_docID.ext

🔧 Technical:
- FilePathManager for standardized paths
- S3StorageService integration
- WebSocket server (Node.js + Docker)
- Redis cache for getBasicModuleInfo()
- Predis library for Redis connectivity

📝 Scripts:
- Migration scripts for all modules
- Test pages for WebSocket/SSE/Polling
- Documentation (MIGRATION_*.md, REDIS_*.md)

🎯 Result: 15,000+ files migrated successfully!
2025-10-24 19:59:28 +03:00

161 lines
4.7 KiB
JavaScript

const WebSocket = require('ws');
const redis = require('redis');
// Конфигурация
const REDIS_HOST = process.env.REDIS_HOST || 'host.docker.internal';
const REDIS_PORT = process.env.REDIS_PORT || 6379;
const REDIS_PASSWORD = process.env.REDIS_PASSWORD || 'CRM_Redis_Pass_2025_Secure!';
const WS_PORT = process.env.WS_PORT || 3000;
const REDIS_CHANNEL = 'crm:file:events';
console.log('🚀 Starting CRM WebSocket Server...');
console.log(`📡 Redis: ${REDIS_HOST}:${REDIS_PORT}`);
console.log(`🔌 WebSocket: 0.0.0.0:${WS_PORT}`);
console.log(`📢 Channel: ${REDIS_CHANNEL}`);
// Создаем WebSocket сервер
const wss = new WebSocket.Server({
port: WS_PORT,
perMessageDeflate: false
});
// Подключаемся к Redis для Pub/Sub
const subscriber = redis.createClient({
socket: {
host: REDIS_HOST,
port: REDIS_PORT
},
password: REDIS_PASSWORD
});
subscriber.on('error', (err) => {
console.error('❌ Redis Subscriber Error:', err);
});
subscriber.on('connect', () => {
console.log('✅ Redis Subscriber connected');
});
// Подключаемся и подписываемся на канал
(async () => {
try {
await subscriber.connect();
await subscriber.subscribe(REDIS_CHANNEL, (message) => {
console.log(`📨 Received from Redis: ${message.substring(0, 100)}...`);
// Отправляем всем WebSocket клиентам
let sentCount = 0;
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
sentCount++;
}
});
console.log(`📤 Sent to ${sentCount} WebSocket clients`);
});
console.log(`✅ Subscribed to Redis channel: ${REDIS_CHANNEL}`);
} catch (err) {
console.error('❌ Failed to connect to Redis:', err);
process.exit(1);
}
})();
// WebSocket сервер
wss.on('connection', (ws, req) => {
const clientIp = req.socket.remoteAddress;
console.log(`🔗 New WebSocket connection from ${clientIp}`);
console.log(`👥 Total clients: ${wss.clients.size}`);
// Отправляем приветственное сообщение
ws.send(JSON.stringify({
type: 'connected',
data: {
message: 'Connected to CRM WebSocket Server',
channel: REDIS_CHANNEL,
timestamp: Date.now()
}
}));
// Heartbeat
ws.isAlive = true;
ws.on('pong', () => {
ws.isAlive = true;
});
// Обработка сообщений от клиента
ws.on('message', (message) => {
console.log(`📩 Message from client: ${message}`);
try {
const data = JSON.parse(message);
// Обработка ping
if (data.type === 'ping') {
ws.send(JSON.stringify({
type: 'pong',
timestamp: Date.now()
}));
}
} catch (err) {
console.error('❌ Invalid message format:', err);
}
});
// Обработка закрытия соединения
ws.on('close', (code, reason) => {
console.log(`🔌 WebSocket disconnected: ${code} - ${reason}`);
console.log(`👥 Total clients: ${wss.clients.size}`);
});
// Обработка ошибок
ws.on('error', (err) => {
console.error('❌ WebSocket error:', err);
});
});
// Heartbeat для проверки живых соединений
const heartbeat = setInterval(() => {
wss.clients.forEach((ws) => {
if (ws.isAlive === false) {
console.log('💔 Terminating dead connection');
return ws.terminate();
}
ws.isAlive = false;
ws.ping();
});
}, 30000); // Каждые 30 секунд
// Обработка завершения
wss.on('close', () => {
clearInterval(heartbeat);
subscriber.quit();
console.log('🛑 WebSocket server stopped');
});
// Обработка сигналов завершения
process.on('SIGTERM', () => {
console.log('🛑 SIGTERM received, closing server...');
wss.close(() => {
subscriber.quit();
process.exit(0);
});
});
process.on('SIGINT', () => {
console.log('🛑 SIGINT received, closing server...');
wss.close(() => {
subscriber.quit();
process.exit(0);
});
});
console.log('✅ WebSocket server started successfully!');
console.log(`🎯 Ready to receive events from Redis and broadcast to ${wss.clients.size} clients`);