main.ts 3.48 KB
Newer Older
1
declare function require(name: string): any;
2

3
import { init as sentryInit } from '@sentry/node';
Fullarton's avatar
Fullarton committed
4
import * as http from 'http';
5
import { Server } from 'http';
6
import * as Minimist from 'minimist';
Fullarton's avatar
Fullarton committed
7
import * as process from 'process';
8
import 'reflect-metadata';
9
import App from './App';
10
import AssetDAO from './db/AssetDAO';
11 12 13 14
import CasDAO from './db/CasDAO';
import DbDAO from './db/DbDAO';
import I18nDAO from './db/I18nDAO';
import MathjaxDAO from './db/MathjaxDAO';
15 16 17 18
import MemberDAO from './db/MemberDAO';
import QuizDAO from './db/quiz/QuizDAO';
import UserDAO from './db/UserDAO';
import LoggerService from './services/LoggerService';
19
import { staticStatistics } from './statistics';
20
import { LoadTester } from './tests/LoadTester';
Fullarton's avatar
Fullarton committed
21

22
require('source-map-support').install();
23
require('./lib/regExpEscape'); // Installing polyfill for RegExp.escape
24

25 26
Error.stackTraceLimit = Infinity;

27 28 29
declare var global: any;
declare var module: any;

30 31 32 33 34
interface IHotModule extends NodeModule {
  hot: {
    accept: Function
  };
}
35

36
export interface IGlobal extends NodeJS.Global {
37
  DAO: {
38
    AssetDAO: {}, CasDAO: {}, I18nDAO: {}, MathjaxDAO: {}, QuizDAO: {}, DbDAO: {}, UserDAO: {}, MemberDAO: {},
39
  };
40 41
}

42
interface IInetAddress {
43 44 45 46 47
  port: number;
  family: string;
  address: string;
}

48
if (process.env.NODE_ENV === 'production') {
49
  sentryInit({ dsn: process.env.SENTRY_DSN });
50
}
51

52
(<IGlobal>global).DAO = {
53
  AssetDAO,
54 55 56
  CasDAO,
  I18nDAO,
  MathjaxDAO,
57
  QuizDAO,
58
  DbDAO,
59 60
  UserDAO,
  MemberDAO,
61
};
62

Fullarton's avatar
Fullarton committed
63 64 65
const port: string | number | boolean = normalizePort(staticStatistics.port);
App.set('port', port);

66 67
LoggerService.info(`Booting NodeJS ${process.version} on ${process.arch} architecture`);

Fullarton's avatar
Fullarton committed
68 69 70 71 72 73
const server: Server = http.createServer(App);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
server.on('close', onClose);

74 75 76 77 78
const argv = Minimist(process.argv.slice(2));
if (argv['load-test']) {
  runTest();
}

Fullarton's avatar
Fullarton committed
79
function normalizePort(val: number | string): number | string | boolean {
80
  const portCheck: number = (typeof val === 'string') ? parseInt(val, 10) : val;
Fullarton's avatar
Fullarton committed
81 82 83 84 85 86 87 88 89 90 91 92 93
  if (isNaN(portCheck)) {
    return val;
  } else if (portCheck >= 0) {
    return portCheck;
  } else {
    return false;
  }
}

function onError(error: NodeJS.ErrnoException): void {
  if (error.syscall !== 'listen') {
    throw error;
  }
94
  const bind: string = (typeof port === 'string') ? 'Pipe ' + port : 'Port ' + port;
Fullarton's avatar
Fullarton committed
95
  switch (error.code) {
96
    case 'EACCESS':
97
      LoggerService.error(`${bind} requires elevated privileges`);
Fullarton's avatar
Fullarton committed
98 99 100
      process.exit(1);
      break;
    case 'EADDRINUSE':
101
      LoggerService.error(`${bind} is already in use`);
Fullarton's avatar
Fullarton committed
102 103 104 105 106 107 108 109
      process.exit(1);
      break;
    default:
      throw error;
  }
}

function onListening(): void {
110
  const addr: IInetAddress | string = server.address();
111
  const bind: string = (typeof addr === 'string') ? `pipe ${addr}` : `port ${addr.port}`;
112
  LoggerService.info(`Listening on ${bind}`);
Fullarton's avatar
Fullarton committed
113

114 115 116
  I18nDAO.reloadCache().catch(reason => {
    console.error('Could not reload i18n dao cache', reason);
  });
Fullarton's avatar
Fullarton committed
117 118
}

119 120 121 122 123
function runTest(): void {
  console.log('----- Running Load Test -----');
  console.log(`CPU Time Spent Begin: ${process.cpuUsage().user / 1000000}`);
  const startTime = new Date().getTime();
  const loadTest = new LoadTester();
124 125 126 127 128
  loadTest.done.on('done', () => {
    console.log(`CPU Time Spent End: ${process.cpuUsage().user / 1000000}`);
    console.log(`Load Test took ${(new Date().getTime() - startTime) / 1000}`);
    console.log('----- Load Test Finished -----');
  });
129 130
}

131
function onClose(): void {}