initial commit

This commit is contained in:
Bhavnoor Singh Saroya 2025-01-07 04:45:03 -08:00
commit b25eb51ff0
280 changed files with 178550 additions and 0 deletions

164
manager-service/app.js Normal file
View file

@ -0,0 +1,164 @@
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const { WebSocketServer } = require('ws');
const axios = require('axios');
const { env } = require('process');
const DATABASE_SERVICE_URL = env.DATABASE_SERVICE_URL;
const FRONTEND_SERVICE_URL = env.FRONTEND_SERVICE_URL;
const UPLOADER_SERVICE_URL = env.UPLOADER_SERVICE_URL;
class Machine {
constructor(username, address) {
this.username = username;
this.address = address;
this.cache = null;
this.lastPingTime = null;
}
async ping() {
try {
const response = await axios.get(`http://${this.address}:5000/`);
this.cache = response.data;
this.lastPingTime = Date.now();
} catch (error) {
console.error(`Failed to ping machine ${this.username}: ${error.message}`);
}
}
getCachedResponse() {
return this.cache;
}
}
// Application setup
const app = express();
app.use(express.json());
const machines = new Map();
// Load machines from database on startup
(async () => {
try {
const { data } = await axios.get('http://database-service/machines'); // Replace with our database endpoint
data.forEach(({ username, machineAddress }) => {
const machine = new Machine(username, machineAddress);
machines.set(username, machine);
machine.ping(); // Initial ping to populate cache
});
console.log('Loaded machines from database.');
} catch (error) {
console.error('Failed to load machines from database:', error.message);
}
})();
// Register a new user and their machine
app.post('/register', async (req, res) => {
const { username, machineAddress } = req.body;
if (!username || !machineAddress) {
return res.status(400).json({ error: 'Username and machineAddress are required' });
}
const machine = new Machine(username, machineAddress);
throw new Error('need to register machine in database');
// register machine in db asap and await success
machines.set(username, machine);
await machine.ping();
res.json({ message: `User ${username} registered with address ${machineAddress}` });
});
// HTTP proxy for dynamic routing
app.use('/:username/:path/*', async (req, res, next) => { //ensure this will work with all paths
//update to use gateway signature or jwt
const username = req.params.username;
const machine = machines.get(username);
if (!machine) {
return res.status(404).json({ error: 'User not found' });
}
const targetPort = req.params.path === ('upload' || 'file' || 'reserved') ? 8080 : 5000; // 3 paths that hit sync agent, rest hit bsnake
const proxy = createProxyMiddleware({
target: `http://${machine.address}:${targetPort}`,
changeOrigin: true,
pathRewrite: { [`^/${username}`]: '' }, // remove username from path before forwarding
ws: true,
onProxyReq: () => {
console.log(`Proxying request to ${machine.address}:${targetPort}`);
},
});
proxy(req, res, next);
});
// External route proxying, update to use wildcards for mapping to other microservices
const externalRoutes = {
'login': 'frontend_service_url',
'signup': 'database_service_url',
'signin': 'database_service_url',
'upload': 'uploader_service_url',
};
Object.entries(externalRoutes).forEach(([route, target]) => {
app.use(`/${route}`, createProxyMiddleware({
target: target,
changeOrigin: true,
pathRewrite: { [`^/${route}`]: '' }, // see if path needs to be rewritten
}));
});
// WebSocket server for forwarding connections
const wss = new WebSocketServer({ noServer: true });
wss.on('connection', (ws, req) => {
const username = req.url.split('/')[1];
const machine = machines.get(username);
if (!machine) {
ws.close();
console.error(`WebSocket connection failed: User ${username} not found`);
return;
}
const target = `ws://${machine.address}:8080`;
const proxySocket = new WebSocket(target);
proxySocket.on('open', () => {
console.log(`Connected to WebSocket for user ${username}`);
});
proxySocket.on('message', (data) => {
ws.send(data);
});
proxySocket.on('close', () => {
ws.close();
});
proxySocket.on('error', (error) => {
console.error(`WebSocket error: ${error}`);
ws.close();
});
ws.on('message', (data) => {
proxySocket.send(data);
});
ws.on('close', () => {
proxySocket.close();
});
});
// Integrate WebSocket server with the HTTP server
const server = app.listen(3000, () => {
console.log('Reverse proxy server running on http://localhost:3000');
});
server.on('upgrade', (req, socket, head) => {
wss.handleUpgrade(req, socket, head, (ws) => {
wss.emit('connection', ws, req);
});
});