UNPKG

bigbasealpha

Version:

Enterprise-Grade NoSQL Database System with Modular Logger & Offline HSM Security - Complete database platform with professional text-based logging, encryption, caching, indexing, JWT authentication, auto-generated REST API, real-time dashboard, and maste

581 lines (493 loc) 18.4 kB
const express = require('express'); const cors = require('cors'); const path = require('path'); const fs = require('fs'); const app = express(); const PORT = process.env.PORT || 3000; // Middleware app.use(cors()); app.use(express.json()); app.use(express.static(path.join(__dirname, '../src/dashboard'))); // In-memory data storage for demo let streams = []; let processors = []; let analytics = []; let events = []; let systemStats = { startTime: Date.now(), totalEvents: 0, totalProcessed: 0, errors: 0 }; // Generate sample data function generateSampleData() { // Sample streams streams = [ { id: 'user-events', type: 'unbounded', format: 'json', description: 'User activity events', active: true, eventCount: 1250, createdAt: new Date(Date.now() - 86400000).toISOString() }, { id: 'sensor-data', type: 'unbounded', format: 'json', description: 'IoT sensor readings', active: true, eventCount: 5830, createdAt: new Date(Date.now() - 43200000).toISOString() }, { id: 'transaction-stream', type: 'bounded', format: 'json', description: 'Financial transactions', active: false, eventCount: 890, createdAt: new Date(Date.now() - 21600000).toISOString() } ]; // Sample processors processors = [ { id: 'filter-1', streamId: 'user-events', type: 'filter', function: 'event => event.action === "click"', active: true, processedCount: 450, createdAt: new Date(Date.now() - 3600000).toISOString() }, { id: 'aggregator-1', streamId: 'sensor-data', type: 'aggregate', function: 'events => events.reduce((sum, e) => sum + e.value, 0)', active: true, processedCount: 1200, createdAt: new Date(Date.now() - 7200000).toISOString() } ]; // Sample analytics analytics = [ { id: 'user-clicks-agg', name: 'User Clicks Aggregation', type: 'aggregation', streamId: 'user-events', lastResult: '245 clicks/hour', createdAt: new Date(Date.now() - 1800000).toISOString() }, { id: 'temp-avg', name: 'Temperature Average', type: 'continuous_query', streamId: 'sensor-data', lastResult: '23.5°C', createdAt: new Date(Date.now() - 2700000).toISOString() } ]; console.log('✅ Sample data generated for Stream Processing API'); } // Initialize sample data generateSampleData(); // Utility functions function generateId() { return Date.now().toString(36) + Math.random().toString(36).substr(2); } function updateSystemStats() { systemStats.totalEvents = events.length; systemStats.totalProcessed = processors.reduce((sum, p) => sum + (p.processedCount || 0), 0); } // ===== STREAM PROCESSING API ENDPOINTS ===== // Get stream analytics overview app.get('/api/stream/analytics', (req, res) => { updateSystemStats(); const analytics = { totalStreams: streams.length, activeStreams: streams.filter(s => s.active).length, eventsPerSecond: Math.floor(Math.random() * 100) + 50, totalProcessors: processors.length, runningProcessors: processors.filter(p => p.active).length, processingRate: Math.floor(Math.random() * 500) + 200, activeWindows: Math.floor(Math.random() * 10) + 3, continuousQueries: analytics.filter(a => a.type === 'continuous_query').length, streamJoins: Math.floor(Math.random() * 5) + 1, avgLatency: Math.floor(Math.random() * 50) + 10, throughput: Math.floor(Math.random() * 100) + 50, memoryUsage: Math.floor(Math.random() * 30) + 45 }; res.json(analytics); }); // Stream management endpoints app.get('/api/streams', (req, res) => { res.json(streams); }); app.post('/api/streams', (req, res) => { const { id, type, format, description } = req.body; if (!id) { return res.status(400).json({ error: 'Stream ID is required' }); } if (streams.find(s => s.id === id)) { return res.status(409).json({ error: 'Stream with this ID already exists' }); } const newStream = { id, type: type || 'unbounded', format: format || 'json', description: description || '', active: true, eventCount: 0, createdAt: new Date().toISOString() }; streams.push(newStream); res.status(201).json(newStream); }); app.get('/api/streams/:id', (req, res) => { const stream = streams.find(s => s.id === req.params.id); if (!stream) { return res.status(404).json({ error: 'Stream not found' }); } res.json(stream); }); app.delete('/api/streams/:id', (req, res) => { const index = streams.findIndex(s => s.id === req.params.id); if (index === -1) { return res.status(404).json({ error: 'Stream not found' }); } const deletedStream = streams.splice(index, 1)[0]; // Also remove related processors processors = processors.filter(p => p.streamId !== req.params.id); res.json({ message: 'Stream deleted successfully', stream: deletedStream }); }); // Publish event to stream app.post('/api/streams/:id/publish', (req, res) => { const stream = streams.find(s => s.id === req.params.id); if (!stream) { return res.status(404).json({ error: 'Stream not found' }); } const event = { id: generateId(), streamId: req.params.id, data: req.body, timestamp: new Date().toISOString() }; events.push(event); stream.eventCount = (stream.eventCount || 0) + 1; // Simulate processing by relevant processors const streamProcessors = processors.filter(p => p.streamId === req.params.id && p.active); streamProcessors.forEach(processor => { processor.processedCount = (processor.processedCount || 0) + 1; }); res.json({ eventId: event.id, message: 'Event published successfully', processedBy: streamProcessors.length }); }); // Processor management endpoints app.get('/api/processors', (req, res) => { res.json(processors); }); app.post('/api/processors', (req, res) => { const { streamId, type, function: processingFunction } = req.body; if (!streamId || !type) { return res.status(400).json({ error: 'StreamId and type are required' }); } const stream = streams.find(s => s.id === streamId); if (!stream) { return res.status(404).json({ error: 'Target stream not found' }); } const newProcessor = { id: generateId(), streamId, type, function: processingFunction || '', active: true, processedCount: 0, createdAt: new Date().toISOString() }; processors.push(newProcessor); res.status(201).json(newProcessor); }); app.delete('/api/processors/:id', (req, res) => { const index = processors.findIndex(p => p.id === req.params.id); if (index === -1) { return res.status(404).json({ error: 'Processor not found' }); } const deletedProcessor = processors.splice(index, 1)[0]; res.json({ message: 'Processor deleted successfully', processor: deletedProcessor }); }); // Analytics endpoints app.get('/api/analytics', (req, res) => { res.json(analytics); }); app.post('/api/analytics/aggregation', (req, res) => { const { sourceStreamId, config } = req.body; if (!sourceStreamId) { return res.status(400).json({ error: 'Source stream ID is required' }); } const sourceStream = streams.find(s => s.id === sourceStreamId); if (!sourceStream) { return res.status(404).json({ error: 'Source stream not found' }); } const outputStreamId = `${sourceStreamId}_aggregation_${Date.now()}`; // Create output stream const outputStream = { id: outputStreamId, type: 'bounded', format: 'json', description: `Aggregation results for ${sourceStreamId}`, active: true, eventCount: 0, createdAt: new Date().toISOString() }; streams.push(outputStream); // Create analytics entry const newAnalytics = { id: generateId(), name: `${config.type} Aggregation`, type: 'aggregation', streamId: sourceStreamId, outputStreamId, config, lastResult: 'Calculating...', createdAt: new Date().toISOString() }; analytics.push(newAnalytics); res.status(201).json({ message: 'Aggregation stream created successfully', sourceStreamId, outputStreamId, analytics: newAnalytics }); }); app.delete('/api/analytics/:id', (req, res) => { const index = analytics.findIndex(a => a.id === req.params.id); if (index === -1) { return res.status(404).json({ error: 'Analytics not found' }); } const deletedAnalytics = analytics.splice(index, 1)[0]; res.json({ message: 'Analytics deleted successfully', analytics: deletedAnalytics }); }); // Performance monitoring endpoints app.get('/api/stream/performance', (req, res) => { const performance = { cpuUsage: Math.floor(Math.random() * 40) + 30, memoryUsage: Math.floor(Math.random() * 200) + 150, networkIO: Math.floor(Math.random() * 1000) + 500, latency: Math.floor(Math.random() * 50) + 10, throughput: Math.floor(Math.random() * 100) + 50, errorRate: Math.random() * 2, timestamp: new Date().toISOString() }; res.json(performance); }); app.get('/api/stream/status', (req, res) => { const uptime = Date.now() - systemStats.startTime; const uptimeMinutes = Math.floor(uptime / 60000); const status = { engineStatus: 'running', uptime: uptimeMinutes, totalStreams: streams.length, activeStreams: streams.filter(s => s.active).length, totalProcessors: processors.length, runningProcessors: processors.filter(p => p.active).length, totalEvents: systemStats.totalEvents, totalProcessed: systemStats.totalProcessed, errorRate: systemStats.errors / Math.max(systemStats.totalEvents, 1) * 100, timestamp: new Date().toISOString() }; res.json(status); }); // Window management endpoints app.post('/api/windows', (req, res) => { const { streamId, type, size, trigger } = req.body; if (!streamId || !type) { return res.status(400).json({ error: 'StreamId and type are required' }); } const stream = streams.find(s => s.id === streamId); if (!stream) { return res.status(404).json({ error: 'Target stream not found' }); } const newWindow = { id: generateId(), streamId, type, size: size || 5000, trigger: trigger || 'time', active: true, triggeredCount: 0, createdAt: new Date().toISOString() }; res.status(201).json(newWindow); }); // Continuous query endpoints app.post('/api/queries/continuous', (req, res) => { const { queryId, streamId, query } = req.body; if (!queryId || !streamId) { return res.status(400).json({ error: 'QueryId and streamId are required' }); } const stream = streams.find(s => s.id === streamId); if (!stream) { return res.status(404).json({ error: 'Target stream not found' }); } const newQuery = { id: queryId, streamId, query: query || '', active: true, resultCount: 0, createdAt: new Date().toISOString() }; // Add to analytics analytics.push({ id: generateId(), name: `Continuous Query: ${queryId}`, type: 'continuous_query', streamId, queryId, lastResult: 'Executing...', createdAt: new Date().toISOString() }); res.status(201).json(newQuery); }); // Stream join endpoints app.post('/api/joins', (req, res) => { const { leftStreamId, rightStreamId, joinType, condition } = req.body; if (!leftStreamId || !rightStreamId) { return res.status(400).json({ error: 'Both stream IDs are required' }); } const leftStream = streams.find(s => s.id === leftStreamId); const rightStream = streams.find(s => s.id === rightStreamId); if (!leftStream || !rightStream) { return res.status(404).json({ error: 'One or both streams not found' }); } const joinId = generateId(); const outputStreamId = `join_${leftStreamId}_${rightStreamId}_${joinId}`; // Create output stream for join results const outputStream = { id: outputStreamId, type: 'unbounded', format: 'json', description: `Join results: ${leftStreamId} ${joinType || 'inner'} ${rightStreamId}`, active: true, eventCount: 0, createdAt: new Date().toISOString() }; streams.push(outputStream); const joinProcessor = { id: joinId, type: 'join', leftStreamId, rightStreamId, outputStreamId, joinType: joinType || 'inner', condition: condition || '', active: true, processedCount: 0, createdAt: new Date().toISOString() }; res.status(201).json({ message: 'Stream join created successfully', join: joinProcessor, outputStream }); }); // Dashboard routes app.get('/', (req, res) => { res.sendFile(path.join(__dirname, '../src/dashboard/stream-dashboard.html')); }); app.get('/dashboard', (req, res) => { res.sendFile(path.join(__dirname, '../src/dashboard/stream-dashboard.html')); }); app.get('/stream-dashboard', (req, res) => { res.sendFile(path.join(__dirname, '../src/dashboard/stream-dashboard.html')); }); // Health check endpoint app.get('/health', (req, res) => { res.json({ status: 'healthy', timestamp: new Date().toISOString(), uptime: Date.now() - systemStats.startTime, streams: streams.length, processors: processors.length, events: events.length }); }); // Error handling middleware app.use((err, req, res, next) => { console.error('Server error:', err); systemStats.errors++; res.status(500).json({ error: 'Internal server error', message: err.message, timestamp: new Date().toISOString() }); }); // 404 handler app.use((req, res) => { res.status(404).json({ error: 'Endpoint not found', path: req.path, method: req.method, timestamp: new Date().toISOString() }); }); // Simulate real-time events function simulateRealTimeEvents() { setInterval(() => { if (streams.length > 0) { const randomStream = streams[Math.floor(Math.random() * streams.length)]; if (randomStream.active) { const sampleEvent = { id: generateId(), streamId: randomStream.id, data: { value: Math.floor(Math.random() * 100), timestamp: Date.now(), action: ['click', 'view', 'purchase', 'login'][Math.floor(Math.random() * 4)] }, timestamp: new Date().toISOString() }; events.push(sampleEvent); randomStream.eventCount = (randomStream.eventCount || 0) + 1; // Keep only last 1000 events to prevent memory issues if (events.length > 1000) { events = events.slice(-1000); } } } }, 2000 + Math.random() * 3000); // Random interval between 2-5 seconds } // Start the server app.listen(PORT, () => { console.log('🚀 BigBaseAlpha Stream Processing Mock Server started'); console.log(`📊 Dashboard: http://localhost:${PORT}/dashboard`); console.log(`🌐 API Base URL: http://localhost:${PORT}/api`); console.log(`💡 Health Check: http://localhost:${PORT}/health`); console.log(''); console.log('📋 Available Endpoints:'); console.log(' GET /api/stream/analytics - Stream processing overview'); console.log(' GET /api/streams - List all streams'); console.log(' POST /api/streams - Create new stream'); console.log(' POST /api/streams/:id/publish - Publish event to stream'); console.log(' GET /api/processors - List all processors'); console.log(' POST /api/processors - Create stream processor'); console.log(' GET /api/analytics - List analytics'); console.log(' POST /api/analytics/aggregation - Create aggregation stream'); console.log(' GET /api/stream/performance - Get performance metrics'); console.log(' GET /api/stream/status - Get system status'); console.log(' POST /api/windows - Create window'); console.log(' POST /api/queries/continuous - Create continuous query'); console.log(' POST /api/joins - Create stream join'); console.log(''); // Start real-time event simulation simulateRealTimeEvents(); console.log('🔄 Real-time event simulation started'); }); module.exports = app;