Ctrl K
ComunidadGuías…

server.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// SPDX-License-Identifier: Apache-2.0
// Copyright 2024-present Scalytics, Inc. (https://www.scalytics.io)
// ──────────────────────────────────────────────────────────────────────────────
// Shim for all `node:`-prefixed core modules (events, buffer, etc.)
// ──────────────────────────────────────────────────────────────────────────────
const Module = require('module');
const _origLoad = Module._load;
Module._load = function(request, parent, isMain) {
  // if it's something like 'node:events' or 'node:buffer', strip the prefix
  if (request.startsWith('node:')) {
    request = request.slice(5);
  }
  return _origLoad(request, parent, isMain);
};
// ──────────────────────────────────────────────────────────────────────────────

const express = require('express');
const path = require('path');
const fs = require('fs');
const http = require('http');
const dotenv = require('dotenv');
const dbPath = path.join(__dirname, 'src', 'models', 'db.js');
if (!fs.existsSync(dbPath)) {
  console.error('ERROR: Database module not found at %s. Deployment issue?', dbPath);
  process.exit(1);
}

const { ensureSecureKeys } = require('./src/utils/securityUtils');
const { checkHuggingFaceDependencies } = require('./scripts/check_hf_dependencies');
const { loadSystemSettings } = require('./src/config/systemConfig'); 

// Configure llama.cpp shared library path (if exists)
const llamaBinDir = path.join(__dirname, 'bin', 'llama');
if (fs.existsSync(llamaBinDir)) {
  process.env.LD_LIBRARY_PATH = process.env.LD_LIBRARY_PATH
    ? `${llamaBinDir}:${process.env.LD_LIBRARY_PATH}`
    : llamaBinDir;
}

// Setup process-wide uncaught exception handlers
process.on('uncaughtException', (err) => {
  console.error('\n=====================================');
  console.error('UNCAUGHT EXCEPTION - SERVER CRASHING:', err);
  fs.appendFileSync('server-crash.log', `\n[${new Date().toISOString()}] UNCAUGHT EXCEPTION:\n${err.stack}\n`);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  console.error('\n=====================================');
  console.error('UNHANDLED PROMISE REJECTION:', reason);
  fs.appendFileSync('server-crash.log', `\n[${new Date().toISOString()}] UNHANDLED REJECTION:\n${reason}\n`);
});

// Load .env file but DO NOT override existing process.env variables (like those set by PM2)
dotenv.config({ override: false }); 

try {
  ensureSecureKeys();

  const app = express();
  const server = http.createServer(app);
  const PORT = process.env.PORT || 3000;

  // Set long timeouts to prevent premature socket closure for long-running SSE streams
  server.timeout = 600000; // 10 minutes
  server.headersTimeout = 600000; // 10 minutes

  const { initializeSocket } = require('./src/config/socket');
  const wsServer = initializeSocket(server);

  const { setupEventBusBridge } = require('./src/config/eventBusBridge');
  setupEventBusBridge(wsServer);

  app.set('wsServer', wsServer);


const { setupMiddleware, getFileUploadMiddleware } = require('./src/config/middleware');
const { protect } = require('./src/middleware/authMiddleware'); 
setupMiddleware(app); 

  const { setupRoutes } = require('./src/config/routes');
  setupRoutes(app, {
    fileUpload: getFileUploadMiddleware(),
    protect: protect
  });

  app.use((err, req, res, next) => {
    if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
      console.error('Malformed JSON received:', err.message);
      return res.status(400).json({ error: 'Malformed JSON payload.' });
    }

    if (err.type === 'entity.too.large' || (err.name === 'PayloadTooLargeError' || err.status === 413)) {
      console.warn("PayloadTooLargeError encountered for %s %s: %s",  String(req.method).replace(/\n|\r/g, ''), String(req.path).replace(/\n|\r/g, ''), err.message);
      const limit = err.limit ? `${(err.limit / 1024 / 1024).toFixed(2)} MB` : 'the configured limit';
      return res.status(413).json({
        error: 'Request payload is too large.',
        message: `The request body exceeds ${limit}.`
      });
    }

    console.error('Unhandled Express error:', err);
    if (!res.headersSent) {
       res.status(err.status || 500).json({ error: 'An unexpected server error occurred.' });
    }
  });


  async function startServer() {
    try {
      const { initializeServer } = require('./src/config/database');
      await initializeServer(); 

      await loadSystemSettings(); 
      if (process.env.SKIP_HF_CHECK !== 'true') {
        try {
          await checkHuggingFaceDependencies();
        } catch (hfError) {
          console.warn('Warning: Hugging Face dependency check failed:', hfError.message);
        }
      }

      if (process.env.SKIP_VLLM_SERVICE !== 'true') {
        try {
          const vllmService = require('./src/services/vllmService');
          if (typeof vllmService.initialize === 'function') {
            await vllmService.initialize();
          }
        } catch (vllmError) {
          console.warn('Warning: vLLM Service initialization failed:', vllmError.message);
        }
      }

      server.listen(PORT, () => {
      });
    } catch (error) {
      console.error('Failed to start server:', error); 
      fs.appendFileSync('server-crash.log', `\n[${new Date().toISOString()}] STARTUP ERROR:\n${error.stack}\n`);
      process.exit(1);
    }
  }

  startServer();

  const shutdown = (signal) => {
    server.close(async () => { 
      try {
        if (process.env.SKIP_VLLM_SERVICE !== 'true') {
          const vllmService = require('./src/services/vllmService');
          if (vllmService && typeof vllmService.shutdown === 'function') {
            await vllmService.shutdown();
          }
        }
        const { db } = require('./src/models/db'); 
        if (db && typeof db.close === 'function') {
          await new Promise((resolve, reject) => {
            db.close((err) => {
              if (err) {
                console.error('Error closing database:', err.message);
                reject(err);
              } else {
                resolve();
              }
            });
          });
        }
      } catch (dbCloseError) {
        console.error('Error accessing/closing database during shutdown:', dbCloseError);
      }
      process.exit(0); 
    });

    setTimeout(() => {
      console.error('Graceful shutdown timed out. Forcing exit.');
      process.exit(1);
    }, 10000); 
  };

  process.on('SIGTERM', () => shutdown('SIGTERM'));
  process.on('SIGINT', () => shutdown('SIGINT'));

} catch (initError) {
  console.error('Error during server initialization:', initError);
  fs.appendFileSync('server-crash.log', `\n[${new Date().toISOString()}] INITIALIZATION ERROR:\n${initError.stack}\n`);
  process.exit(1);
}