forked from snxraven/p2ns
reorg
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Global Profile Plugin - WebSocket Management
|
||||
*
|
||||
* Handles WebSocket connections, broadcasting, and real-time updates
|
||||
*/
|
||||
|
||||
const sdk = require('../../includes/plugins/sdk');
|
||||
const { getProfileFromDB, getAllProfilesFromDB } = require('./database');
|
||||
|
||||
/**
|
||||
* Broadcast profile update to WebSocket clients and all peers
|
||||
*/
|
||||
function broadcastProfileUpdate(data) {
|
||||
const message = {
|
||||
...data,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
sdk.log.debug('global.profile', `Broadcasting profile update: ${data.type} for peer ${data.profile?.peerId || data.peerId}`);
|
||||
|
||||
// Broadcast to local WebSocket clients
|
||||
const localClients = sdk.websocket.broadcast(message);
|
||||
sdk.log.debug('global.profile', `Sent to ${localClients} local WebSocket client(s)`);
|
||||
|
||||
// Broadcast to all connected P2P peers via channels
|
||||
// Peers will forward to their local WebSocket clients
|
||||
try {
|
||||
const peerCount = sdk.channels.broadcast('profile-updates', message);
|
||||
if (peerCount > 0) {
|
||||
sdk.log.debug('global.profile', `Sent to ${peerCount} peer(s) via P2P channels`);
|
||||
}
|
||||
} catch (err) {
|
||||
sdk.log.debug('global.profile', `Error broadcasting to peers: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get replication status for HyperDB (avatars are stored in HyperDB)
|
||||
*/
|
||||
function getReplicationStatus() {
|
||||
const status = {
|
||||
hyperdb: { active: false, peers: 0 }
|
||||
};
|
||||
|
||||
try {
|
||||
// Get HyperDB replication status
|
||||
const dbReplication = sdk.db.replication;
|
||||
if (dbReplication) {
|
||||
const dbStatus = dbReplication.getStatus();
|
||||
if (dbStatus) {
|
||||
status.hyperdb = {
|
||||
active: dbStatus.active,
|
||||
peers: dbStatus.peers || 0
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
sdk.log.debug('global.profile', `Error getting HyperDB replication status: ${err.message}`);
|
||||
}
|
||||
|
||||
// Avatars are now stored in HyperDB, so no separate Hyperdrive status needed
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup WebSocket handlers
|
||||
*/
|
||||
function setupWebSocketHandlers() {
|
||||
// Initialize WebSocket server
|
||||
if (!sdk.websocket.initialize()) {
|
||||
sdk.log.warn('global.profile', 'Failed to initialize WebSocket server');
|
||||
return;
|
||||
}
|
||||
|
||||
// Track previous replication status to detect changes
|
||||
let previousReplicationStatus = JSON.stringify(getReplicationStatus());
|
||||
|
||||
sdk.websocket.on('connection', async (ws) => {
|
||||
const clientCount = sdk.websocket.getClientCount();
|
||||
sdk.log.info('global.profile', `WebSocket client connected (${clientCount} total)`);
|
||||
|
||||
// Initial profile data is now loaded via REST API
|
||||
// WebSocket is only used for real-time updates (profile-update, profile-deleted)
|
||||
// The request-profiles handler below is kept for backward compatibility
|
||||
});
|
||||
|
||||
sdk.websocket.on('message', async (ws, message) => {
|
||||
try {
|
||||
if (message.type === 'request-profiles') {
|
||||
try {
|
||||
const profiles = await getAllProfilesFromDB();
|
||||
sdk.websocket.send(ws, {
|
||||
type: 'profiles',
|
||||
profiles: profiles.map(p => {
|
||||
try {
|
||||
p.customFields = p.customFields ? JSON.parse(p.customFields) : {};
|
||||
p.tags = p.tags ? JSON.parse(p.tags) : [];
|
||||
} catch (err) {
|
||||
p.customFields = {};
|
||||
p.tags = [];
|
||||
}
|
||||
p.online = sdk.state.peerIds.includes(p.peerId);
|
||||
return p;
|
||||
}),
|
||||
timestamp: Date.now()
|
||||
});
|
||||
} catch (err) {
|
||||
sdk.log.error('global.profile', `Error getting profiles for WebSocket: ${err.message}`);
|
||||
sdk.websocket.send(ws, {
|
||||
type: 'profiles',
|
||||
profiles: [],
|
||||
timestamp: Date.now(),
|
||||
error: 'Database not ready'
|
||||
});
|
||||
}
|
||||
} else if (message.type === 'request-replication-status') {
|
||||
// Send current replication status
|
||||
const replicationStatus = getReplicationStatus();
|
||||
sdk.websocket.send(ws, {
|
||||
type: 'replication-status',
|
||||
data: replicationStatus,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
sdk.log.error('global.profile', `Error handling WebSocket message: ${err.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Broadcast replication status updates periodically
|
||||
setInterval(() => {
|
||||
const clientCount = sdk.websocket.getClientCount();
|
||||
if (clientCount > 0) {
|
||||
const currentStatus = getReplicationStatus();
|
||||
const currentStatusStr = JSON.stringify(currentStatus);
|
||||
|
||||
// Only broadcast if status changed
|
||||
if (currentStatusStr !== previousReplicationStatus) {
|
||||
const sent = sdk.websocket.broadcast({
|
||||
type: 'replication-status',
|
||||
data: currentStatus,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
previousReplicationStatus = currentStatusStr;
|
||||
sdk.log.debug('global.profile', `Broadcasted replication status update to ${sent} client(s)`);
|
||||
}
|
||||
}
|
||||
}, 2000); // Check every 2 seconds
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
broadcastProfileUpdate,
|
||||
getReplicationStatus,
|
||||
setupWebSocketHandlers
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user