improvent for invites

This commit is contained in:
Raven Scott
2025-12-17 21:13:46 -05:00
parent d3b61e9823
commit d1ee8b979a
6 changed files with 477 additions and 75 deletions
@@ -8,6 +8,7 @@ const { trackRequest, trackRequestWithTiming } = require('../../../maintenance/m
const { createErrorResponse } = require('../../../infrastructure/error_handler');
const execAsync = promisify(exec);
const { state } = require('../../../infrastructure/state');
async function handleDiagnosticsRoutes(req, res) {
const urlPath = req.urlPath || new URL(req.url, `https://${req.headers.host}`).pathname;
@@ -502,6 +503,30 @@ async function handleDiagnosticsRoutes(req, res) {
return true;
}
// GET /api/diagnostics/invites
if (method === 'GET' && urlPath === '/api/diagnostics/invites') {
try {
if (!state.diagnoseInviteIssues) {
res.writeHead(503, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invite diagnostics not available - system not fully initialized' }));
trackRequest(urlPath, false);
return true;
}
const diagnostics = state.diagnoseInviteIssues();
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(diagnostics));
trackRequest(urlPath, true);
return true;
} catch (err) {
logError('DiagnosticsRoute', `Invite diagnostics error: ${err.message}`);
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: err.message }));
trackRequest(urlPath, false);
return true;
}
}
return false;
}
+9
View File
@@ -872,6 +872,15 @@
<button onclick="testConnection()" class="w-full px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Test Connection</button>
</div>
</div>
<!-- Invite Diagnostics -->
<div class="theme-glass rounded-lg p-4 col-span-1 lg:col-span-2">
<h4 class="text-lg font-semibold mb-4">Invite Diagnostics</h4>
<div class="space-y-3">
<p class="text-sm text-gray-400">Diagnose invite system issues including channel health, peer connections, and pending acknowledgments.</p>
<button onclick="runInviteDiagnostics()" class="w-full px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Run Invite Diagnostics</button>
</div>
</div>
</div>
<!-- Results -->
@@ -666,6 +666,176 @@ function closeDiagnosticResult(resultId) {
}
}
// Run invite diagnostics
async function runInviteDiagnostics() {
const buttonEl = document.querySelector('button[onclick="runInviteDiagnostics()"]');
// Show loading indicator
if (buttonEl) {
buttonEl.disabled = true;
buttonEl.innerHTML = '<span class="inline-block animate-spin rounded-full h-4 w-4 border-t-2 border-white mr-2"></span>Diagnosing...';
}
try {
const response = await fetch('/api/diagnostics/invites');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
const diagnostics = await response.json();
displayInviteDiagnostics(diagnostics);
} catch (err) {
console.error('Invite diagnostics failed:', err);
if (window.showNotification) window.showNotification('Invite diagnostics failed: ' + err.message, 'error');
} finally {
// Restore button
if (buttonEl) {
buttonEl.disabled = false;
buttonEl.innerHTML = 'Run Invite Diagnostics';
}
}
}
// Display invite diagnostics results
function displayInviteDiagnostics(diagnostics) {
const resultId = 'invite-diagnostics-' + Date.now();
const resultDiv = document.createElement('div');
resultDiv.id = resultId;
resultDiv.className = 'bg-gray-800 rounded-lg p-4 mb-4 border border-gray-600';
const headerDiv = document.createElement('div');
headerDiv.className = 'flex justify-between items-center mb-3';
const titleDiv = document.createElement('div');
titleDiv.className = 'flex items-center';
titleDiv.innerHTML = `
<h3 class="text-lg font-semibold text-white">Invite Diagnostics</h3>
<span class="ml-2 text-sm text-gray-400">${new Date(diagnostics.timestamp).toLocaleString()}</span>
`;
const buttonContainer = document.createElement('div');
buttonContainer.className = 'flex space-x-2';
headerDiv.appendChild(titleDiv);
headerDiv.appendChild(buttonContainer);
const contentDiv = document.createElement('div');
contentDiv.className = 'space-y-3';
// Basic info
contentDiv.innerHTML += `
<div class="grid grid-cols-2 gap-4">
<div class="bg-gray-700 rounded p-3">
<div class="text-sm text-gray-400">Node Type</div>
<div class="text-lg font-semibold text-white">${diagnostics.nodeType}</div>
</div>
<div class="bg-gray-700 rounded p-3">
<div class="text-sm text-gray-400">DNS Pass Initialized</div>
<div class="text-lg font-semibold ${diagnostics.dnsPassInitialized ? 'text-green-400' : 'text-red-400'}">
${diagnostics.dnsPassInitialized ? 'Yes' : 'No'}
</div>
</div>
</div>
`;
// Peer connections
contentDiv.innerHTML += `
<div class="bg-gray-700 rounded p-3">
<div class="text-sm text-gray-400 mb-2">Peer Connections</div>
<div class="text-lg font-semibold text-white">${diagnostics.connectedPeers} connected</div>
</div>
`;
// Failed peers
if (diagnostics.failedInvitePeers.length > 0) {
contentDiv.innerHTML += `
<div class="bg-red-900 border border-red-600 rounded p-3">
<div class="text-sm text-red-400 mb-2">Failed Invite Peers</div>
<div class="text-sm text-red-300">${diagnostics.failedInvitePeers.join(', ')}</div>
</div>
`;
}
// Pending ACKs
if (diagnostics.pendingInviteAcks.length > 0) {
contentDiv.innerHTML += `
<div class="bg-yellow-900 border border-yellow-600 rounded p-3">
<div class="text-sm text-yellow-400 mb-2">Pending Invite Acknowledgments</div>
<div class="text-sm text-yellow-300">${diagnostics.pendingInviteAcks.length} pending</div>
</div>
`;
}
// Connection issues
if (diagnostics.connectionIssues.length > 0) {
contentDiv.innerHTML += `
<div class="bg-orange-900 border border-orange-600 rounded p-3">
<div class="text-sm text-orange-400 mb-2">Connection Issues</div>
<div class="text-sm text-orange-300">${diagnostics.connectionIssues.join('<br>')}</div>
</div>
`;
}
// Channel health summary
const healthyInviteChannels = Object.values(diagnostics.inviteChannels).filter(ch => ch.opened).length;
const healthyRequestChannels = Object.values(diagnostics.requestChannels).filter(ch => ch.opened).length;
contentDiv.innerHTML += `
<div class="bg-gray-700 rounded p-3">
<div class="text-sm text-gray-400 mb-2">Channel Health</div>
<div class="grid grid-cols-2 gap-4 text-sm">
<div>
<span class="text-gray-300">Invite Channels:</span>
<span class="ml-2 font-semibold ${healthyInviteChannels === diagnostics.connectedPeers ? 'text-green-400' : 'text-yellow-400'}">
${healthyInviteChannels}/${diagnostics.connectedPeers} healthy
</span>
</div>
<div>
<span class="text-gray-300">Request Channels:</span>
<span class="ml-2 font-semibold ${healthyRequestChannels === diagnostics.connectedPeers ? 'text-green-400' : 'text-yellow-400'}">
${healthyRequestChannels}/${diagnostics.connectedPeers} healthy
</span>
</div>
</div>
</div>
`;
// Recommendations
if (diagnostics.recommendations.length > 0) {
contentDiv.innerHTML += `
<div class="bg-blue-900 border border-blue-600 rounded p-3">
<div class="text-sm text-blue-400 mb-2">Recommendations</div>
<ul class="text-sm text-blue-300 space-y-1">
${diagnostics.recommendations.map(rec => `<li>• ${rec}</li>`).join('')}
</ul>
</div>
`;
}
resultDiv.appendChild(headerDiv);
resultDiv.appendChild(contentDiv);
// Add close button
const closeBtn = document.createElement('button');
closeBtn.id = `close-btn-${resultId}`;
closeBtn.className = 'ml-2 px-2 py-1 text-xs bg-gray-500 text-white rounded hover:bg-gray-600';
closeBtn.textContent = 'Close';
closeBtn.addEventListener('click', () => {
closeDiagnosticResult(resultId);
});
buttonContainer.appendChild(closeBtn);
// Add to diagnostics results container
const resultsContainer = document.getElementById('diagnostics-results');
if (resultsContainer) {
resultsContainer.insertBefore(resultDiv, resultsContainer.firstChild);
}
// Scroll to top of results
resultDiv.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
// Setup Enter key handlers for diagnostics forms
function setupDiagnosticsEnterHandlers() {
// Return early if handlers have already been set up
@@ -756,6 +926,7 @@ window.fetchBandwidth = fetchBandwidth;
window.renderDiagnostics = renderDiagnostics;
window.cancelStream = cancelStream;
window.closeDiagnosticResult = closeDiagnosticResult;
window.runInviteDiagnostics = runInviteDiagnostics;
// Setup Enter key handlers when DOM is ready
if (document.readyState === 'loading') {