const mongoose = require('mongoose'); const path = require('path'); const { Readable } = require('stream'); require('dotenv').config({ path: path.join(__dirname, '../.env') }); const Contract = require('../src/models/Contract'); const Clause = require('../src/models/Clause'); const QueueJob = require('../src/models/QueueJob'); const embeddingService = require('../src/services/embeddingService'); // Mock HuggingFace API for stress testing to avoid real HTTP network bottleneck limits embeddingService.generateEmbedding = async (text) => { return Array.from({ length: 384 }, () => Math.random()); }; async function runStressTest() { console.log('šŸš€ Starting Zero-Rupee Architecture Stress Test...\n'); await mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true, }); console.log('āœ… Connected to MongoDB\n'); const results = { gridFsStress: null, queueLockStress: null, ragStress: null }; try { // --------------------------------------------------------- // 1. GridFS Stress Test // --------------------------------------------------------- console.log('--- 1. GridFS Concurrent Upload Stress ---'); const bucket = new mongoose.mongo.GridFSBucket(mongoose.connection.db, { bucketName: 'contracts' }); const t0 = performance.now(); // Create 20 concurrent file uploads const uploadPromises = Array.from({ length: 20 }).map((_, i) => { return new Promise((resolve, reject) => { const dummyPdfContent = Buffer.from(`%PDF-1.4 Mock PDF Content ${i}`.repeat(1000)); const readable = new Readable(); readable.push(dummyPdfContent); readable.push(null); const uploadStream = bucket.openUploadStream(`stress_test_file_${i}.pdf`); readable.pipe(uploadStream) .on('error', reject) .on('finish', () => resolve(uploadStream.id)); }); }); const fileIds = await Promise.all(uploadPromises); const t1 = performance.now(); console.log(`āœ… Uploaded 20 files to GridFS in ${(t1 - t0).toFixed(2)}ms`); results.gridFsStress = `Passed: 20 concurrent uploads in ${(t1 - t0).toFixed(2)}ms`; // Cleanup GridFS await Promise.all(fileIds.map(id => bucket.delete(id).catch(() => {}))); // --------------------------------------------------------- // 2. Queue Lock Stress Test // --------------------------------------------------------- console.log('\n--- 2. Atomic Queue Lock Stress (Concurrency) ---'); const mockContractId = new mongoose.Types.ObjectId(); // Insert 50 jobs const jobsToInsert = Array.from({ length: 50 }).map(() => ({ contractId: mockContractId, status: 'queued' })); await QueueJob.insertMany(jobsToInsert); const t2 = performance.now(); let processedCount = 0; const workerIds = ['Worker-A', 'Worker-B', 'Worker-C', 'Worker-D', 'Worker-E']; // Simulate 5 workers aggressively polling at the exact same time const workerPromises = workerIds.map(async (workerId) => { let active = true; let localCount = 0; while (active) { const job = await QueueJob.findOneAndUpdate( { status: 'queued' }, { $set: { status: 'processing', lockedAt: new Date(), lockedBy: workerId } }, { sort: { createdAt: 1 }, new: true } ); if (job) { localCount++; // simulate minimal work await new Promise(r => setTimeout(r, 10)); await QueueJob.findByIdAndUpdate(job._id, { status: 'done', lockedAt: null, lockedBy: null }); } else { active = false; } } return { workerId, count: localCount }; }); const workerStats = await Promise.all(workerPromises); const t3 = performance.now(); processedCount = workerStats.reduce((acc, w) => acc + w.count, 0); console.log(`āœ… Processed ${processedCount} jobs across 5 concurrent workers in ${(t3 - t2).toFixed(2)}ms`); workerStats.forEach(w => console.log(` - ${w.workerId} processed ${w.count} jobs`)); if (processedCount === 50) { results.queueLockStress = `Passed: 50 jobs locked cleanly by 5 workers in ${(t3 - t2).toFixed(2)}ms`; } else { results.queueLockStress = `Failed: Data race occurred, processed ${processedCount}/50`; } // --------------------------------------------------------- // 3. Vector RAG Cosine Similarity Stress Test // --------------------------------------------------------- console.log('\n--- 3. Vector RAG Search Stress (Memory CPU) ---'); // Create 200 mock clauses (simulating a 100-page document) console.log('Generating 200 clauses with 384-dimensional vectors...'); const massiveClauses = Array.from({ length: 200 }).map((_, i) => ({ contractId: mockContractId, segmentIndex: i, rawText: `Clause ${i} containing some legal terminology about indemnification.`, embedding: Array.from({ length: 384 }, () => Math.random()) // Random 384d vector })); await Clause.insertMany(massiveClauses); const t4 = performance.now(); console.log('Executing 20 concurrent semantic RAG queries across 200 clauses...'); const ragPromises = Array.from({ length: 20 }).map(() => embeddingService.searchSimilarClauses(mockContractId, 'Find clauses related to indemnity', 5) ); await Promise.all(ragPromises); const t5 = performance.now(); console.log(`āœ… Completed 20 concurrent vector searches in ${(t5 - t4).toFixed(2)}ms`); results.ragStress = `Passed: 20 concurrent queries over 200 clauses in ${(t5 - t4).toFixed(2)}ms`; } catch (error) { console.error('āŒ Stress Test Error:', error); } finally { // Cleanup await Clause.deleteMany({ contractId: { $exists: false } }); await QueueJob.deleteMany({ status: 'done' }); await mongoose.connection.close(); console.log('\nšŸ“Š --- Stress Test Summary ---'); console.table(results); process.exit(0); } } runStressTest();